Merge tag 'davinci-fixes-for-v3.15-rc4' of git://git.kernel.org/pub/scm/linux/kernel...
[deliverable/linux.git] / drivers / staging / unisys / uislib / uislib.c
CommitLineData
bac8a4d5
KC
1/* uislib.c
2 *
3 * Copyright � 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/* @ALL_INSPECTED */
19#define EXPORT_SYMTAB
20#include <linux/kernel.h>
21#include <linux/highmem.h>
22#ifdef CONFIG_MODVERSIONS
23#include <config/modversions.h>
24#endif
25#include <linux/module.h>
26
27#include "commontypes.h"
28
29#include <linux/version.h>
30#include "uniklog.h"
31#include "diagnostics/appos_subsystems.h"
32#include "uisutils.h"
33#include "vbuschannel.h"
34
35#include <linux/proc_fs.h>
36#include <linux/uaccess.h> /* for copy_from_user */
37#include <linux/ctype.h> /* for toupper */
38#include <linux/list.h>
39
40#include "sparstop.h"
41#include "visorchipset.h"
42#include "chanstub.h"
43#include "version.h"
44#include "guestlinuxdebug.h"
45
46#define SET_PROC_OWNER(x, y)
47
48#define UISLIB_TEST_PROC
49#define POLLJIFFIES_NORMAL 1
50/* Choose whether or not you want to wakeup the request-polling thread
51 * after an IO termination:
52 * this is shorter than using __FILE__ (full path name) in
53 * debug/info/error messages
54 */
55#define CURRENT_FILE_PC UISLIB_PC_uislib_c
56#define __MYFILE__ "uislib.c"
57
58/* global function pointers that act as callback functions into virtpcimod */
59int (*VirtControlChanFunc)(struct guest_msgs *);
60
61static int ProcReadBufferValid;
62static char *ProcReadBuffer; /* Note this MUST be global,
63 * because the contents must */
64static unsigned int chipset_inited;
a8d7f21d 65
bac8a4d5
KC
66#define WAIT_ON_CALLBACK(handle) \
67 do { \
68 if (handle) \
69 break; \
70 UIS_THREAD_WAIT; \
71 } while (1)
72
73static struct bus_info *BusListHead;
74static rwlock_t BusListLock;
75static int BusListCount; /* number of buses in the list */
76static int MaxBusCount; /* maximum number of buses expected */
77static U64 PhysicalDataChan;
78static int PlatformNumber;
79
bac8a4d5
KC
80static struct uisthread_info Incoming_ThreadInfo;
81static BOOL Incoming_Thread_Started = FALSE;
a8d7f21d
KC
82static LIST_HEAD(List_Polling_Device_Channels);
83static unsigned long long tot_moved_to_tail_cnt;
84static unsigned long long tot_wait_cnt;
85static unsigned long long tot_wakeup_cnt;
86static unsigned long long tot_schedule_cnt;
87static int en_smart_wakeup = 1;
bac8a4d5 88static DEFINE_SEMAPHORE(Lock_Polling_Device_Channels); /* unlocked */
a8d7f21d 89static DECLARE_WAIT_QUEUE_HEAD(Wakeup_Polling_Device_Channels);
bac8a4d5
KC
90static int Go_Polling_Device_Channels;
91
92static struct proc_dir_entry *uislib_proc_dir;
93static struct proc_dir_entry *uislib_proc_vbus_dir;
94static struct proc_dir_entry *vnic_proc_entry; /* Used to be "datachan" */
95static struct proc_dir_entry *ctrlchan_proc_entry;
96static struct proc_dir_entry *pmem_proc_entry;
97static struct proc_dir_entry *info_proc_entry;
98static struct proc_dir_entry *switch_proc_entry;
99static struct proc_dir_entry *extport_proc_entry;
100static struct proc_dir_entry *platformnumber_proc_entry;
101static struct proc_dir_entry *bus_proc_entry;
102static struct proc_dir_entry *dev_proc_entry;
103static struct proc_dir_entry *chipset_proc_entry;
104static struct proc_dir_entry *cycles_before_wait_proc_entry;
105static struct proc_dir_entry *reset_counts_proc_entry;
106static struct proc_dir_entry *smart_wakeup_proc_entry;
107static struct proc_dir_entry *disable_proc_entry;
108
109#define DIR_PROC_ENTRY "uislib"
110#define DIR_VBUS_PROC_ENTRY "vbus"
111#define VNIC_PROC_ENTRY_FN "vnic" /* Used to be "datachan" */
112#define CTRLCHAN_PROC_ENTRY_FN "ctrlchan"
113#define PMEM_PROC_ENTRY_FN "phys_to_virt"
114#define INFO_PROC_ENTRY_FN "info"
115#define SWITCH_PROC_ENTRY_FN "switch"
116#define SWITCH_COUNT_PROC_ENTRY_FN "switch_count"
117#define EXTPORT_PROC_ENTRY_FN "extport"
118#define PLATFORMNUMBER_PROC_ENTRY_FN "platform"
119#define BUS_PROC_ENTRY_FN "bus"
120#define DEV_PROC_ENTRY_FN "device"
121#define CHIPSET_PROC_ENTRY_FN "chipset"
122#define CYCLES_BEFORE_WAIT_PROC_ENTRY_FN "cycles_before_wait"
123#define RESET_COUNTS_PROC_ENTRY_FN "reset_counts"
124#define SMART_WAKEUP_PROC_ENTRY_FN "smart_wakeup"
125#define CALLHOME_PROC_ENTRY_FN "callhome"
126#define CALLHOME_THROTTLED_PROC_ENTRY_FN "callhome_throttled"
127#define DISABLE_PROC_ENTRY_FN "switch_state"
128#ifdef UISLIB_TEST_PROC
129static struct proc_dir_entry *test_proc_entry;
130#define TEST_PROC_ENTRY_FN "test"
131#endif
a8d7f21d 132static unsigned long long cycles_before_wait, wait_cycles;
bac8a4d5
KC
133
134/*****************************************************/
135/* local functions */
136/*****************************************************/
137
138static int proc_info_vbus_show(struct seq_file *m, void *v);
139static int
140proc_info_vbus_open(struct inode *inode, struct file *filp)
141{
142 /* proc_info_vbus_show will grab this from seq_file.private: */
143 struct bus_info *bus = PDE_DATA(inode);
144 return single_open(filp, proc_info_vbus_show, bus);
145}
146
147static const struct file_operations proc_info_vbus_fops = {
148 .open = proc_info_vbus_open,
149 .read = seq_read,
150 .llseek = seq_lseek,
151 .release = single_release,
152};
153
154static ssize_t uislib_proc_read_writeonly(struct file *file,
155 char __user *buffer,
156 size_t count, loff_t *ppos);
157
158static ssize_t vnic_proc_write(struct file *file, const char __user *buffer,
159 size_t count, loff_t *ppos);
160
161static const struct file_operations proc_vnic_fops = {
162 .read = uislib_proc_read_writeonly,
163 .write = vnic_proc_write,
164};
165
166static ssize_t chipset_proc_write(struct file *file, const char __user *buffer,
167 size_t count, loff_t *ppos);
168
169static const struct file_operations proc_chipset_fops = {
170 .read = uislib_proc_read_writeonly,
171 .write = chipset_proc_write,
172};
173
174static ssize_t info_proc_read(struct file *file, char __user *buf,
175 size_t len, loff_t *offset);
176static const struct file_operations proc_info_fops = {
177 .read = info_proc_read,
178};
179
180static ssize_t platformnumber_proc_read(struct file *file, char __user *buf,
181 size_t len, loff_t *offset);
182static const struct file_operations proc_platformnumber_fops = {
183 .read = platformnumber_proc_read,
184};
185
186static ssize_t cycles_before_wait_proc_write(struct file *file,
187 const char __user *buffer,
188 size_t count, loff_t *ppos);
189static const struct file_operations proc_cycles_before_wait_fops = {
190 .read = uislib_proc_read_writeonly,
191 .write = cycles_before_wait_proc_write,
192};
193
194static ssize_t reset_counts_proc_write(struct file *file,
195 const char __user *buffer,
196 size_t count, loff_t *ppos);
197static const struct file_operations proc_reset_counts_fops = {
198 .read = uislib_proc_read_writeonly,
199 .write = reset_counts_proc_write,
200};
201
202static ssize_t smart_wakeup_proc_write(struct file *file,
203 const char __user *buffer,
204 size_t count, loff_t *ppos);
205static const struct file_operations proc_smart_wakeup_fops = {
206 .read = uislib_proc_read_writeonly,
207 .write = smart_wakeup_proc_write,
208};
209
210static ssize_t test_proc_write(struct file *file,
211 const char __user *buffer,
212 size_t count, loff_t *ppos);
213static const struct file_operations proc_test_fops = {
214 .read = uislib_proc_read_writeonly,
215 .write = test_proc_write,
216};
217
218static ssize_t bus_proc_write(struct file *file,
219 const char __user *buffer,
220 size_t count, loff_t *ppos);
221static const struct file_operations proc_bus_fops = {
222 .read = uislib_proc_read_writeonly,
223 .write = bus_proc_write,
224};
225
226static ssize_t dev_proc_write(struct file *file,
227 const char __user *buffer,
228 size_t count, loff_t *ppos);
229static const struct file_operations proc_dev_fops = {
230 .read = uislib_proc_read_writeonly,
231 .write = dev_proc_write,
232};
233
234static void
235init_msg_header(CONTROLVM_MESSAGE *msg, U32 id, uint rsp, uint svr)
236{
237 memset(msg, 0, sizeof(CONTROLVM_MESSAGE));
238 msg->hdr.Id = id;
239 msg->hdr.Flags.responseExpected = rsp;
240 msg->hdr.Flags.server = svr;
241}
242
243static void
244create_bus_proc_entries(struct bus_info *bus)
245{
246 bus->proc_dir = proc_mkdir(bus->name, uislib_proc_vbus_dir);
247 if (!bus->proc_dir) {
248 LOGERR("failed to create /proc/uislib/vbus/%s directory",
249 bus->name);
250 return;
251 }
252 bus->proc_info = proc_create_data("info", 0, bus->proc_dir,
253 &proc_info_vbus_fops, bus);
254 if (!bus->proc_info) {
255 LOGERR("failed to create /proc/uislib/vbus/%s/info", bus->name);
256 remove_proc_entry(bus->name, uislib_proc_vbus_dir);
257 bus->proc_dir = NULL;
258 return;
259 }
260 SET_PROC_OWNER(bus->proc_info, THIS_MODULE);
261
262}
263
a8d7f21d 264static __iomem void *
bac8a4d5
KC
265init_vbus_channel(U64 channelAddr, U32 channelBytes, int isServer)
266{
267 void *rc = NULL;
a8d7f21d 268 void __iomem *pChan = uislib_ioremap_cache(channelAddr, channelBytes);
bac8a4d5
KC
269 if (!pChan) {
270 LOGERR("CONTROLVM_BUS_CREATE error: ioremap_cache of channelAddr:%Lx for channelBytes:%llu failed",
271 (unsigned long long) channelAddr,
272 (unsigned long long) channelBytes);
d9355f89
KC
273 rc = NULL;
274 goto Away;
bac8a4d5
KC
275 }
276 if (isServer) {
a8d7f21d 277 memset_io(pChan, 0, channelBytes);
bac8a4d5
KC
278 if (!ULTRA_VBUS_CHANNEL_OK_SERVER(channelBytes, NULL)) {
279 ERRDRV("%s channel cannot be used", __func__);
280 uislib_iounmap(pChan);
d9355f89
KC
281 rc = NULL;
282 goto Away;
bac8a4d5
KC
283 }
284 ULTRA_VBUS_init_channel(pChan, channelBytes);
285 } else {
286 if (!ULTRA_VBUS_CHANNEL_OK_CLIENT(pChan, NULL)) {
287 ERRDRV("%s channel cannot be used", __func__);
288 uislib_iounmap(pChan);
d9355f89
KC
289 rc = NULL;
290 goto Away;
bac8a4d5
KC
291 }
292 }
d9355f89 293 rc = pChan;
bac8a4d5
KC
294Away:
295 return rc;
296}
297
298static int
299create_bus(CONTROLVM_MESSAGE *msg, char *buf)
300{
301 U32 busNo, deviceCount;
302 struct bus_info *tmp, *bus;
303 size_t size;
304
305 if (MaxBusCount == BusListCount) {
306 LOGERR("CONTROLVM_BUS_CREATE Failed: max buses:%d already created\n",
307 MaxBusCount);
308 POSTCODE_LINUX_3(BUS_CREATE_FAILURE_PC, MaxBusCount,
309 POSTCODE_SEVERITY_ERR);
310 return CONTROLVM_RESP_ERROR_MAX_BUSES;
311 }
312
313 busNo = msg->cmd.createBus.busNo;
314 deviceCount = msg->cmd.createBus.deviceCount;
315
316 POSTCODE_LINUX_4(BUS_CREATE_ENTRY_PC, busNo, deviceCount,
317 POSTCODE_SEVERITY_INFO);
318
319 size =
320 sizeof(struct bus_info) +
321 (deviceCount * sizeof(struct device_info *));
60140462 322 bus = kzalloc(size, GFP_ATOMIC);
bac8a4d5
KC
323 if (!bus) {
324 LOGERR("CONTROLVM_BUS_CREATE Failed: kmalloc for bus failed.\n");
325 POSTCODE_LINUX_3(BUS_CREATE_FAILURE_PC, busNo,
326 POSTCODE_SEVERITY_ERR);
327 return CONTROLVM_RESP_ERROR_KMALLOC_FAILED;
328 }
329
bac8a4d5
KC
330 /* Currently by default, the bus Number is the GuestHandle.
331 * Configure Bus message can override this.
332 */
333 if (msg->hdr.Flags.testMessage) {
334 /* This implies we're the IOVM so set guest handle to 0... */
335 bus->guestHandle = 0;
336 bus->busNo = busNo;
337 bus->localVnic = 1;
338 } else
339 bus->busNo = bus->guestHandle = busNo;
340 sprintf(bus->name, "%d", (int) bus->busNo);
341 bus->deviceCount = deviceCount;
342 bus->device =
343 (struct device_info **) ((char *) bus + sizeof(struct bus_info));
344 bus->busInstGuid = msg->cmd.createBus.busInstGuid;
345 bus->busChannelBytes = 0;
346 bus->pBusChannel = NULL;
347
348 /* add bus to our bus list - but check for duplicates first */
349 read_lock(&BusListLock);
350 for (tmp = BusListHead; tmp; tmp = tmp->next) {
351 if (tmp->busNo == bus->busNo)
352 break;
353 }
354 read_unlock(&BusListLock);
355 if (tmp) {
356 /* found a bus already in the list with same busNo -
357 * reject add
358 */
359 LOGERR("CONTROLVM_BUS_CREATE Failed: bus %d already exists.\n",
360 bus->busNo);
361 POSTCODE_LINUX_3(BUS_CREATE_FAILURE_PC, bus->busNo,
362 POSTCODE_SEVERITY_ERR);
60140462 363 kfree(bus);
bac8a4d5
KC
364 return CONTROLVM_RESP_ERROR_ALREADY_DONE;
365 }
366 if ((msg->cmd.createBus.channelAddr != 0)
367 && (msg->cmd.createBus.channelBytes != 0)) {
368 bus->busChannelBytes = msg->cmd.createBus.channelBytes;
369 bus->pBusChannel =
370 init_vbus_channel(msg->cmd.createBus.channelAddr,
371 msg->cmd.createBus.channelBytes,
372 msg->hdr.Flags.server);
373 }
374 /* the msg is bound for virtpci; send guest_msgs struct to callback */
375 if (!msg->hdr.Flags.server) {
376 struct guest_msgs cmd;
377 cmd.msgtype = GUEST_ADD_VBUS;
378 cmd.add_vbus.busNo = busNo;
379 cmd.add_vbus.chanptr = bus->pBusChannel;
380 cmd.add_vbus.deviceCount = deviceCount;
381 cmd.add_vbus.busTypeGuid = msg->cmd.createBus.busDataTypeGuid;
382 cmd.add_vbus.busInstGuid = msg->cmd.createBus.busInstGuid;
383 if (!VirtControlChanFunc) {
bac8a4d5
KC
384 LOGERR("CONTROLVM_BUS_CREATE Failed: virtpci callback not registered.");
385 POSTCODE_LINUX_3(BUS_CREATE_FAILURE_PC, bus->busNo,
386 POSTCODE_SEVERITY_ERR);
d21bb450 387 kfree(bus);
bac8a4d5
KC
388 return CONTROLVM_RESP_ERROR_VIRTPCI_DRIVER_FAILURE;
389 }
390 if (!VirtControlChanFunc(&cmd)) {
bac8a4d5
KC
391 LOGERR("CONTROLVM_BUS_CREATE Failed: virtpci GUEST_ADD_VBUS returned error.");
392 POSTCODE_LINUX_3(BUS_CREATE_FAILURE_PC, bus->busNo,
393 POSTCODE_SEVERITY_ERR);
d21bb450 394 kfree(bus);
bac8a4d5
KC
395 return
396 CONTROLVM_RESP_ERROR_VIRTPCI_DRIVER_CALLBACK_ERROR;
397 }
398 }
399 create_bus_proc_entries(bus);
400
401 /* add bus at the head of our list */
402 write_lock(&BusListLock);
403 if (!BusListHead)
404 BusListHead = bus;
405 else {
406 bus->next = BusListHead;
407 BusListHead = bus;
408 }
409 BusListCount++;
410 write_unlock(&BusListLock);
411
412 POSTCODE_LINUX_3(BUS_CREATE_EXIT_PC, bus->busNo,
413 POSTCODE_SEVERITY_INFO);
414 return CONTROLVM_RESP_SUCCESS;
415}
416
417static int
418destroy_bus(CONTROLVM_MESSAGE *msg, char *buf)
419{
420 int i;
421 struct bus_info *bus, *prev = NULL;
422 U32 busNo;
423
424 busNo = msg->cmd.destroyBus.busNo;
425
426 /* find and delete the bus */
427 read_lock(&BusListLock);
428 for (bus = BusListHead; bus; prev = bus, bus = bus->next) {
429 if (bus->busNo == busNo) {
430 /* found the bus - ensure that all device
431 * slots are NULL
432 */
433 for (i = 0; i < bus->deviceCount; i++) {
434 if (bus->device[i] != NULL) {
435 LOGERR("CONTROLVM_BUS_DESTROY Failed: device %i attached to bus %d.",
436 i, busNo);
437 read_unlock(&BusListLock);
438 return CONTROLVM_RESP_ERROR_BUS_DEVICE_ATTACHED;
439 }
440 }
441 read_unlock(&BusListLock);
442 /* the msg is bound for virtpci; send
443 * guest_msgs struct to callback
444 */
445 if (!msg->hdr.Flags.server) {
446 struct guest_msgs cmd;
447 cmd.msgtype = GUEST_DEL_VBUS;
448 cmd.del_vbus.busNo = busNo;
449 if (!VirtControlChanFunc) {
450 LOGERR("CONTROLVM_BUS_DESTROY Failed: virtpci callback not registered.");
451 return CONTROLVM_RESP_ERROR_VIRTPCI_DRIVER_FAILURE;
452 }
453 if (!VirtControlChanFunc(&cmd)) {
454 LOGERR("CONTROLVM_BUS_DESTROY Failed: virtpci GUEST_DEL_VBUS returned error.");
455 return CONTROLVM_RESP_ERROR_VIRTPCI_DRIVER_CALLBACK_ERROR;
456 }
457 }
458 /* remove the bus from the list */
459 write_lock(&BusListLock);
460 if (prev) /* not at head */
461 prev->next = bus->next;
462 else
463 BusListHead = bus->next;
464 BusListCount--;
465 write_unlock(&BusListLock);
466 break;
467 }
468 }
469
470 if (!bus) {
471 LOGERR("CONTROLVM_BUS_DESTROY Failed: failed to find bus %d.\n",
472 busNo);
473 read_unlock(&BusListLock);
474 return CONTROLVM_RESP_ERROR_ALREADY_DONE;
475 }
476 if (bus->proc_info) {
477 remove_proc_entry("info", bus->proc_dir);
478 bus->proc_info = NULL;
479 }
480 if (bus->proc_dir) {
481 remove_proc_entry(bus->name, uislib_proc_vbus_dir);
482 bus->proc_dir = NULL;
483 }
484 if (bus->pBusChannel) {
485 uislib_iounmap(bus->pBusChannel);
486 bus->pBusChannel = NULL;
487 }
488
60140462 489 kfree(bus);
bac8a4d5
KC
490 return CONTROLVM_RESP_SUCCESS;
491}
492
493static int
494create_device(CONTROLVM_MESSAGE *msg, char *buf)
495{
496 struct device_info *dev;
497 struct bus_info *bus;
498 U32 busNo, devNo;
499 int result = CONTROLVM_RESP_SUCCESS;
500 U64 minSize = MIN_IO_CHANNEL_SIZE;
501 ReqHandlerInfo_t *pReqHandler;
502
503 busNo = msg->cmd.createDevice.busNo;
504 devNo = msg->cmd.createDevice.devNo;
505
506 POSTCODE_LINUX_4(DEVICE_CREATE_ENTRY_PC, devNo, busNo,
507 POSTCODE_SEVERITY_INFO);
508
60140462 509 dev = kzalloc(sizeof(struct device_info), GFP_ATOMIC);
bac8a4d5
KC
510 if (!dev) {
511 LOGERR("CONTROLVM_DEVICE_CREATE Failed: kmalloc for dev failed.\n");
512 POSTCODE_LINUX_4(DEVICE_CREATE_FAILURE_PC, devNo, busNo,
513 POSTCODE_SEVERITY_ERR);
514 return CONTROLVM_RESP_ERROR_KMALLOC_FAILED;
515 }
516
bac8a4d5
KC
517 dev->channelTypeGuid = msg->cmd.createDevice.dataTypeGuid;
518 dev->intr = msg->cmd.createDevice.intr;
519 dev->channelAddr = msg->cmd.createDevice.channelAddr;
520 dev->busNo = busNo;
521 dev->devNo = devNo;
522 sema_init(&dev->interrupt_callback_lock, 1); /* unlocked */
523 sprintf(dev->devid, "vbus%u:dev%u", (unsigned) busNo, (unsigned) devNo);
524 /* map the channel memory for the device. */
525 if (msg->hdr.Flags.testMessage)
a8d7f21d 526 dev->chanptr = (void __iomem *)__va(dev->channelAddr);
bac8a4d5
KC
527 else {
528 pReqHandler = ReqHandlerFind(dev->channelTypeGuid);
529 if (pReqHandler)
530 /* generic service handler registered for this
531 * channel
532 */
533 minSize = pReqHandler->min_channel_bytes;
534 if (minSize > msg->cmd.createDevice.channelBytes) {
535 LOGERR("CONTROLVM_DEVICE_CREATE Failed: channel size is too small, channel size:0x%lx, required size:0x%lx",
536 (ulong) msg->cmd.createDevice.channelBytes,
537 (ulong) minSize);
538 POSTCODE_LINUX_4(DEVICE_CREATE_FAILURE_PC, devNo, busNo,
539 POSTCODE_SEVERITY_ERR);
540 result = CONTROLVM_RESP_ERROR_CHANNEL_SIZE_TOO_SMALL;
541 goto Away;
542 }
543 dev->chanptr =
544 uislib_ioremap_cache(dev->channelAddr,
545 msg->cmd.createDevice.channelBytes);
546 if (!dev->chanptr) {
547 LOGERR("CONTROLVM_DEVICE_CREATE Failed: ioremap_cache of channelAddr:%Lx for channelBytes:%llu failed",
548 dev->channelAddr,
549 msg->cmd.createDevice.channelBytes);
550 result = CONTROLVM_RESP_ERROR_IOREMAP_FAILED;
551 POSTCODE_LINUX_4(DEVICE_CREATE_FAILURE_PC, devNo, busNo,
552 POSTCODE_SEVERITY_ERR);
553 goto Away;
554 }
555 }
556 dev->devInstGuid = msg->cmd.createDevice.devInstGuid;
557 dev->channelBytes = msg->cmd.createDevice.channelBytes;
558
559 read_lock(&BusListLock);
560 for (bus = BusListHead; bus; bus = bus->next) {
561 if (bus->busNo == busNo) {
562 /* make sure the device number is valid */
563 if (devNo >= bus->deviceCount) {
564 LOGERR("CONTROLVM_DEVICE_CREATE Failed: device (%d) >= deviceCount (%d).",
565 devNo, bus->deviceCount);
566 result = CONTROLVM_RESP_ERROR_MAX_DEVICES;
567 POSTCODE_LINUX_4(DEVICE_CREATE_FAILURE_PC,
568 devNo, busNo,
569 POSTCODE_SEVERITY_ERR);
570 read_unlock(&BusListLock);
571 goto Away;
572 }
573 /* make sure this device is not already set */
574 if (bus->device[devNo]) {
575 LOGERR("CONTROLVM_DEVICE_CREATE Failed: device %d is already exists.",
576 devNo);
577 POSTCODE_LINUX_4(DEVICE_CREATE_FAILURE_PC,
578 devNo, busNo,
579 POSTCODE_SEVERITY_ERR);
580 result = CONTROLVM_RESP_ERROR_ALREADY_DONE;
581 read_unlock(&BusListLock);
582 goto Away;
583 }
584 read_unlock(&BusListLock);
585 /* the msg is bound for virtpci; send
586 * guest_msgs struct to callback
587 */
588 if (!msg->hdr.Flags.server) {
589 struct guest_msgs cmd;
590 if (!memcmp
591 (&dev->channelTypeGuid,
592 &UltraVhbaChannelProtocolGuid,
593 sizeof(GUID))) {
594 WAIT_FOR_VALID_GUID(((CHANNEL_HEADER
a8d7f21d 595 __iomem *) (dev->
bac8a4d5
KC
596 chanptr))->
597 Type);
598 if (!ULTRA_VHBA_CHANNEL_OK_CLIENT
599 (dev->chanptr, NULL)) {
600 LOGERR("CONTROLVM_DEVICE_CREATE Failed:[CLIENT]VHBA dev %d chan invalid.",
601 devNo);
602 POSTCODE_LINUX_4
603 (DEVICE_CREATE_FAILURE_PC,
604 devNo, busNo,
605 POSTCODE_SEVERITY_ERR);
606 result = CONTROLVM_RESP_ERROR_CHANNEL_INVALID;
607 goto Away;
608 }
609 cmd.msgtype = GUEST_ADD_VHBA;
610 cmd.add_vhba.chanptr = dev->chanptr;
611 cmd.add_vhba.busNo = busNo;
612 cmd.add_vhba.deviceNo = devNo;
613 cmd.add_vhba.devInstGuid =
614 dev->devInstGuid;
615 cmd.add_vhba.intr = dev->intr;
616 } else
617 if (!memcmp
618 (&dev->channelTypeGuid,
619 &UltraVnicChannelProtocolGuid,
620 sizeof(GUID))) {
621 WAIT_FOR_VALID_GUID(((CHANNEL_HEADER
a8d7f21d 622 __iomem *) (dev->
bac8a4d5
KC
623 chanptr))->
624 Type);
625 if (!ULTRA_VNIC_CHANNEL_OK_CLIENT
626 (dev->chanptr, NULL)) {
627 LOGERR("CONTROLVM_DEVICE_CREATE Failed: VNIC[CLIENT] dev %d chan invalid.",
628 devNo);
629 POSTCODE_LINUX_4
630 (DEVICE_CREATE_FAILURE_PC,
631 devNo, busNo,
632 POSTCODE_SEVERITY_ERR);
633 result = CONTROLVM_RESP_ERROR_CHANNEL_INVALID;
634 goto Away;
635 }
636 cmd.msgtype = GUEST_ADD_VNIC;
637 cmd.add_vnic.chanptr = dev->chanptr;
638 cmd.add_vnic.busNo = busNo;
639 cmd.add_vnic.deviceNo = devNo;
640 cmd.add_vnic.devInstGuid =
641 dev->devInstGuid;
642 cmd.add_vhba.intr = dev->intr;
643 } else {
644 LOGERR("CONTROLVM_DEVICE_CREATE Failed: unknown channelTypeGuid.\n");
645 POSTCODE_LINUX_4
646 (DEVICE_CREATE_FAILURE_PC, devNo,
647 busNo, POSTCODE_SEVERITY_ERR);
648 result = CONTROLVM_RESP_ERROR_CHANNEL_TYPE_UNKNOWN;
649 goto Away;
650 }
651
652 if (!VirtControlChanFunc) {
653 LOGERR("CONTROLVM_DEVICE_CREATE Failed: virtpci callback not registered.");
654 POSTCODE_LINUX_4
655 (DEVICE_CREATE_FAILURE_PC, devNo,
656 busNo, POSTCODE_SEVERITY_ERR);
657 result = CONTROLVM_RESP_ERROR_VIRTPCI_DRIVER_FAILURE;
658 goto Away;
659 }
660
661 if (!VirtControlChanFunc(&cmd)) {
662 LOGERR("CONTROLVM_DEVICE_CREATE Failed: virtpci GUEST_ADD_[VHBA||VNIC] returned error.");
663 POSTCODE_LINUX_4
664 (DEVICE_CREATE_FAILURE_PC, devNo,
665 busNo, POSTCODE_SEVERITY_ERR);
666 result = CONTROLVM_RESP_ERROR_VIRTPCI_DRIVER_CALLBACK_ERROR;
667 goto Away;
668 }
669 }
670 bus->device[devNo] = dev;
671 POSTCODE_LINUX_4(DEVICE_CREATE_SUCCESS_PC, devNo, busNo,
672 POSTCODE_SEVERITY_INFO);
673 return CONTROLVM_RESP_SUCCESS;
674 }
675 }
676 read_unlock(&BusListLock);
677
678 LOGERR("CONTROLVM_DEVICE_CREATE Failed: failed to find bus %d.", busNo);
679 POSTCODE_LINUX_4(DEVICE_CREATE_FAILURE_PC, devNo, busNo,
680 POSTCODE_SEVERITY_ERR);
681 result = CONTROLVM_RESP_ERROR_BUS_INVALID;
682
683Away:
684 if (!msg->hdr.Flags.testMessage) {
685 uislib_iounmap(dev->chanptr);
686 dev->chanptr = NULL;
687 }
688
60140462 689 kfree(dev);
bac8a4d5
KC
690 return result;
691}
692
693static int
694pause_device(CONTROLVM_MESSAGE *msg)
695{
696 U32 busNo, devNo;
697 struct bus_info *bus;
698 struct device_info *dev;
699 struct guest_msgs cmd;
700
701 busNo = msg->cmd.deviceChangeState.busNo;
702 devNo = msg->cmd.deviceChangeState.devNo;
703
704 read_lock(&BusListLock);
705 for (bus = BusListHead; bus; bus = bus->next) {
706 if (bus->busNo == busNo) {
707 /* make sure the device number is valid */
708 if (devNo >= bus->deviceCount) {
709 LOGERR("CONTROLVM_DEVICE_CHANGESTATE:pause Failed: device(%d) >= deviceCount(%d).",
710 devNo, bus->deviceCount);
711 read_unlock(&BusListLock);
712 return CONTROLVM_RESP_ERROR_DEVICE_INVALID;
713 }
714 /* make sure this device exists */
715 dev = bus->device[devNo];
716 if (!dev) {
717 LOGERR("CONTROLVM_DEVICE_CHANGESTATE:pause Failed: device %d does not exist.",
718 devNo);
719 read_unlock(&BusListLock);
720 return CONTROLVM_RESP_ERROR_ALREADY_DONE;
721 }
722 read_unlock(&BusListLock);
723 /* the msg is bound for virtpci; send
724 * guest_msgs struct to callback
725 */
726 if (!memcmp
727 (&dev->channelTypeGuid,
728 &UltraVhbaChannelProtocolGuid, sizeof(GUID))) {
729 cmd.msgtype = GUEST_PAUSE_VHBA;
730 cmd.pause_vhba.chanptr = dev->chanptr;
731 } else
732 if (!memcmp
733 (&dev->channelTypeGuid,
734 &UltraVnicChannelProtocolGuid,
735 sizeof(GUID))) {
736 cmd.msgtype = GUEST_PAUSE_VNIC;
737 cmd.pause_vnic.chanptr = dev->chanptr;
738 } else {
739 LOGERR("CONTROLVM_DEVICE_CHANGESTATE:pause Failed: unknown channelTypeGuid.\n");
740 return
741 CONTROLVM_RESP_ERROR_CHANNEL_TYPE_UNKNOWN;
742 }
743
744 if (!VirtControlChanFunc) {
745 LOGERR("CONTROLVM_DEVICE_CHANGESTATE Failed: virtpci callback not registered.");
746 return
747 CONTROLVM_RESP_ERROR_VIRTPCI_DRIVER_FAILURE;
748 }
749
750 if (!VirtControlChanFunc(&cmd)) {
751 LOGERR("CONTROLVM_DEVICE_CHANGESTATE:pause Failed: virtpci GUEST_PAUSE_[VHBA||VNIC] returned error.");
752 return CONTROLVM_RESP_ERROR_VIRTPCI_DRIVER_CALLBACK_ERROR;
753 }
754 break;
755 }
756 }
757
758 if (!bus) {
759 LOGERR("CONTROLVM_DEVICE_CHANGESTATE:pause Failed: bus %d does not exist",
760 busNo);
761 read_unlock(&BusListLock);
762 return CONTROLVM_RESP_ERROR_BUS_INVALID;
763 }
764
765 return CONTROLVM_RESP_SUCCESS;
766}
767
768static int
769resume_device(CONTROLVM_MESSAGE *msg)
770{
771 U32 busNo, devNo;
772 struct bus_info *bus;
773 struct device_info *dev;
774 struct guest_msgs cmd;
775
776 busNo = msg->cmd.deviceChangeState.busNo;
777 devNo = msg->cmd.deviceChangeState.devNo;
778
779 read_lock(&BusListLock);
780 for (bus = BusListHead; bus; bus = bus->next) {
781 if (bus->busNo == busNo) {
782 /* make sure the device number is valid */
783 if (devNo >= bus->deviceCount) {
784 LOGERR("CONTROLVM_DEVICE_CHANGESTATE:resume Failed: device(%d) >= deviceCount(%d).",
785 devNo, bus->deviceCount);
786 read_unlock(&BusListLock);
787 return CONTROLVM_RESP_ERROR_DEVICE_INVALID;
788 }
789 /* make sure this device exists */
790 dev = bus->device[devNo];
791 if (!dev) {
792 LOGERR("CONTROLVM_DEVICE_CHANGESTATE:resume Failed: device %d does not exist.",
793 devNo);
794 read_unlock(&BusListLock);
795 return CONTROLVM_RESP_ERROR_ALREADY_DONE;
796 }
797 read_unlock(&BusListLock);
798 /* the msg is bound for virtpci; send
799 * guest_msgs struct to callback
800 */
801 if (!memcmp(&dev->channelTypeGuid,
802 &UltraVhbaChannelProtocolGuid,
803 sizeof(GUID))) {
804 cmd.msgtype = GUEST_RESUME_VHBA;
805 cmd.resume_vhba.chanptr = dev->chanptr;
806 } else
807 if (!memcmp(&dev->channelTypeGuid,
808 &UltraVnicChannelProtocolGuid,
809 sizeof(GUID))) {
810 cmd.msgtype = GUEST_RESUME_VNIC;
811 cmd.resume_vnic.chanptr = dev->chanptr;
812 } else {
813 LOGERR("CONTROLVM_DEVICE_CHANGESTATE:resume Failed: unknown channelTypeGuid.\n");
814 return
815 CONTROLVM_RESP_ERROR_CHANNEL_TYPE_UNKNOWN;
816 }
817
818 if (!VirtControlChanFunc) {
819 LOGERR("CONTROLVM_DEVICE_CHANGESTATE Failed: virtpci callback not registered.");
820 return
821 CONTROLVM_RESP_ERROR_VIRTPCI_DRIVER_FAILURE;
822 }
823
824 if (!VirtControlChanFunc(&cmd)) {
825 LOGERR("CONTROLVM_DEVICE_CHANGESTATE:resume Failed: virtpci GUEST_RESUME_[VHBA||VNIC] returned error.");
826 return CONTROLVM_RESP_ERROR_VIRTPCI_DRIVER_CALLBACK_ERROR;
827 }
828 break;
829 }
830 }
831
832 if (!bus) {
833 LOGERR("CONTROLVM_DEVICE_CHANGESTATE:resume Failed: bus %d does not exist",
834 busNo);
835 read_unlock(&BusListLock);
836 return CONTROLVM_RESP_ERROR_BUS_INVALID;
837 }
838
839 return CONTROLVM_RESP_SUCCESS;
840}
841
842static int
843destroy_device(CONTROLVM_MESSAGE *msg, char *buf)
844{
845 U32 busNo, devNo;
846 struct bus_info *bus;
847 struct device_info *dev;
848 struct guest_msgs cmd;
849
850 busNo = msg->cmd.destroyDevice.busNo;
851 devNo = msg->cmd.destroyDevice.devNo;
852
853 read_lock(&BusListLock);
854 LOGINF("destroy_device called for busNo=%u, devNo=%u", busNo, devNo);
855 for (bus = BusListHead; bus; bus = bus->next) {
856 if (bus->busNo == busNo) {
857 /* make sure the device number is valid */
858 if (devNo >= bus->deviceCount) {
859 LOGERR("CONTROLVM_DEVICE_DESTORY Failed: device(%d) >= deviceCount(%d).",
860 devNo, bus->deviceCount);
861 read_unlock(&BusListLock);
862 return CONTROLVM_RESP_ERROR_DEVICE_INVALID;
863 }
864 /* make sure this device exists */
865 dev = bus->device[devNo];
866 if (!dev) {
867 LOGERR("CONTROLVM_DEVICE_DESTROY Failed: device %d does not exist.",
868 devNo);
869 read_unlock(&BusListLock);
870 return CONTROLVM_RESP_ERROR_ALREADY_DONE;
871 }
872 read_unlock(&BusListLock);
873 /* the msg is bound for virtpci; send
874 * guest_msgs struct to callback
875 */
876 if (!memcmp
877 (&dev->channelTypeGuid,
878 &UltraVhbaChannelProtocolGuid, sizeof(GUID))) {
879 cmd.msgtype = GUEST_DEL_VHBA;
880 cmd.del_vhba.chanptr = dev->chanptr;
881 } else
882 if (!memcmp
883 (&dev->channelTypeGuid,
884 &UltraVnicChannelProtocolGuid,
885 sizeof(GUID))) {
886 cmd.msgtype = GUEST_DEL_VNIC;
887 cmd.del_vnic.chanptr = dev->chanptr;
888 } else {
889 LOGERR("CONTROLVM_DEVICE_DESTROY Failed: unknown channelTypeGuid.\n");
890 return
891 CONTROLVM_RESP_ERROR_CHANNEL_TYPE_UNKNOWN;
892 }
893
894 if (!VirtControlChanFunc) {
895 LOGERR("CONTROLVM_DEVICE_DESTORY Failed: virtpci callback not registered.");
896 return
897 CONTROLVM_RESP_ERROR_VIRTPCI_DRIVER_FAILURE;
898 }
899
900 if (!VirtControlChanFunc(&cmd)) {
901 LOGERR("CONTROLVM_DEVICE_DESTROY Failed: virtpci GUEST_DEL_[VHBA||VNIC] returned error.");
902 return CONTROLVM_RESP_ERROR_VIRTPCI_DRIVER_CALLBACK_ERROR;
903 }
904/* you must disable channel interrupts BEFORE you unmap the channel,
905 * because if you unmap first, there may still be some activity going
906 * on which accesses the channel and you will get a "unable to handle
907 * kernel paging request"
908 */
909 if (dev->polling) {
910 LOGINF("calling uislib_disable_channel_interrupts");
911 uislib_disable_channel_interrupts(busNo, devNo);
912 }
913 /* unmap the channel memory for the device. */
914 if (!msg->hdr.Flags.testMessage) {
915 LOGINF("destroy_device, doing iounmap");
916 uislib_iounmap(dev->chanptr);
917 }
60140462 918 kfree(dev);
bac8a4d5
KC
919 bus->device[devNo] = NULL;
920 break;
921 }
922 }
923
924 if (!bus) {
925 LOGERR("CONTROLVM_DEVICE_DESTROY Failed: bus %d does not exist",
926 busNo);
927 read_unlock(&BusListLock);
928 return CONTROLVM_RESP_ERROR_BUS_INVALID;
929 }
930
931 return CONTROLVM_RESP_SUCCESS;
932}
933
bac8a4d5
KC
934static int
935init_chipset(CONTROLVM_MESSAGE *msg, char *buf)
936{
937 POSTCODE_LINUX_2(CHIPSET_INIT_ENTRY_PC, POSTCODE_SEVERITY_INFO);
938
939 MaxBusCount = msg->cmd.initChipset.busCount;
940 PlatformNumber = msg->cmd.initChipset.platformNumber;
941 PhysicalDataChan = 0;
942
943 /* We need to make sure we have our functions registered
944 * before processing messages. If we are a test vehicle the
945 * testMessage for init_chipset will be set. We can ignore the
946 * waits for the callbacks, since this will be manually entered
947 * from a user. If no testMessage is set, we will wait for the
948 * functions.
949 */
950 if (!msg->hdr.Flags.testMessage)
951 WAIT_ON_CALLBACK(VirtControlChanFunc);
952
953 chipset_inited = 1;
954 POSTCODE_LINUX_2(CHIPSET_INIT_EXIT_PC, POSTCODE_SEVERITY_INFO);
955
956 return CONTROLVM_RESP_SUCCESS;
957}
958
959static int
960stop_chipset(CONTROLVM_MESSAGE *msg, char *buf)
961{
962 /* Check that all buses and switches have been torn down and
963 * destroyed.
964 */
965 if (BusListHead) {
966 /* Buses still exist. */
967 LOGERR("CONTROLVM_CHIPSET_STOP: BusListHead is not NULL");
968 return CONTROLVM_RESP_ERROR_CHIPSET_STOP_FAILED_BUS;
969 }
970 if (BusListCount) {
971 /* BusListHead is NULL, but BusListCount != 0 */
972 LOGERR("CONTROLVM_CHIPSET_STOP: BusListCount != 0");
973 return CONTROLVM_RESP_ERROR_CHIPSET_STOP_FAILED_BUS;
974 }
975
976 /* Buses are shut down. */
977 return visorchipset_chipset_notready();
978}
979
980static int
981delete_bus_glue(U32 busNo)
982{
983 CONTROLVM_MESSAGE msg;
984
985 init_msg_header(&msg, CONTROLVM_BUS_DESTROY, 0, 0);
986 msg.cmd.destroyBus.busNo = busNo;
987 if (destroy_bus(&msg, NULL) != CONTROLVM_RESP_SUCCESS) {
988 LOGERR("destroy_bus failed. busNo=0x%x\n", busNo);
989 return 0;
990 }
991 return 1;
992}
993
994static int
995delete_device_glue(U32 busNo, U32 devNo)
996{
997 CONTROLVM_MESSAGE msg;
998
999 init_msg_header(&msg, CONTROLVM_DEVICE_DESTROY, 0, 0);
1000 msg.cmd.destroyDevice.busNo = busNo;
1001 msg.cmd.destroyDevice.devNo = devNo;
1002 if (destroy_device(&msg, NULL) != CONTROLVM_RESP_SUCCESS) {
1003 LOGERR("destroy_device failed. busNo=0x%x devNo=0x%x\n", busNo,
1004 devNo);
1005 return 0;
1006 }
1007 return 1;
1008}
1009
1010int
1011uislib_client_inject_add_bus(U32 busNo, GUID instGuid,
1012 U64 channelAddr, ulong nChannelBytes)
1013{
1014 CONTROLVM_MESSAGE msg;
1015
1016 LOGINF("enter busNo=0x%x\n", busNo);
1017 /* step 0: init the chipset */
1018 POSTCODE_LINUX_3(CHIPSET_INIT_ENTRY_PC, busNo, POSTCODE_SEVERITY_INFO);
1019
1020 if (!chipset_inited) {
1021 /* step: initialize the chipset */
1022 init_msg_header(&msg, CONTROLVM_CHIPSET_INIT, 0, 0);
1023 /* this change is needed so that console will come up
1024 * OK even when the bus 0 create comes in late. If the
1025 * bus 0 create is the first create, then the add_vnic
1026 * will work fine, but if the bus 0 create arrives
1027 * after number 4, then the add_vnic will fail, and the
1028 * ultraboot will fail.
1029 */
1030 msg.cmd.initChipset.busCount = 23;
1031 msg.cmd.initChipset.switchCount = 0;
1032 if (init_chipset(&msg, NULL) != CONTROLVM_RESP_SUCCESS) {
1033 LOGERR("init_chipset failed.\n");
1034 return 0;
1035 }
1036 LOGINF("chipset initialized\n");
1037 POSTCODE_LINUX_3(CHIPSET_INIT_EXIT_PC, busNo,
1038 POSTCODE_SEVERITY_INFO);
1039 }
1040
1041 /* step 1: create a bus */
1042 POSTCODE_LINUX_3(BUS_CREATE_ENTRY_PC, busNo, POSTCODE_SEVERITY_WARNING);
1043 init_msg_header(&msg, CONTROLVM_BUS_CREATE, 0, 0);
1044 msg.cmd.createBus.busNo = busNo;
1045 msg.cmd.createBus.deviceCount = 23; /* devNo+1; */
1046 msg.cmd.createBus.channelAddr = channelAddr;
1047 msg.cmd.createBus.channelBytes = nChannelBytes;
1048 if (create_bus(&msg, NULL) != CONTROLVM_RESP_SUCCESS) {
1049 LOGERR("create_bus failed.\n");
1050 POSTCODE_LINUX_3(BUS_CREATE_FAILURE_PC, busNo,
1051 POSTCODE_SEVERITY_ERR);
1052 return 0;
1053 }
1054 POSTCODE_LINUX_3(BUS_CREATE_EXIT_PC, busNo, POSTCODE_SEVERITY_INFO);
1055
1056 return 1;
1057}
1058EXPORT_SYMBOL_GPL(uislib_client_inject_add_bus);
1059
1060
1061int
1062uislib_client_inject_del_bus(U32 busNo)
1063{
1064 return delete_bus_glue(busNo);
1065}
1066EXPORT_SYMBOL_GPL(uislib_client_inject_del_bus);
1067
1068int
1069uislib_client_inject_pause_vhba(U32 busNo, U32 devNo)
1070{
1071 CONTROLVM_MESSAGE msg;
1072 int rc;
1073
1074 init_msg_header(&msg, CONTROLVM_DEVICE_CHANGESTATE, 0, 0);
1075 msg.cmd.deviceChangeState.busNo = busNo;
1076 msg.cmd.deviceChangeState.devNo = devNo;
1077 msg.cmd.deviceChangeState.state = SegmentStateStandby;
1078 rc = pause_device(&msg);
1079 if (rc != CONTROLVM_RESP_SUCCESS) {
1080 LOGERR("VHBA pause_device failed. busNo=0x%x devNo=0x%x\n",
1081 busNo, devNo);
1082 return rc;
1083 }
1084 return 0;
1085}
1086EXPORT_SYMBOL_GPL(uislib_client_inject_pause_vhba);
1087
1088int
1089uislib_client_inject_resume_vhba(U32 busNo, U32 devNo)
1090{
1091 CONTROLVM_MESSAGE msg;
1092 int rc;
1093
1094 init_msg_header(&msg, CONTROLVM_DEVICE_CHANGESTATE, 0, 0);
1095 msg.cmd.deviceChangeState.busNo = busNo;
1096 msg.cmd.deviceChangeState.devNo = devNo;
1097 msg.cmd.deviceChangeState.state = SegmentStateRunning;
1098 rc = resume_device(&msg);
1099 if (rc != CONTROLVM_RESP_SUCCESS) {
1100 LOGERR("VHBA resume_device failed. busNo=0x%x devNo=0x%x\n",
1101 busNo, devNo);
1102 return rc;
1103 }
1104 return 0;
1105
1106}
1107EXPORT_SYMBOL_GPL(uislib_client_inject_resume_vhba);
1108
1109int
1110uislib_client_inject_add_vhba(U32 busNo, U32 devNo,
1111 U64 phys_chan_addr, U32 chan_bytes,
1112 int is_test_addr, GUID instGuid,
1113 struct InterruptInfo *intr)
1114{
1115 CONTROLVM_MESSAGE msg;
1116
1117 LOGINF(" enter busNo=0x%x devNo=0x%x\n", busNo, devNo);
1118 /* chipset init'ed with bus bus has been previously created -
1119 * Verify it still exists step 2: create the VHBA device on the
1120 * bus
1121 */
1122 POSTCODE_LINUX_4(VHBA_CREATE_ENTRY_PC, devNo, busNo,
1123 POSTCODE_SEVERITY_INFO);
1124
1125 init_msg_header(&msg, CONTROLVM_DEVICE_CREATE, 0, 0);
1126 if (is_test_addr)
1127 /* signify that the physical channel address does NOT
1128 * need to be ioremap()ed
1129 */
1130 msg.hdr.Flags.testMessage = 1;
1131 msg.cmd.createDevice.busNo = busNo;
1132 msg.cmd.createDevice.devNo = devNo;
1133 msg.cmd.createDevice.devInstGuid = instGuid;
1134 if (intr)
1135 msg.cmd.createDevice.intr = *intr;
1136 else
1137 memset(&msg.cmd.createDevice.intr, 0,
1138 sizeof(struct InterruptInfo));
1139 msg.cmd.createDevice.channelAddr = phys_chan_addr;
1140 if (chan_bytes < MIN_IO_CHANNEL_SIZE) {
1141 LOGERR("wrong channel size.chan_bytes = 0x%x IO_CHANNEL_SIZE= 0x%x\n",
1142 chan_bytes, (unsigned int) MIN_IO_CHANNEL_SIZE);
1143 POSTCODE_LINUX_4(VHBA_CREATE_FAILURE_PC, chan_bytes,
1144 MIN_IO_CHANNEL_SIZE, POSTCODE_SEVERITY_ERR);
1145 return 0;
1146 }
1147 msg.cmd.createDevice.channelBytes = chan_bytes;
1148 msg.cmd.createDevice.dataTypeGuid = UltraVhbaChannelProtocolGuid;
1149 if (create_device(&msg, NULL) != CONTROLVM_RESP_SUCCESS) {
1150 LOGERR("VHBA create_device failed.\n");
1151 POSTCODE_LINUX_4(VHBA_CREATE_FAILURE_PC, devNo, busNo,
1152 POSTCODE_SEVERITY_ERR);
1153 return 0;
1154 }
1155 POSTCODE_LINUX_4(VHBA_CREATE_SUCCESS_PC, devNo, busNo,
1156 POSTCODE_SEVERITY_INFO);
1157 return 1;
1158}
1159EXPORT_SYMBOL_GPL(uislib_client_inject_add_vhba);
1160
1161int
1162uislib_client_inject_del_vhba(U32 busNo, U32 devNo)
1163{
1164 return delete_device_glue(busNo, devNo);
1165}
1166EXPORT_SYMBOL_GPL(uislib_client_inject_del_vhba);
1167
1168int
1169uislib_client_inject_add_vnic(U32 busNo, U32 devNo,
1170 U64 phys_chan_addr, U32 chan_bytes,
1171 int is_test_addr, GUID instGuid,
1172 struct InterruptInfo *intr)
1173{
1174 CONTROLVM_MESSAGE msg;
1175
1176 LOGINF(" enter busNo=0x%x devNo=0x%x\n", busNo, devNo);
1177 /* chipset init'ed with bus bus has been previously created -
1178 * Verify it still exists step 2: create the VNIC device on the
1179 * bus
1180 */
1181 POSTCODE_LINUX_4(VNIC_CREATE_ENTRY_PC, devNo, busNo,
1182 POSTCODE_SEVERITY_INFO);
1183
1184 init_msg_header(&msg, CONTROLVM_DEVICE_CREATE, 0, 0);
1185 if (is_test_addr)
1186 /* signify that the physical channel address does NOT
1187 * need to be ioremap()ed
1188 */
1189 msg.hdr.Flags.testMessage = 1;
1190 msg.cmd.createDevice.busNo = busNo;
1191 msg.cmd.createDevice.devNo = devNo;
1192 msg.cmd.createDevice.devInstGuid = instGuid;
1193 if (intr)
1194 msg.cmd.createDevice.intr = *intr;
1195 else
1196 memset(&msg.cmd.createDevice.intr, 0,
1197 sizeof(struct InterruptInfo));
1198 msg.cmd.createDevice.channelAddr = phys_chan_addr;
1199 if (chan_bytes < MIN_IO_CHANNEL_SIZE) {
1200 LOGERR("wrong channel size.chan_bytes = 0x%x IO_CHANNEL_SIZE= 0x%x\n",
1201 chan_bytes, (unsigned int) MIN_IO_CHANNEL_SIZE);
1202 POSTCODE_LINUX_4(VNIC_CREATE_FAILURE_PC, chan_bytes,
1203 MIN_IO_CHANNEL_SIZE, POSTCODE_SEVERITY_ERR);
1204 return 0;
1205 }
1206 msg.cmd.createDevice.channelBytes = chan_bytes;
1207 msg.cmd.createDevice.dataTypeGuid = UltraVnicChannelProtocolGuid;
1208 if (create_device(&msg, NULL) != CONTROLVM_RESP_SUCCESS) {
1209 LOGERR("VNIC create_device failed.\n");
1210 POSTCODE_LINUX_4(VNIC_CREATE_FAILURE_PC, devNo, busNo,
1211 POSTCODE_SEVERITY_ERR);
1212 return 0;
1213 }
1214
1215 POSTCODE_LINUX_4(VNIC_CREATE_SUCCESS_PC, devNo, busNo,
1216 POSTCODE_SEVERITY_INFO);
1217 return 1;
1218}
1219EXPORT_SYMBOL_GPL(uislib_client_inject_add_vnic);
1220
1221int
1222uislib_client_inject_pause_vnic(U32 busNo, U32 devNo)
1223{
1224 CONTROLVM_MESSAGE msg;
1225 int rc;
1226
1227 init_msg_header(&msg, CONTROLVM_DEVICE_CHANGESTATE, 0, 0);
1228 msg.cmd.deviceChangeState.busNo = busNo;
1229 msg.cmd.deviceChangeState.devNo = devNo;
1230 msg.cmd.deviceChangeState.state = SegmentStateStandby;
1231 rc = pause_device(&msg);
1232 if (rc != CONTROLVM_RESP_SUCCESS) {
1233 LOGERR("VNIC pause_device failed. busNo=0x%x devNo=0x%x\n",
1234 busNo, devNo);
1235 return -1;
1236 }
1237 return 0;
1238}
1239EXPORT_SYMBOL_GPL(uislib_client_inject_pause_vnic);
1240
1241int
1242uislib_client_inject_resume_vnic(U32 busNo, U32 devNo)
1243{
1244 CONTROLVM_MESSAGE msg;
1245 int rc;
1246
1247 init_msg_header(&msg, CONTROLVM_DEVICE_CHANGESTATE, 0, 0);
1248 msg.cmd.deviceChangeState.busNo = busNo;
1249 msg.cmd.deviceChangeState.devNo = devNo;
1250 msg.cmd.deviceChangeState.state = SegmentStateRunning;
1251 rc = resume_device(&msg);
1252 if (rc != CONTROLVM_RESP_SUCCESS) {
1253 LOGERR("VNIC resume_device failed. busNo=0x%x devNo=0x%x\n",
1254 busNo, devNo);
1255 return -1;
1256 }
1257 return 0;
1258
1259}
1260EXPORT_SYMBOL_GPL(uislib_client_inject_resume_vnic);
1261
1262int
1263uislib_client_inject_del_vnic(U32 busNo, U32 devNo)
1264{
1265 return delete_device_glue(busNo, devNo);
1266}
1267EXPORT_SYMBOL_GPL(uislib_client_inject_del_vnic);
1268
a8d7f21d 1269static int
bac8a4d5
KC
1270uislib_client_add_vnic(U32 busNo)
1271{
1272 BOOL busCreated = FALSE;
1273 int devNo = 0; /* Default to 0, since only one device
1274 * will be created for this bus... */
1275 GUID dummyGuid = GUID0;
1276 CONTROLVM_MESSAGE msg;
1277
1278 init_msg_header(&msg, CONTROLVM_BUS_CREATE, 0, 0);
1279 msg.hdr.Flags.testMessage = 1;
1280 msg.cmd.createBus.busNo = busNo;
1281 msg.cmd.createBus.deviceCount = 4;
1282 msg.cmd.createBus.channelAddr = 0;
1283 msg.cmd.createBus.channelBytes = 0;
1284 if (create_bus(&msg, NULL) != CONTROLVM_RESP_SUCCESS) {
1285 LOGERR("client create_bus failed");
1286 return 0;
1287 }
1288 busCreated = TRUE;
1289
1290 init_msg_header(&msg, CONTROLVM_DEVICE_CREATE, 0, 0);
1291 msg.hdr.Flags.testMessage = 1;
1292 msg.cmd.createDevice.busNo = busNo;
1293 msg.cmd.createDevice.devNo = devNo;
1294 msg.cmd.createDevice.devInstGuid = dummyGuid;
1295 memset(&msg.cmd.createDevice.intr, 0, sizeof(struct InterruptInfo));
1296 msg.cmd.createDevice.channelAddr = PhysicalDataChan;
1297 msg.cmd.createDevice.channelBytes = MIN_IO_CHANNEL_SIZE;
1298 msg.cmd.createDevice.dataTypeGuid = UltraVnicChannelProtocolGuid;
1299 if (create_device(&msg, NULL) != CONTROLVM_RESP_SUCCESS) {
1300 LOGERR("client create_device failed");
1301 goto AwayCleanup;
1302 }
1303
1304 return 1;
1305
1306AwayCleanup:
1307 if (busCreated) {
1308 init_msg_header(&msg, CONTROLVM_BUS_DESTROY, 0, 0);
1309 msg.hdr.Flags.testMessage = 1;
1310 msg.cmd.destroyBus.busNo = busNo;
1311 if (destroy_bus(&msg, NULL) != CONTROLVM_RESP_SUCCESS)
1312 LOGERR("client destroy_bus failed.\n");
1313 }
1314
1315 return 0;
1316} /* end uislib_client_add_vnic */
1317EXPORT_SYMBOL_GPL(uislib_client_add_vnic);
1318
a8d7f21d 1319static int
bac8a4d5
KC
1320uislib_client_delete_vnic(U32 busNo)
1321{
1322 int devNo = 0; /* Default to 0, since only one device
1323 * will be created for this bus... */
1324 CONTROLVM_MESSAGE msg;
1325
1326 init_msg_header(&msg, CONTROLVM_DEVICE_DESTROY, 0, 0);
1327 msg.hdr.Flags.testMessage = 1;
1328 msg.cmd.destroyDevice.busNo = busNo;
1329 msg.cmd.destroyDevice.devNo = devNo;
1330 if (destroy_device(&msg, NULL) != CONTROLVM_RESP_SUCCESS) {
1331 /* Don't error exit - try to see if bus can be destroyed... */
1332 LOGERR("client destroy_device failed.\n");
1333 }
1334
1335 init_msg_header(&msg, CONTROLVM_BUS_DESTROY, 0, 0);
1336 msg.hdr.Flags.testMessage = 1;
1337 msg.cmd.destroyBus.busNo = busNo;
1338 if (destroy_bus(&msg, NULL) != CONTROLVM_RESP_SUCCESS)
1339 LOGERR("client destroy_bus failed.\n");
1340
1341 return 1;
1342}
1343EXPORT_SYMBOL_GPL(uislib_client_delete_vnic);
60140462 1344/* end client_delete_vnic */
bac8a4d5
KC
1345
1346void *
1347uislib_cache_alloc(struct kmem_cache *cur_pool, char *fn, int ln)
1348{
1349 /* __GFP_NORETRY means "ok to fail", meaning kmalloc() can
1350 * return NULL. If you do NOT specify __GFP_NORETRY, Linux
1351 * will go to extreme measures to get memory for you (like,
1352 * invoke oom killer), which will probably cripple the system.
1353 */
1354 void *p = kmem_cache_alloc(cur_pool, GFP_ATOMIC | __GFP_NORETRY);
1355 if (p == NULL) {
1356 LOGERR("uislib_malloc failed to alloc uiscmdrsp @%s:%d",
1357 fn, ln);
1358 return NULL;
1359 }
1360 return p;
1361}
1362EXPORT_SYMBOL_GPL(uislib_cache_alloc);
1363
1364void
1365uislib_cache_free(struct kmem_cache *cur_pool, void *p, char *fn, int ln)
1366{
1367 if (p == NULL) {
1368 LOGERR("uislib_free NULL pointer @%s:%d", fn, ln);
1369 return;
1370 }
1371 kmem_cache_free(cur_pool, p);
1372}
1373EXPORT_SYMBOL_GPL(uislib_cache_free);
1374
1375/*****************************************************/
1376/* proc filesystem callback functions */
1377/*****************************************************/
1378
1379static ssize_t
1380vnic_proc_write(struct file *file, const char __user *buffer,
1381 size_t count, loff_t *ppos)
1382{
1383 int action = 0xffff, busNo = 0, i, result = 0;
61a0bc0f 1384 char buf[4];
bac8a4d5
KC
1385 char direction;
1386/* GUID guid; */
61a0bc0f
KC
1387 if (count >= ARRAY_SIZE(buf))
1388 return -EINVAL;
1389
bac8a4d5
KC
1390 if (copy_from_user(buf, buffer, count)) {
1391 LOGERR("echo > /proc/uislib/vnic copy_from_user ****FAILED.\n");
1392 return -EFAULT;
1393 }
1394
1395 i = sscanf(buf, "%d%c", &action, &direction);
1396 if (i != 2) {
1397 LOGERR("unable to parse vnic proc parameters.\n");
1398 return -EFAULT;
1399 }
1400
1401 if ((direction != '-') && (direction != '+')) {
1402 LOGERR("unable to determine whether to add or delete vnic\n");
1403 return -EFAULT;
1404 }
1405
1406 /* if (i < 1), i.e., if we didn't even read the action field,
1407 * then action will default to 0xffff and the code below will
1408 * fall through the switch and print usage.
1409 */
1410 switch (action) {
1411 case 0:
1412 /* call client method... */
1413 busNo = 0; /* All client drivers use bus value of 0... */
1414 if (direction == '+')
1415 result = uislib_client_add_vnic(busNo);
1416 else
1417 result = uislib_client_delete_vnic(busNo);
1418 if (!result) {
1419 LOGERR("echo 0%c > /proc/uislib/vnic failed (client end)",
1420 direction);
1421 return -EFAULT;
1422 }
1423 return count;
1424
1425 default:
1426 break;
1427 }
1428
1429 LOGERR("USAGE: echo <action><direction (up/down)> > /proc/uislib/vnic");
1430 LOGERR(" ");
1431 LOGERR("Client Syntax");
1432 LOGERR("-------------");
1433 LOGERR("0+ ==> add vnic");
1434 LOGERR("0- ==> delete vnic");
1435 LOGERR(" ");
1436 return count;
1437} /* end vnic_proc_write */
1438
1439static ssize_t
1440chipset_proc_write(struct file *file, const char __user *buffer,
1441 size_t count, loff_t *ppos)
1442{
1443 int i, action = 0xffff;
61a0bc0f 1444 char buf[4];
bac8a4d5
KC
1445 CONTROLVM_MESSAGE msg;
1446
61a0bc0f
KC
1447 if (count >= ARRAY_SIZE(buf))
1448 return -EINVAL;
1449
bac8a4d5
KC
1450 memset(&msg, 0, sizeof(CONTROLVM_MESSAGE));
1451
1452 if (copy_from_user(buf, buffer, count)) {
1453 LOGERR("copy_from_user ****FAILED.\n");
1454 return -EFAULT;
1455 }
1456
1457 if (chipset_inited) {
1458 LOGINF("Chipset already initialized\n");
1459 return -EFAULT;
1460 }
1461 i = sscanf(buf, "%x", &action);
1462
1463 /* if (i < 1), i.e., if we didn't even read the action field,
1464 * then action will default to 0xffff and the code below will
1465 * fall through the switch and print usage.
1466 */
1467 switch (action) {
1468 case 1:
1469 /* GUEST */
1470 /* step: initialize the chipset */
1471 init_msg_header(&msg, CONTROLVM_CHIPSET_INIT, 0, 0);
1472 msg.hdr.Flags.testMessage = 0;
1473 msg.cmd.initChipset.busCount = 23;
1474 msg.cmd.initChipset.switchCount = 23;
1475
1476 if (init_chipset(&msg, NULL) != CONTROLVM_RESP_SUCCESS) {
1477 LOGERR("init_chipset failed.\n");
1478 return 0;
1479 }
1480 return 1;
1481 case 2:
1482 /* BOTH */
1483 init_msg_header(&msg, CONTROLVM_CHIPSET_INIT, 0, 0);
1484 msg.hdr.Flags.testMessage = 1;
1485 msg.cmd.initChipset.busCount = 23;
1486 msg.cmd.initChipset.switchCount = 23;
1487
1488 if (init_chipset(&msg, NULL) != CONTROLVM_RESP_SUCCESS) {
1489 LOGERR("init_chipset failed.\n");
1490 return 0;
1491 }
1492 return 1;
1493
1494 default:
1495 break;
1496 }
1497
1498 LOGERR("usage: 1 ==> init_chipset client\n");
1499 LOGERR("usage: 2 ==> init_chipset test\n");
1500 return -EFAULT;
1501}
1502
27dd5548
KC
1503#define PLINE(...) uisutil_add_proc_line_ex(&tot, buff, \
1504 buff_len, __VA_ARGS__)
bac8a4d5
KC
1505
1506static int
1507info_proc_read_helper(char **buff, int *buff_len)
1508{
1509 int i, tot = 0;
1510 struct bus_info *bus;
1511
27dd5548
KC
1512 if (PLINE("\nBuses:\n") < 0)
1513 goto err_done;
bac8a4d5
KC
1514
1515 read_lock(&BusListLock);
1516 for (bus = BusListHead; bus; bus = bus->next) {
1517
27dd5548
KC
1518 if (PLINE(" bus=0x%p, busNo=%d, deviceCount=%d\n",
1519 bus, bus->busNo, bus->deviceCount) < 0)
1520 goto err_done_unlock;
bac8a4d5 1521
27dd5548
KC
1522
1523 if (PLINE(" Devices:\n") < 0)
1524 goto err_done_unlock;
bac8a4d5
KC
1525
1526 for (i = 0; i < bus->deviceCount; i++) {
1527 if (bus->device[i]) {
27dd5548
KC
1528 if (PLINE(" busNo %d, device[%i]: 0x%p, chanptr=0x%p, swtch=0x%p\n",
1529 bus->busNo, i, bus->device[i],
1530 bus->device[i]->chanptr,
1531 bus->device[i]->swtch) < 0)
1532 goto err_done_unlock;
1533
1534 if (PLINE(" first_busy_cnt=%llu, moved_to_tail_cnt=%llu, last_on_list_cnt=%llu\n",
1535 bus->device[i]->first_busy_cnt,
1536 bus->device[i]->moved_to_tail_cnt,
1537 bus->device[i]->last_on_list_cnt) < 0)
1538 goto err_done_unlock;
bac8a4d5
KC
1539 }
1540 }
1541 }
1542 read_unlock(&BusListLock);
1543
27dd5548
KC
1544 if (PLINE("UisUtils_Registered_Services: %d\n",
1545 atomic_read(&UisUtils_Registered_Services)) < 0)
1546 goto err_done;
1547 if (PLINE("cycles_before_wait %llu wait_cycles:%llu\n",
1548 cycles_before_wait, wait_cycles) < 0)
1549 goto err_done;
1550 if (PLINE("tot_wakeup_cnt %llu:tot_wait_cnt %llu:tot_schedule_cnt %llu\n",
1551 tot_wakeup_cnt, tot_wait_cnt, tot_schedule_cnt) < 0)
1552 goto err_done;
1553 if (PLINE("en_smart_wakeup %d\n", en_smart_wakeup) < 0)
1554 goto err_done;
1555 if (PLINE("tot_moved_to_tail_cnt %llu\n", tot_moved_to_tail_cnt) < 0)
1556 goto err_done;
bac8a4d5
KC
1557
1558 return tot;
bac8a4d5 1559
27dd5548
KC
1560err_done_unlock:
1561 read_unlock(&BusListLock);
1562err_done:
bac8a4d5
KC
1563 return -1;
1564}
1565
1566static ssize_t
1567info_proc_read(struct file *file, char __user *buf, size_t len, loff_t *offset)
1568{
1569 char *temp;
1570 int totalBytes = 0;
1571 int remaining_bytes = PROC_READ_BUFFER_SIZE;
1572
1573/* *start = buf; */
1574 if (ProcReadBuffer == NULL) {
1575 DBGINF("ProcReadBuffer == NULL; allocating buffer.\n.");
60140462 1576 ProcReadBuffer = vmalloc(PROC_READ_BUFFER_SIZE);
bac8a4d5
KC
1577
1578 if (ProcReadBuffer == NULL) {
1579 LOGERR("failed to allocate buffer to provide proc data.\n");
1580 return -ENOMEM;
1581 }
1582 }
1583
1584 temp = ProcReadBuffer;
1585
1586 if ((*offset == 0) || (!ProcReadBufferValid)) {
1587 DBGINF("calling info_proc_read_helper.\n");
1588 /* if the read fails, then -1 will be returned */
1589 totalBytes = info_proc_read_helper(&temp, &remaining_bytes);
1590 ProcReadBufferValid = 1;
1591 } else
1592 totalBytes = strlen(ProcReadBuffer);
1593
1594 return simple_read_from_buffer(buf, len, offset,
1595 ProcReadBuffer, totalBytes);
1596}
1597
1598static ssize_t
1599platformnumber_proc_read(struct file *file, char __user *buf,
1600 size_t len, loff_t *offset)
1601{
1602 int length = 0;
1603 char *vbuf;
1604 loff_t pos = *offset;
1605
1606 if (pos < 0)
1607 return -EINVAL;
1608
1609 if (pos > 0 || !len)
1610 return 0;
1611
1612 vbuf = kzalloc(len, GFP_KERNEL);
1613 if (!vbuf)
1614 return -ENOMEM;
1615
1616 length = sprintf(vbuf, "%d\n", PlatformNumber);
1617
1618 if (copy_to_user(buf, vbuf, length)) {
1619 kfree(vbuf);
1620 return -EFAULT;
1621 }
1622
1623 kfree(vbuf);
1624 *offset += length;
1625 return length;
1626}
1627
1628#ifdef UISLIB_TEST_PROC
1629
1630/* proc/uislib/vbus/<x>/info */
1631static int
1632proc_info_vbus_show(struct seq_file *m, void *v)
1633{
1634 struct bus_info *bus = m->private;
1635 int i, devInfoCount, x;
1636 char buf[999];
1637
1638 if (bus == NULL)
1639 return 0;
1640 seq_printf(m, "Client device / client driver info for %s partition (vbus #%d):\n",
1641 bus->partitionName, bus->busNo);
1642 if ((bus->busChannelBytes == 0) || (bus->pBusChannel == NULL))
1643 return 0;
1644 devInfoCount =
1645 (bus->busChannelBytes -
1646 sizeof(ULTRA_VBUS_CHANNEL_PROTOCOL)) /
1647 sizeof(ULTRA_VBUS_DEVICEINFO);
a8d7f21d 1648 x = VBUSCHANNEL_devInfoToStringBuffer(&bus->pBusChannel->ChpInfo, buf,
bac8a4d5
KC
1649 sizeof(buf) - 1, -1);
1650 buf[x] = '\0';
1651 seq_printf(m, "%s", buf);
a8d7f21d 1652 x = VBUSCHANNEL_devInfoToStringBuffer(&bus->pBusChannel->BusInfo,
bac8a4d5
KC
1653 buf, sizeof(buf) - 1, -1);
1654 buf[x] = '\0';
1655 seq_printf(m, "%s", buf);
1656 for (i = 0; i < devInfoCount; i++) {
a8d7f21d 1657 x = VBUSCHANNEL_devInfoToStringBuffer(&bus->pBusChannel->
bac8a4d5
KC
1658 DevInfo[i], buf,
1659 sizeof(buf) - 1, i);
1660 if (x > 0) {
1661 buf[x] = '\0';
1662 seq_printf(m, "%s", buf);
1663 }
1664 }
1665 return 0;
1666}
1667
1668static ssize_t
1669bus_proc_write(struct file *file, const char __user *buffer,
1670 size_t count, loff_t *ppos)
1671{
1672 int server_flag = 0;
1673 int i, action = 0xffff, result;
61a0bc0f 1674 char buf[16];
bac8a4d5
KC
1675 CONTROLVM_MESSAGE msg;
1676 U32 busNo, deviceCount;
1677
61a0bc0f
KC
1678 if (count >= ARRAY_SIZE(buf))
1679 return -EINVAL;
1680
bac8a4d5
KC
1681 memset(&msg, 0, sizeof(CONTROLVM_MESSAGE));
1682
1683 if (copy_from_user(buf, buffer, count)) {
1684 LOGERR("echo > /proc/uislib/bus: copy_from_user ****FAILED.");
1685 return -EFAULT;
1686 }
1687
1688 i = sscanf(buf, "%x-%d-%d", &action, &busNo, &deviceCount);
1689
1690 /* if (i < 1), i.e., if we didn't even read the action field,
1691 * then action will default to 0xffff and the code below will
1692 * fall through the switch and print usage.
1693 */
1694 switch (action) {
1695 case 0:
1696 /* destroy a bus */
1697 if (i != 2)
1698 break;
1699 init_msg_header(&msg, CONTROLVM_BUS_DESTROY, 0, server_flag);
1700 msg.cmd.destroyBus.busNo = busNo;
1701
1702 result = destroy_bus(&msg, NULL);
1703
1704 if (result != CONTROLVM_RESP_SUCCESS) {
1705 LOGERR("echo 0-%d > /proc/uislib/bus {CONTROLVM_BUS_DESTROY Failed} Result(%d)",
1706 busNo, result);
1707 return -EFAULT;
1708 }
1709 return count;
1710 case 1:
1711 /* create a bus */
1712 if (i != 3)
1713 break;
1714 init_msg_header(&msg, CONTROLVM_BUS_CREATE, 0, server_flag);
1715 msg.cmd.createBus.busNo = busNo;
1716 msg.cmd.createBus.deviceCount = deviceCount;
1717
1718 result = create_bus(&msg, NULL);
1719
1720 if (result != CONTROLVM_RESP_SUCCESS) {
1721 LOGERR("echo 1-%d-%d > /proc/uislib/bus {CONTROLVM_BUS_CREATE Failed} Result(%d)",
1722 busNo, deviceCount, result);
1723 return -EFAULT;
1724 }
1725
1726 return count;
1727 default:
1728 break;
1729 }
1730
1731 LOGERR("USAGE: echo <action>-<busNo>... > /proc/uislib/bus");
1732 LOGERR(" ");
1733 LOGERR("Destruct Syntax ControlVM Message Id");
1734 LOGERR("--------------- ---------------------");
1735 LOGERR("0-<busNo> ==> CONTROLVM_BUS_DESTROY");
1736 LOGERR(" ");
1737 LOGERR("Construct Syntax ControlVM Message Id");
1738 LOGERR("----------------------- -------------------- ");
1739 LOGERR("1-<busNo>-<deviceCount> ==> CONTROLVM_BUS_CREATE");
1740
1741 return -EFAULT;
1742}
1743
1744static ssize_t
1745uislib_proc_read_writeonly(struct file *file, char __user *buffer,
1746 size_t count, loff_t *ppos)
1747{
1748 return 0;
1749}
1750
1751static ssize_t
1752dev_proc_write(struct file *file, const char __user *buffer,
1753 size_t count, loff_t *ppos)
1754{
1755 int server_flag = 0;
1756 CONTROLVM_MESSAGE msg;
1757 U32 busNo, devNo;
61a0bc0f 1758 char buf[32];
bac8a4d5
KC
1759 unsigned int chanptr;
1760 int type, i, action = 0xffff, result;
1761
61a0bc0f
KC
1762 if (count >= ARRAY_SIZE(buf))
1763 return -EINVAL;
1764
bac8a4d5
KC
1765 if (copy_from_user(buf, buffer, count)) {
1766 LOGERR("echo > /proc/uislib/device: copy_from_user ****FAILED.");
1767 return -EFAULT;
1768 }
1769
1770 i = sscanf(buf, "%x-%d-%d-%x-%d",
1771 &action, &busNo, &devNo, &chanptr, &type);
1772
1773 switch (action) {
1774 case 0:
1775 if (i != 3)
1776 break;
1777
1778 /* destroy a device */
1779 init_msg_header(&msg, CONTROLVM_DEVICE_DESTROY, 0, server_flag);
1780 msg.cmd.destroyDevice.busNo = busNo;
1781 msg.cmd.destroyDevice.devNo = devNo;
1782
1783 result = destroy_device(&msg, NULL);
1784
1785 if (result != CONTROLVM_RESP_SUCCESS) {
1786 LOGERR("echo 0-%d-%d > /proc/uislib/device {CONTROLVM_DEVICE_DESTROY Failed} Result(%d)",
1787 busNo, devNo, result);
1788 return -EFAULT;
1789 }
1790
1791 return count;
1792
1793 case 1:
1794 if (i != 5)
1795 break;
1796
1797 /* create a device */
1798 init_msg_header(&msg, CONTROLVM_DEVICE_CREATE, 0, server_flag);
1799 msg.cmd.createDevice.busNo = busNo;
1800 msg.cmd.createDevice.devNo = devNo;
1801 msg.cmd.createDevice.channelAddr = __pa(chanptr);
1802 msg.cmd.createDevice.channelBytes = MIN_IO_CHANNEL_SIZE;
1803
1804 if (type == 0)
1805 msg.cmd.createDevice.dataTypeGuid =
1806 UltraVhbaChannelProtocolGuid;
1807 else if (type == 1)
1808 msg.cmd.createDevice.dataTypeGuid =
1809 UltraVnicChannelProtocolGuid;
1810 else {
1811 LOGERR("echo 1-%d-%d-%x-<type> > /proc/uislib/devce failed: invalid device type %d.",
1812 busNo, devNo, chanptr, type);
1813 return -EFAULT;
1814 }
1815
1816 result = create_device(&msg, NULL);
1817
1818 if (result != CONTROLVM_RESP_SUCCESS) {
1819 if (type == 0)
1820 LOGERR("echo 1-%d-%d-%x-0 > /proc/uislib/device {CONTROLVM_DEVICE_CREATE[vHBA] Failed} Result(%d)",
1821 busNo, devNo, chanptr, result);
1822 else
1823 LOGERR("echo 1-%d-%d-%x-1 > /proc/uislib/device {CONTROLVM_DEVICE_CREATE[vNIC] Failed} Result(%d)",
1824 busNo, devNo, chanptr, result);
1825 return -EFAULT;
1826 }
1827
1828 default:
1829 break;
1830 }
1831
1832 LOGERR("USAGE: echo <action>-<busNo>-<devNo>... > /proc/uislib/device");
1833 LOGERR(" ");
1834 LOGERR("Destruct Syntax ControlVM Message Id");
1835 LOGERR("----------------- ------------------------");
1836 LOGERR("0-<busNo>-<devNo> ==> CONTROLVM_DEVICE_DESTROY");
1837 LOGERR(" ");
1838 LOGERR("Construct Syntax ControlVM Message Id");
1839 LOGERR
1840 ("---------------------------------- ----------------------- ");
1841 LOGERR
1842 ("1-<busNo>-<devNo>-<chanptr>-<type> ==> CONTROLVM_DEVICE_CREATE");
1843 LOGERR(" <type = 0>: vHBA");
1844 LOGERR(" <type = 1>: vNIC");
1845 LOGERR(" ");
1846
1847 return -EFAULT;
1848}
1849
1850static ssize_t
1851cycles_before_wait_proc_write(struct file *file, const char __user *buffer,
1852 size_t count, loff_t *ppos)
1853{
61a0bc0f 1854 char buf[16];
bac8a4d5
KC
1855
1856#define CYCLES_BEFORE_WAIT_USE_ERROR { \
1857 LOGERR("Incorrect Call Home Input.\n"); \
1858 pr_info("Please pass Call Home Event Parameters in the form:\n"); \
1859 pr_info("EventID Category Type[parameter1][parameter2][parameter3][parameter4][parameter5][parameter6]\n"); \
1860 return -EFAULT; \
1861}
61a0bc0f
KC
1862 if (count >= ARRAY_SIZE(buf))
1863 return -EINVAL;
bac8a4d5
KC
1864
1865 if (count == 0)
1866 CYCLES_BEFORE_WAIT_USE_ERROR;
1867
1868 if (copy_from_user(buf, buffer, count)) {
1869 LOGERR("copy_from_user failed.\n");
1870 return -EFAULT;
1871 }
1872 buf[count - 1] = '\0'; /* Replace the LF at the end of the
1873 * input with a NULL */
1874 /* Pull out the cycles_before_wait must be decimal integer */
1875 if (sscanf(buf, "%lld", &cycles_before_wait) != 1)
1876 CYCLES_BEFORE_WAIT_USE_ERROR;
1877
1878 return count;
1879}
1880
1881static ssize_t
1882reset_counts_proc_write(struct file *file, const char __user *buffer,
1883 size_t count, loff_t *ppos)
1884{
61a0bc0f 1885 char buf[16];
bac8a4d5
KC
1886 unsigned long long new_value;
1887 struct bus_info *bus;
1888 int i;
1889
1890#define RESET_COUNTS_USE_ERROR { \
1891 LOGERR("Incorrect reset_counts Input.\n"); \
1892 pr_info("Please pass the new value for the counters:\n"); \
1893 pr_info("e.g. echo 0 > reset_counts\n"); \
1894 return -EFAULT; \
1895 }
1896
61a0bc0f
KC
1897 if (count >= ARRAY_SIZE(buf))
1898 return -EINVAL;
1899
bac8a4d5
KC
1900 if (count == 0)
1901 RESET_COUNTS_USE_ERROR;
1902
1903 if (copy_from_user(buf, buffer, count)) {
1904 LOGERR("copy_from_user failed.\n");
1905 return -EFAULT;
1906 }
1907 buf[count - 1] = '\0'; /* Replace the LF at the end of the
1908 * input with a NULL */
1909 /* Pull out the reset_counts must be decimal integer */
1910 if (sscanf(buf, "%llu", &new_value) != 1)
1911 RESET_COUNTS_USE_ERROR;
1912 read_lock(&BusListLock);
1913 for (bus = BusListHead; bus; bus = bus->next) {
1914
1915 for (i = 0; i < bus->deviceCount; i++) {
1916 if (bus->device[i]) {
1917 bus->device[i]->first_busy_cnt = new_value;
1918 bus->device[i]->moved_to_tail_cnt = new_value;
1919 bus->device[i]->last_on_list_cnt = new_value;
1920 }
1921 }
1922 }
1923 read_unlock(&BusListLock);
1924 tot_moved_to_tail_cnt = new_value;
1925 tot_wait_cnt = new_value;
1926 tot_wakeup_cnt = new_value;
1927 tot_schedule_cnt = new_value;
1928 return count;
1929}
1930
1931static ssize_t
1932smart_wakeup_proc_write(struct file *file, const char __user *buffer,
1933 size_t count, loff_t *ppos)
1934{
61a0bc0f 1935 char buf[16];
bac8a4d5
KC
1936 int new_value;
1937
1938#define SMART_WAKEUP_USE_ERROR { \
1939 LOGERR("Incorrect smart_wakeup Input 0 disables smart_wakeup, and 1 enables smart_wakeup.\n"); \
1940 pr_info("echo 0 > smart_wakeup\n"); \
1941 pr_info("echo 1 > smart_wakeup\n"); \
1942 return -EFAULT; \
1943 }
1944
61a0bc0f
KC
1945 if (count >= ARRAY_SIZE(buf))
1946 return -EINVAL;
1947
bac8a4d5
KC
1948 if (count == 0)
1949 SMART_WAKEUP_USE_ERROR;
1950
1951 if (copy_from_user(buf, buffer, count)) {
1952 LOGERR("copy_from_user failed.\n");
1953 return -EFAULT;
1954 }
1955 buf[count - 1] = '\0'; /* Replace the LF at the end of the
1956 * input with a NULL */
1957 /* Pull out the smart_wakeup must be decimal integer */
1958 if (sscanf(buf, "%d", &new_value) != 1)
1959 SMART_WAKEUP_USE_ERROR;
1960 en_smart_wakeup = new_value;
1961 return count;
1962}
1963
1964static ssize_t
1965test_proc_write(struct file *file, const char __user *buffer,
1966 size_t count, loff_t *ppos)
1967{
1968 int i, action = 0xffff;
61a0bc0f 1969 char buf[16];
bac8a4d5
KC
1970 CONTROLVM_MESSAGE msg;
1971 S64 vrtc_offset;
1972
61a0bc0f
KC
1973 if (count >= ARRAY_SIZE(buf))
1974 return -EINVAL;
1975
bac8a4d5
KC
1976 memset(&msg, 0, sizeof(CONTROLVM_MESSAGE));
1977
1978 if (copy_from_user(buf, buffer, count)) {
1979 LOGERR("copy_from_user ****FAILED.\n");
1980 return -EFAULT;
1981 }
1982
1983 i = sscanf(buf, "%x", &action);
1984
1985 /* if (i < 1), i.e., if we didn't even read the action field,
1986 * then action will default to 0xffff and the code below will
1987 * fall through the switch and print usage. */
1988 switch (action) {
1989 case 6:
1990 msg.hdr.Id = CONTROLVM_CHIPSET_STOP;
1991 msg.hdr.Flags.responseExpected = 1;
1992 stop_chipset(&msg, NULL);
1993 break;
1994 case 7:
1995 vrtc_offset = 0;
1996 LOGERR("about to issue QUERY vrtc_offset=%LX", vrtc_offset);
1997 vrtc_offset = Issue_VMCALL_QUERY_GUEST_VIRTUAL_TIME_OFFSET();
1998 LOGERR("result is vrtc_offset=%LX", vrtc_offset);
1999 break;
2000 case 8:
2001 vrtc_offset = 60;
2002 LOGERR("about to increase physical time by 0x%LX seconds",
2003 vrtc_offset);
2004 vrtc_offset = Issue_VMCALL_UPDATE_PHYSICAL_TIME(vrtc_offset);
2005 break;
2006 case 9:
2007 vrtc_offset = -60;
2008 LOGERR("about to decrease physical time by 0x%LX seconds",
2009 vrtc_offset);
2010 vrtc_offset = Issue_VMCALL_UPDATE_PHYSICAL_TIME(vrtc_offset);
2011 break;
2012 default:
2013 LOGERR("usage: 6 for CHIPSET_STOP\n");
2014 LOGERR(" 7 for VMCALL_QUERY_GUEST_VIRTUAL_TIME_OFFSET()\n");
2015 LOGERR(" 8 for VMCALL_UPDATE_PHYSICAL_TIME(60)\n");
2016 LOGERR(" 9 for VMCALL_UPDATE_PHYSICAL_TIME(-60)\n");
2017 return -EFAULT;
2018 break;
2019 }
2020 return count;
2021}
2022
2023#endif /* UISLIB_TEST_PROC */
2024static struct device_info *
2025find_dev(U32 busNo, U32 devNo)
2026{
2027 struct bus_info *bus;
2028 struct device_info *dev = NULL;
2029
2030 read_lock(&BusListLock);
2031 for (bus = BusListHead; bus; bus = bus->next) {
2032 if (bus->busNo == busNo) {
2033 /* make sure the device number is valid */
2034 if (devNo >= bus->deviceCount) {
2035 LOGERR("%s bad busNo, devNo=%d,%d",
2036 __func__,
2037 (int) (busNo), (int) (devNo));
2038 goto Away;
2039 }
2040 dev = bus->device[devNo];
2041 if (!dev)
2042 LOGERR("%s bad busNo, devNo=%d,%d",
2043 __func__,
2044 (int) (busNo), (int) (devNo));
2045 goto Away;
2046 }
2047 }
2048Away:
2049 read_unlock(&BusListLock);
2050 return dev;
2051}
2052
2053/* This thread calls the "interrupt" function for each device that has
2054 * enabled such using uislib_enable_channel_interrupts(). The "interrupt"
2055 * function typically reads and processes the devices's channel input
2056 * queue. This thread repeatedly does this, until the thread is told to stop
2057 * (via uisthread_stop()). Sleeping rules:
2058 * - If we have called the "interrupt" function for all devices, and all of
2059 * them have reported "nothing processed" (returned 0), then we will go to
2060 * sleep for a maximum of POLLJIFFIES_NORMAL jiffies.
2061 * - If anyone calls uislib_force_channel_interrupt(), the above jiffy
2062 * sleep will be interrupted, and we will resume calling the "interrupt"
2063 * function for all devices.
2064 * - The list of devices is dynamically re-ordered in order to
2065 * attempt to preserve fairness. Whenever we spin thru the list of
2066 * devices and call the dev->interrupt() function, if we find
2067 * devices which report that there is still more work to do, the
2068 * the first such device we find is moved to the end of the device
2069 * list. This ensures that extremely busy devices don't starve out
2070 * less-busy ones.
2071 *
2072 */
2073static int
2074Process_Incoming(void *v)
2075{
2076 unsigned long long cur_cycles, old_cycles, idle_cycles, delta_cycles;
2077 struct list_head *new_tail = NULL;
2078 int i;
2079 UIS_DAEMONIZE("dev_incoming");
2080 for (i = 0; i < 16; i++) {
2081 old_cycles = get_cycles();
2082 wait_event_timeout(Wakeup_Polling_Device_Channels,
2083 0, POLLJIFFIES_NORMAL);
2084 cur_cycles = get_cycles();
2085 if (wait_cycles == 0) {
2086 wait_cycles = (cur_cycles - old_cycles);
2087 } else {
2088 if (wait_cycles < (cur_cycles - old_cycles))
2089 wait_cycles = (cur_cycles - old_cycles);
2090 }
2091 }
2092 LOGINF("wait_cycles=%llu", wait_cycles);
2093 cycles_before_wait = wait_cycles;
2094 idle_cycles = 0;
2095 Go_Polling_Device_Channels = 0;
2096 while (1) {
2097 struct list_head *lelt, *tmp;
2098 struct device_info *dev = NULL;
2099
2100 /* poll each channel for input */
2101 LOCKSEM_UNINTERRUPTIBLE(&Lock_Polling_Device_Channels);
2102 new_tail = NULL;
2103 list_for_each_safe(lelt, tmp, &List_Polling_Device_Channels) {
2104 int rc = 0;
2105 dev = list_entry(lelt, struct device_info,
2106 list_polling_device_channels);
2107 LOCKSEM_UNINTERRUPTIBLE(&dev->interrupt_callback_lock);
2108 if (dev->interrupt)
2109 rc = dev->interrupt(dev->interrupt_context);
2110 else
2111 continue;
2112 UNLOCKSEM(&dev->interrupt_callback_lock);
2113 if (rc) {
2114 /* dev->interrupt returned, but there
2115 * is still more work to do.
2116 * Reschedule work to occur as soon as
2117 * possible. */
2118 idle_cycles = 0;
2119 if (new_tail == NULL) {
2120 dev->first_busy_cnt++;
2121 if (!
2122 (list_is_last
2123 (lelt,
2124 &List_Polling_Device_Channels))) {
2125 new_tail = lelt;
2126 dev->moved_to_tail_cnt++;
2127 } else
2128 dev->last_on_list_cnt++;
2129 }
2130
2131 }
2132 if (Incoming_ThreadInfo.should_stop)
2133 break;
2134 }
2135 if (new_tail != NULL) {
2136 tot_moved_to_tail_cnt++;
2137 list_move_tail(new_tail, &List_Polling_Device_Channels);
2138 }
2139 UNLOCKSEM(&Lock_Polling_Device_Channels);
2140 cur_cycles = get_cycles();
2141 delta_cycles = cur_cycles - old_cycles;
2142 old_cycles = cur_cycles;
2143
2144 /* At this point, we have scanned thru all of the
2145 * channels, and at least one of the following is true:
2146 * - there is no input waiting on any of the channels
2147 * - we have received a signal to stop this thread
2148 */
2149 if (Incoming_ThreadInfo.should_stop)
2150 break;
2151 if (en_smart_wakeup == 0xFF) {
2152 LOGINF("en_smart_wakeup set to 0xff, to force exiting process_incoming");
2153 break;
2154 }
2155 /* wait for POLLJIFFIES_NORMAL jiffies, or until
2156 * someone wakes up Wakeup_Polling_Device_Channels,
2157 * whichever comes first only do a wait when we have
2158 * been idle for cycles_before_wait cycles.
2159 */
2160 if (idle_cycles > cycles_before_wait) {
2161 Go_Polling_Device_Channels = 0;
2162 tot_wait_cnt++;
2163 wait_event_timeout(Wakeup_Polling_Device_Channels,
2164 Go_Polling_Device_Channels,
2165 POLLJIFFIES_NORMAL);
2166 Go_Polling_Device_Channels = 1;
2167 } else {
2168 tot_schedule_cnt++;
2169 schedule();
2170 idle_cycles = idle_cycles + delta_cycles;
2171 }
2172 }
2173 DBGINF("exiting.\n");
2174 complete_and_exit(&Incoming_ThreadInfo.has_stopped, 0);
2175}
2176
2177static BOOL
2178Initialize_incoming_thread(void)
2179{
2180 if (Incoming_Thread_Started)
2181 return TRUE;
2182 if (!uisthread_start(&Incoming_ThreadInfo,
2183 &Process_Incoming, NULL, "dev_incoming")) {
2184 LOGERR("uisthread_start Initialize_incoming_thread ****FAILED");
2185 return FALSE;
2186 }
2187 Incoming_Thread_Started = TRUE;
2188 return TRUE;
2189}
2190
2191/* Add a new device/channel to the list being processed by
2192 * Process_Incoming().
2193 * <interrupt> - indicates the function to call periodically.
2194 * <interrupt_context> - indicates the data to pass to the <interrupt>
2195 * function.
2196 */
2197void
2198uislib_enable_channel_interrupts(U32 busNo, U32 devNo,
2199 int (*interrupt)(void *),
2200 void *interrupt_context)
2201{
2202 struct device_info *dev;
2203 dev = find_dev(busNo, devNo);
2204 if (!dev) {
2205 LOGERR("%s busNo=%d, devNo=%d", __func__, (int) (busNo),
2206 (int) (devNo));
2207 return;
2208 }
2209 LOCKSEM_UNINTERRUPTIBLE(&Lock_Polling_Device_Channels);
2210 Initialize_incoming_thread();
2211 dev->interrupt = interrupt;
2212 dev->interrupt_context = interrupt_context;
2213 dev->polling = TRUE;
2214 list_add_tail(&(dev->list_polling_device_channels),
2215 &List_Polling_Device_Channels);
2216 UNLOCKSEM(&Lock_Polling_Device_Channels);
2217}
2218EXPORT_SYMBOL_GPL(uislib_enable_channel_interrupts);
2219
2220/* Remove a device/channel from the list being processed by
2221 * Process_Incoming().
2222 */
2223void
2224uislib_disable_channel_interrupts(U32 busNo, U32 devNo)
2225{
2226 struct device_info *dev;
2227 dev = find_dev(busNo, devNo);
2228 if (!dev) {
2229 LOGERR("%s busNo=%d, devNo=%d", __func__, (int) (busNo),
2230 (int) (devNo));
2231 return;
2232 }
2233 LOCKSEM_UNINTERRUPTIBLE(&Lock_Polling_Device_Channels);
2234 list_del(&dev->list_polling_device_channels);
2235 dev->polling = FALSE;
2236 dev->interrupt = NULL;
2237 UNLOCKSEM(&Lock_Polling_Device_Channels);
2238}
2239EXPORT_SYMBOL_GPL(uislib_disable_channel_interrupts);
2240
2241static void
2242do_wakeup_polling_device_channels(struct work_struct *dummy)
2243{
2244 if (!Go_Polling_Device_Channels) {
2245 Go_Polling_Device_Channels = 1;
2246 wake_up(&Wakeup_Polling_Device_Channels);
2247 }
2248}
2249
a8d7f21d
KC
2250static DECLARE_WORK(Work_wakeup_polling_device_channels,
2251 do_wakeup_polling_device_channels);
bac8a4d5
KC
2252
2253/* Call this function when you want to send a hint to Process_Incoming() that
2254 * your device might have more requests.
2255 */
2256void
2257uislib_force_channel_interrupt(U32 busNo, U32 devNo)
2258{
2259 if (en_smart_wakeup == 0)
2260 return;
2261 if (Go_Polling_Device_Channels)
2262 return;
2263 /* The point of using schedule_work() instead of just doing
2264 * the work inline is to force a slight delay before waking up
2265 * the Process_Incoming() thread.
2266 */
2267 tot_wakeup_cnt++;
2268 schedule_work(&Work_wakeup_polling_device_channels);
2269}
2270EXPORT_SYMBOL_GPL(uislib_force_channel_interrupt);
2271
2272/*****************************************************/
2273/* Module Init & Exit functions */
2274/*****************************************************/
2275
2276static int __init
2277uislib_mod_init(void)
2278{
2279
2280 LOGINF("MONITORAPIS");
2281
2282 LOGINF("sizeof(struct uiscmdrsp):%lu bytes\n",
2283 (ulong) sizeof(struct uiscmdrsp));
2284 LOGINF("sizeof(struct phys_info):%lu\n",
2285 (ulong) sizeof(struct phys_info));
2286 LOGINF("sizeof(uiscmdrsp_scsi):%lu\n",
2287 (ulong) sizeof(struct uiscmdrsp_scsi));
2288 LOGINF("sizeof(uiscmdrsp_net):%lu\n",
2289 (ulong) sizeof(struct uiscmdrsp_net));
2290 LOGINF("sizeof(CONTROLVM_MESSAGE):%lu bytes\n",
2291 (ulong) sizeof(CONTROLVM_MESSAGE));
2292 LOGINF("sizeof(ULTRA_CONTROLVM_CHANNEL_PROTOCOL):%lu bytes\n",
2293 (ulong) sizeof(ULTRA_CONTROLVM_CHANNEL_PROTOCOL));
2294 LOGINF("sizeof(CHANNEL_HEADER):%lu bytes\n",
2295 (ulong) sizeof(CHANNEL_HEADER));
2296 LOGINF("sizeof(ULTRA_IO_CHANNEL_PROTOCOL):%lu bytes\n",
2297 (ulong) sizeof(ULTRA_IO_CHANNEL_PROTOCOL));
2298 LOGINF("SIZEOF_CMDRSP:%lu bytes\n", SIZEOF_CMDRSP);
2299 LOGINF("SIZEOF_PROTOCOL:%lu bytes\n", SIZEOF_PROTOCOL);
2300
2301 /* initialize global pointers to NULL */
2302 BusListHead = NULL;
2303 BusListCount = MaxBusCount = 0;
2304 rwlock_init(&BusListLock);
2305 VirtControlChanFunc = NULL;
2306
2307 /* Issue VMCALL_GET_CONTROLVM_ADDR to get CtrlChanPhysAddr and
2308 * then map this physical address to a virtual address. */
2309 POSTCODE_LINUX_2(DRIVER_ENTRY_PC, POSTCODE_SEVERITY_INFO);
2310
2311 /* create the proc entries for the channels */
2312 uislib_proc_dir = proc_mkdir(DIR_PROC_ENTRY, NULL);
2313 /* (e.g., for /proc/uislib/vbus/<x>/info) */
2314 uislib_proc_vbus_dir = proc_mkdir(DIR_VBUS_PROC_ENTRY, uislib_proc_dir);
2315
2316 vnic_proc_entry = proc_create(VNIC_PROC_ENTRY_FN, 0, uislib_proc_dir,
2317 &proc_vnic_fops);
2318 SET_PROC_OWNER(vnic_proc_entry, THIS_MODULE);
2319
2320 /* for testing purposes only, create the proc entries for
2321 * enqueuing Control Channel messages */
2322 chipset_proc_entry =
2323 proc_create(CHIPSET_PROC_ENTRY_FN, 0, uislib_proc_dir,
2324 &proc_chipset_fops);
2325 SET_PROC_OWNER(chipset_proc_entry, THIS_MODULE);
2326
2327 info_proc_entry = proc_create(INFO_PROC_ENTRY_FN, 0, uislib_proc_dir,
2328 &proc_info_fops);
2329 SET_PROC_OWNER(info_proc_entry, THIS_MODULE);
2330
2331 platformnumber_proc_entry =
2332 proc_create(PLATFORMNUMBER_PROC_ENTRY_FN, 0, uislib_proc_dir,
2333 &proc_platformnumber_fops);
2334 SET_PROC_OWNER(platformnumberinfo_proc_entry, THIS_MODULE);
2335
2336 cycles_before_wait_proc_entry =
2337 proc_create(CYCLES_BEFORE_WAIT_PROC_ENTRY_FN, 0, uislib_proc_dir,
2338 &proc_cycles_before_wait_fops);
2339 SET_PROC_OWNER(cycles_before_wait_proc_entry, THIS_MODULE);
2340
2341 reset_counts_proc_entry =
2342 proc_create(RESET_COUNTS_PROC_ENTRY_FN, 0, uislib_proc_dir,
2343 &proc_reset_counts_fops);
2344 SET_PROC_OWNER(reset_counts_proc_entry, THIS_MODULE);
2345
2346 smart_wakeup_proc_entry =
2347 proc_create(SMART_WAKEUP_PROC_ENTRY_FN, 0, uislib_proc_dir,
2348 &proc_smart_wakeup_fops);
2349 SET_PROC_OWNER(smart_wakeup_proc_entry, THIS_MODULE);
2350
2351#ifdef UISLIB_TEST_PROC
2352 test_proc_entry = proc_create(TEST_PROC_ENTRY_FN, 0, uislib_proc_dir,
2353 &proc_test_fops);
2354 SET_PROC_OWNER(test_proc_entry, THIS_MODULE);
2355
2356 bus_proc_entry = proc_create(BUS_PROC_ENTRY_FN, 0, uislib_proc_dir,
2357 &proc_bus_fops);
2358 SET_PROC_OWNER(bus_proc_entry, THIS_MODULE);
2359
2360 dev_proc_entry = proc_create(DEV_PROC_ENTRY_FN, 0, uislib_proc_dir,
2361 &proc_dev_fops);
2362 SET_PROC_OWNER(dev_proc_entry, THIS_MODULE);
2363#endif /* UISLIB_TEST_PROC */
2364 POSTCODE_LINUX_3(DRIVER_EXIT_PC, 0, POSTCODE_SEVERITY_INFO);
2365 return 0;
2366}
2367
2368static void __exit
2369uislib_mod_exit(void)
2370{
2371 if (disable_proc_entry)
2372 remove_proc_entry(DISABLE_PROC_ENTRY_FN, uislib_proc_dir);
2373 if (cycles_before_wait_proc_entry)
2374 remove_proc_entry(CYCLES_BEFORE_WAIT_PROC_ENTRY_FN,
2375 uislib_proc_dir);
2376 if (reset_counts_proc_entry)
2377 remove_proc_entry(RESET_COUNTS_PROC_ENTRY_FN, uislib_proc_dir);
2378 if (smart_wakeup_proc_entry)
2379 remove_proc_entry(SMART_WAKEUP_PROC_ENTRY_FN, uislib_proc_dir);
2380 if (ctrlchan_proc_entry)
2381 remove_proc_entry(CTRLCHAN_PROC_ENTRY_FN, uislib_proc_dir);
2382 if (pmem_proc_entry)
2383 remove_proc_entry(PMEM_PROC_ENTRY_FN, uislib_proc_dir);
2384 if (info_proc_entry)
2385 remove_proc_entry(INFO_PROC_ENTRY_FN, uislib_proc_dir);
2386 if (switch_proc_entry)
2387 remove_proc_entry(SWITCH_PROC_ENTRY_FN, uislib_proc_dir);
2388 if (extport_proc_entry)
2389 remove_proc_entry(EXTPORT_PROC_ENTRY_FN, uislib_proc_dir);
2390 if (platformnumber_proc_entry)
2391 remove_proc_entry(PLATFORMNUMBER_PROC_ENTRY_FN,
2392 uislib_proc_dir);
2393 if (bus_proc_entry)
2394 remove_proc_entry(BUS_PROC_ENTRY_FN, uislib_proc_dir);
2395 if (dev_proc_entry)
2396 remove_proc_entry(DEV_PROC_ENTRY_FN, uislib_proc_dir);
2397 if (vnic_proc_entry)
2398 remove_proc_entry(VNIC_PROC_ENTRY_FN, uislib_proc_dir);
2399 if (chipset_proc_entry)
2400 remove_proc_entry(CHIPSET_PROC_ENTRY_FN, uislib_proc_dir);
2401 if (uislib_proc_vbus_dir)
2402 remove_proc_entry(DIR_VBUS_PROC_ENTRY, uislib_proc_dir);
2403 if (uislib_proc_dir)
2404 remove_proc_entry(DIR_PROC_ENTRY, NULL);
2405
2406 if (ProcReadBuffer) {
60140462 2407 vfree(ProcReadBuffer);
bac8a4d5
KC
2408 ProcReadBuffer = NULL;
2409 }
2410
2411 DBGINF("goodbye.\n");
2412 return;
2413}
2414
2415module_init(uislib_mod_init);
2416module_exit(uislib_mod_exit);
2417
bac8a4d5
KC
2418MODULE_LICENSE("GPL");
2419MODULE_AUTHOR("Usha Srinivasan");
2420MODULE_ALIAS("uislib");
2421 /* this is extracted during depmod and kept in modules.dep */
This page took 0.140818 seconds and 5 git commands to generate.