staging: unisys: remove U32 type
[linux-2.6/btrfs-unstable.git] / drivers / staging / unisys / uislib / uislib.c
blob4e2777ef405b7aa53382374158d59cb6c22027b4
1 /* uislib.c
3 * Copyright (C) 2010 - 2013 UNISYS CORPORATION
4 * All rights reserved.
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.
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.
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 #include <linux/debugfs.h>
28 #include "commontypes.h"
30 #include <linux/version.h>
31 #include "uniklog.h"
32 #include "diagnostics/appos_subsystems.h"
33 #include "uisutils.h"
34 #include "vbuschannel.h"
36 #include <linux/proc_fs.h>
37 #include <linux/uaccess.h> /* for copy_from_user */
38 #include <linux/ctype.h> /* for toupper */
39 #include <linux/list.h>
41 #include "sparstop.h"
42 #include "visorchipset.h"
43 #include "chanstub.h"
44 #include "version.h"
45 #include "guestlinuxdebug.h"
47 #define SET_PROC_OWNER(x, y)
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
55 #define CURRENT_FILE_PC UISLIB_PC_uislib_c
56 #define __MYFILE__ "uislib.c"
58 /* global function pointers that act as callback functions into virtpcimod */
59 int (*VirtControlChanFunc)(struct guest_msgs *);
61 static int ProcReadBufferValid;
62 static char *ProcReadBuffer; /* Note this MUST be global,
63 * because the contents must */
64 static unsigned int chipset_inited;
66 #define WAIT_ON_CALLBACK(handle) \
67 do { \
68 if (handle) \
69 break; \
70 UIS_THREAD_WAIT; \
71 } while (1)
73 static struct bus_info *BusListHead;
74 static rwlock_t BusListLock;
75 static int BusListCount; /* number of buses in the list */
76 static int MaxBusCount; /* maximum number of buses expected */
77 static U64 PhysicalDataChan;
78 static int PlatformNumber;
80 static struct uisthread_info Incoming_ThreadInfo;
81 static BOOL Incoming_Thread_Started = FALSE;
82 static LIST_HEAD(List_Polling_Device_Channels);
83 static unsigned long long tot_moved_to_tail_cnt;
84 static unsigned long long tot_wait_cnt;
85 static unsigned long long tot_wakeup_cnt;
86 static unsigned long long tot_schedule_cnt;
87 static int en_smart_wakeup = 1;
88 static DEFINE_SEMAPHORE(Lock_Polling_Device_Channels); /* unlocked */
89 static DECLARE_WAIT_QUEUE_HEAD(Wakeup_Polling_Device_Channels);
90 static int Go_Polling_Device_Channels;
92 #define CALLHOME_PROC_ENTRY_FN "callhome"
93 #define CALLHOME_THROTTLED_PROC_ENTRY_FN "callhome_throttled"
95 #define DIR_DEBUGFS_ENTRY "uislib"
96 static struct dentry *dir_debugfs;
98 #define PLATFORMNUMBER_DEBUGFS_ENTRY_FN "platform"
99 static struct dentry *platformnumber_debugfs_read;
101 #define CYCLES_BEFORE_WAIT_DEBUGFS_ENTRY_FN "cycles_before_wait"
102 static struct dentry *cycles_before_wait_debugfs_read;
104 #define SMART_WAKEUP_DEBUGFS_ENTRY_FN "smart_wakeup"
105 static struct dentry *smart_wakeup_debugfs_entry;
107 #define INFO_DEBUGFS_ENTRY_FN "info"
108 static struct dentry *info_debugfs_entry;
110 static unsigned long long cycles_before_wait, wait_cycles;
112 /*****************************************************/
113 /* local functions */
114 /*****************************************************/
116 static ssize_t info_debugfs_read(struct file *file, char __user *buf,
117 size_t len, loff_t *offset);
118 static const struct file_operations debugfs_info_fops = {
119 .read = info_debugfs_read,
122 static void
123 init_msg_header(CONTROLVM_MESSAGE *msg, u32 id, uint rsp, uint svr)
125 memset(msg, 0, sizeof(CONTROLVM_MESSAGE));
126 msg->hdr.Id = id;
127 msg->hdr.Flags.responseExpected = rsp;
128 msg->hdr.Flags.server = svr;
131 static __iomem void *
132 init_vbus_channel(U64 channelAddr, u32 channelBytes)
134 void __iomem *rc = NULL;
135 void __iomem *pChan = uislib_ioremap_cache(channelAddr, channelBytes);
136 if (!pChan) {
137 LOGERR("CONTROLVM_BUS_CREATE error: ioremap_cache of channelAddr:%Lx for channelBytes:%llu failed",
138 (unsigned long long) channelAddr,
139 (unsigned long long) channelBytes);
140 rc = NULL;
141 goto Away;
143 if (!ULTRA_VBUS_CHANNEL_OK_CLIENT(pChan, NULL)) {
144 ERRDRV("%s channel cannot be used", __func__);
145 uislib_iounmap(pChan);
146 rc = NULL;
147 goto Away;
149 rc = pChan;
150 Away:
151 return rc;
154 static int
155 create_bus(CONTROLVM_MESSAGE *msg, char *buf)
157 u32 busNo, deviceCount;
158 struct bus_info *tmp, *bus;
159 size_t size;
161 if (MaxBusCount == BusListCount) {
162 LOGERR("CONTROLVM_BUS_CREATE Failed: max buses:%d already created\n",
163 MaxBusCount);
164 POSTCODE_LINUX_3(BUS_CREATE_FAILURE_PC, MaxBusCount,
165 POSTCODE_SEVERITY_ERR);
166 return CONTROLVM_RESP_ERROR_MAX_BUSES;
169 busNo = msg->cmd.createBus.busNo;
170 deviceCount = msg->cmd.createBus.deviceCount;
172 POSTCODE_LINUX_4(BUS_CREATE_ENTRY_PC, busNo, deviceCount,
173 POSTCODE_SEVERITY_INFO);
175 size =
176 sizeof(struct bus_info) +
177 (deviceCount * sizeof(struct device_info *));
178 bus = kzalloc(size, GFP_ATOMIC);
179 if (!bus) {
180 LOGERR("CONTROLVM_BUS_CREATE Failed: kmalloc for bus failed.\n");
181 POSTCODE_LINUX_3(BUS_CREATE_FAILURE_PC, busNo,
182 POSTCODE_SEVERITY_ERR);
183 return CONTROLVM_RESP_ERROR_KMALLOC_FAILED;
186 /* Currently by default, the bus Number is the GuestHandle.
187 * Configure Bus message can override this.
189 if (msg->hdr.Flags.testMessage) {
190 /* This implies we're the IOVM so set guest handle to 0... */
191 bus->guestHandle = 0;
192 bus->busNo = busNo;
193 bus->localVnic = 1;
194 } else
195 bus->busNo = bus->guestHandle = busNo;
196 sprintf(bus->name, "%d", (int) bus->busNo);
197 bus->deviceCount = deviceCount;
198 bus->device =
199 (struct device_info **) ((char *) bus + sizeof(struct bus_info));
200 bus->busInstGuid = msg->cmd.createBus.busInstGuid;
201 bus->busChannelBytes = 0;
202 bus->pBusChannel = NULL;
204 /* add bus to our bus list - but check for duplicates first */
205 read_lock(&BusListLock);
206 for (tmp = BusListHead; tmp; tmp = tmp->next) {
207 if (tmp->busNo == bus->busNo)
208 break;
210 read_unlock(&BusListLock);
211 if (tmp) {
212 /* found a bus already in the list with same busNo -
213 * reject add
215 LOGERR("CONTROLVM_BUS_CREATE Failed: bus %d already exists.\n",
216 bus->busNo);
217 POSTCODE_LINUX_3(BUS_CREATE_FAILURE_PC, bus->busNo,
218 POSTCODE_SEVERITY_ERR);
219 kfree(bus);
220 return CONTROLVM_RESP_ERROR_ALREADY_DONE;
222 if ((msg->cmd.createBus.channelAddr != 0)
223 && (msg->cmd.createBus.channelBytes != 0)) {
224 bus->busChannelBytes = msg->cmd.createBus.channelBytes;
225 bus->pBusChannel =
226 init_vbus_channel(msg->cmd.createBus.channelAddr,
227 msg->cmd.createBus.channelBytes);
229 /* the msg is bound for virtpci; send guest_msgs struct to callback */
230 if (!msg->hdr.Flags.server) {
231 struct guest_msgs cmd;
232 cmd.msgtype = GUEST_ADD_VBUS;
233 cmd.add_vbus.busNo = busNo;
234 cmd.add_vbus.chanptr = bus->pBusChannel;
235 cmd.add_vbus.deviceCount = deviceCount;
236 cmd.add_vbus.busTypeGuid = msg->cmd.createBus.busDataTypeGuid;
237 cmd.add_vbus.busInstGuid = msg->cmd.createBus.busInstGuid;
238 if (!VirtControlChanFunc) {
239 LOGERR("CONTROLVM_BUS_CREATE Failed: virtpci callback not registered.");
240 POSTCODE_LINUX_3(BUS_CREATE_FAILURE_PC, bus->busNo,
241 POSTCODE_SEVERITY_ERR);
242 kfree(bus);
243 return CONTROLVM_RESP_ERROR_VIRTPCI_DRIVER_FAILURE;
245 if (!VirtControlChanFunc(&cmd)) {
246 LOGERR("CONTROLVM_BUS_CREATE Failed: virtpci GUEST_ADD_VBUS returned error.");
247 POSTCODE_LINUX_3(BUS_CREATE_FAILURE_PC, bus->busNo,
248 POSTCODE_SEVERITY_ERR);
249 kfree(bus);
250 return
251 CONTROLVM_RESP_ERROR_VIRTPCI_DRIVER_CALLBACK_ERROR;
255 /* add bus at the head of our list */
256 write_lock(&BusListLock);
257 if (!BusListHead)
258 BusListHead = bus;
259 else {
260 bus->next = BusListHead;
261 BusListHead = bus;
263 BusListCount++;
264 write_unlock(&BusListLock);
266 POSTCODE_LINUX_3(BUS_CREATE_EXIT_PC, bus->busNo,
267 POSTCODE_SEVERITY_INFO);
268 return CONTROLVM_RESP_SUCCESS;
271 static int
272 destroy_bus(CONTROLVM_MESSAGE *msg, char *buf)
274 int i;
275 struct bus_info *bus, *prev = NULL;
276 u32 busNo;
278 busNo = msg->cmd.destroyBus.busNo;
280 /* find and delete the bus */
281 read_lock(&BusListLock);
282 for (bus = BusListHead; bus; prev = bus, bus = bus->next) {
283 if (bus->busNo == busNo) {
284 /* found the bus - ensure that all device
285 * slots are NULL
287 for (i = 0; i < bus->deviceCount; i++) {
288 if (bus->device[i] != NULL) {
289 LOGERR("CONTROLVM_BUS_DESTROY Failed: device %i attached to bus %d.",
290 i, busNo);
291 read_unlock(&BusListLock);
292 return CONTROLVM_RESP_ERROR_BUS_DEVICE_ATTACHED;
295 read_unlock(&BusListLock);
296 /* the msg is bound for virtpci; send
297 * guest_msgs struct to callback
299 if (!msg->hdr.Flags.server) {
300 struct guest_msgs cmd;
301 cmd.msgtype = GUEST_DEL_VBUS;
302 cmd.del_vbus.busNo = busNo;
303 if (!VirtControlChanFunc) {
304 LOGERR("CONTROLVM_BUS_DESTROY Failed: virtpci callback not registered.");
305 return CONTROLVM_RESP_ERROR_VIRTPCI_DRIVER_FAILURE;
307 if (!VirtControlChanFunc(&cmd)) {
308 LOGERR("CONTROLVM_BUS_DESTROY Failed: virtpci GUEST_DEL_VBUS returned error.");
309 return CONTROLVM_RESP_ERROR_VIRTPCI_DRIVER_CALLBACK_ERROR;
312 /* remove the bus from the list */
313 write_lock(&BusListLock);
314 if (prev) /* not at head */
315 prev->next = bus->next;
316 else
317 BusListHead = bus->next;
318 BusListCount--;
319 write_unlock(&BusListLock);
320 break;
324 if (!bus) {
325 LOGERR("CONTROLVM_BUS_DESTROY Failed: failed to find bus %d.\n",
326 busNo);
327 read_unlock(&BusListLock);
328 return CONTROLVM_RESP_ERROR_ALREADY_DONE;
330 if (bus->pBusChannel) {
331 uislib_iounmap(bus->pBusChannel);
332 bus->pBusChannel = NULL;
335 kfree(bus);
336 return CONTROLVM_RESP_SUCCESS;
339 static int
340 create_device(CONTROLVM_MESSAGE *msg, char *buf)
342 struct device_info *dev;
343 struct bus_info *bus;
344 u32 busNo, devNo;
345 int result = CONTROLVM_RESP_SUCCESS;
346 U64 minSize = MIN_IO_CHANNEL_SIZE;
347 ReqHandlerInfo_t *pReqHandler;
349 busNo = msg->cmd.createDevice.busNo;
350 devNo = msg->cmd.createDevice.devNo;
352 POSTCODE_LINUX_4(DEVICE_CREATE_ENTRY_PC, devNo, busNo,
353 POSTCODE_SEVERITY_INFO);
355 dev = kzalloc(sizeof(struct device_info), GFP_ATOMIC);
356 if (!dev) {
357 LOGERR("CONTROLVM_DEVICE_CREATE Failed: kmalloc for dev failed.\n");
358 POSTCODE_LINUX_4(DEVICE_CREATE_FAILURE_PC, devNo, busNo,
359 POSTCODE_SEVERITY_ERR);
360 return CONTROLVM_RESP_ERROR_KMALLOC_FAILED;
363 dev->channelTypeGuid = msg->cmd.createDevice.dataTypeGuid;
364 dev->intr = msg->cmd.createDevice.intr;
365 dev->channelAddr = msg->cmd.createDevice.channelAddr;
366 dev->busNo = busNo;
367 dev->devNo = devNo;
368 sema_init(&dev->interrupt_callback_lock, 1); /* unlocked */
369 sprintf(dev->devid, "vbus%u:dev%u", (unsigned) busNo, (unsigned) devNo);
370 /* map the channel memory for the device. */
371 if (msg->hdr.Flags.testMessage)
372 dev->chanptr = (void __iomem *)__va(dev->channelAddr);
373 else {
374 pReqHandler = ReqHandlerFind(dev->channelTypeGuid);
375 if (pReqHandler)
376 /* generic service handler registered for this
377 * channel
379 minSize = pReqHandler->min_channel_bytes;
380 if (minSize > msg->cmd.createDevice.channelBytes) {
381 LOGERR("CONTROLVM_DEVICE_CREATE Failed: channel size is too small, channel size:0x%lx, required size:0x%lx",
382 (ulong) msg->cmd.createDevice.channelBytes,
383 (ulong) minSize);
384 POSTCODE_LINUX_4(DEVICE_CREATE_FAILURE_PC, devNo, busNo,
385 POSTCODE_SEVERITY_ERR);
386 result = CONTROLVM_RESP_ERROR_CHANNEL_SIZE_TOO_SMALL;
387 goto Away;
389 dev->chanptr =
390 uislib_ioremap_cache(dev->channelAddr,
391 msg->cmd.createDevice.channelBytes);
392 if (!dev->chanptr) {
393 LOGERR("CONTROLVM_DEVICE_CREATE Failed: ioremap_cache of channelAddr:%Lx for channelBytes:%llu failed",
394 dev->channelAddr,
395 msg->cmd.createDevice.channelBytes);
396 result = CONTROLVM_RESP_ERROR_IOREMAP_FAILED;
397 POSTCODE_LINUX_4(DEVICE_CREATE_FAILURE_PC, devNo, busNo,
398 POSTCODE_SEVERITY_ERR);
399 goto Away;
402 dev->devInstGuid = msg->cmd.createDevice.devInstGuid;
403 dev->channelBytes = msg->cmd.createDevice.channelBytes;
405 read_lock(&BusListLock);
406 for (bus = BusListHead; bus; bus = bus->next) {
407 if (bus->busNo == busNo) {
408 /* make sure the device number is valid */
409 if (devNo >= bus->deviceCount) {
410 LOGERR("CONTROLVM_DEVICE_CREATE Failed: device (%d) >= deviceCount (%d).",
411 devNo, bus->deviceCount);
412 result = CONTROLVM_RESP_ERROR_MAX_DEVICES;
413 POSTCODE_LINUX_4(DEVICE_CREATE_FAILURE_PC,
414 devNo, busNo,
415 POSTCODE_SEVERITY_ERR);
416 read_unlock(&BusListLock);
417 goto Away;
419 /* make sure this device is not already set */
420 if (bus->device[devNo]) {
421 LOGERR("CONTROLVM_DEVICE_CREATE Failed: device %d is already exists.",
422 devNo);
423 POSTCODE_LINUX_4(DEVICE_CREATE_FAILURE_PC,
424 devNo, busNo,
425 POSTCODE_SEVERITY_ERR);
426 result = CONTROLVM_RESP_ERROR_ALREADY_DONE;
427 read_unlock(&BusListLock);
428 goto Away;
430 read_unlock(&BusListLock);
431 /* the msg is bound for virtpci; send
432 * guest_msgs struct to callback
434 if (!msg->hdr.Flags.server) {
435 struct guest_msgs cmd;
436 if (!uuid_le_cmp(dev->channelTypeGuid,
437 UltraVhbaChannelProtocolGuid)) {
438 wait_for_valid_guid(&((CHANNEL_HEADER
439 __iomem *) (dev->
440 chanptr))->
441 Type);
442 if (!ULTRA_VHBA_CHANNEL_OK_CLIENT
443 (dev->chanptr, NULL)) {
444 LOGERR("CONTROLVM_DEVICE_CREATE Failed:[CLIENT]VHBA dev %d chan invalid.",
445 devNo);
446 POSTCODE_LINUX_4
447 (DEVICE_CREATE_FAILURE_PC,
448 devNo, busNo,
449 POSTCODE_SEVERITY_ERR);
450 result = CONTROLVM_RESP_ERROR_CHANNEL_INVALID;
451 goto Away;
453 cmd.msgtype = GUEST_ADD_VHBA;
454 cmd.add_vhba.chanptr = dev->chanptr;
455 cmd.add_vhba.busNo = busNo;
456 cmd.add_vhba.deviceNo = devNo;
457 cmd.add_vhba.devInstGuid =
458 dev->devInstGuid;
459 cmd.add_vhba.intr = dev->intr;
460 } else
461 if (!uuid_le_cmp(dev->channelTypeGuid,
462 UltraVnicChannelProtocolGuid)) {
463 wait_for_valid_guid(&((CHANNEL_HEADER
464 __iomem *) (dev->
465 chanptr))->
466 Type);
467 if (!ULTRA_VNIC_CHANNEL_OK_CLIENT
468 (dev->chanptr, NULL)) {
469 LOGERR("CONTROLVM_DEVICE_CREATE Failed: VNIC[CLIENT] dev %d chan invalid.",
470 devNo);
471 POSTCODE_LINUX_4
472 (DEVICE_CREATE_FAILURE_PC,
473 devNo, busNo,
474 POSTCODE_SEVERITY_ERR);
475 result = CONTROLVM_RESP_ERROR_CHANNEL_INVALID;
476 goto Away;
478 cmd.msgtype = GUEST_ADD_VNIC;
479 cmd.add_vnic.chanptr = dev->chanptr;
480 cmd.add_vnic.busNo = busNo;
481 cmd.add_vnic.deviceNo = devNo;
482 cmd.add_vnic.devInstGuid =
483 dev->devInstGuid;
484 cmd.add_vhba.intr = dev->intr;
485 } else {
486 LOGERR("CONTROLVM_DEVICE_CREATE Failed: unknown channelTypeGuid.\n");
487 POSTCODE_LINUX_4
488 (DEVICE_CREATE_FAILURE_PC, devNo,
489 busNo, POSTCODE_SEVERITY_ERR);
490 result = CONTROLVM_RESP_ERROR_CHANNEL_TYPE_UNKNOWN;
491 goto Away;
494 if (!VirtControlChanFunc) {
495 LOGERR("CONTROLVM_DEVICE_CREATE Failed: virtpci callback not registered.");
496 POSTCODE_LINUX_4
497 (DEVICE_CREATE_FAILURE_PC, devNo,
498 busNo, POSTCODE_SEVERITY_ERR);
499 result = CONTROLVM_RESP_ERROR_VIRTPCI_DRIVER_FAILURE;
500 goto Away;
503 if (!VirtControlChanFunc(&cmd)) {
504 LOGERR("CONTROLVM_DEVICE_CREATE Failed: virtpci GUEST_ADD_[VHBA||VNIC] returned error.");
505 POSTCODE_LINUX_4
506 (DEVICE_CREATE_FAILURE_PC, devNo,
507 busNo, POSTCODE_SEVERITY_ERR);
508 result = CONTROLVM_RESP_ERROR_VIRTPCI_DRIVER_CALLBACK_ERROR;
509 goto Away;
512 bus->device[devNo] = dev;
513 POSTCODE_LINUX_4(DEVICE_CREATE_SUCCESS_PC, devNo, busNo,
514 POSTCODE_SEVERITY_INFO);
515 return CONTROLVM_RESP_SUCCESS;
518 read_unlock(&BusListLock);
520 LOGERR("CONTROLVM_DEVICE_CREATE Failed: failed to find bus %d.", busNo);
521 POSTCODE_LINUX_4(DEVICE_CREATE_FAILURE_PC, devNo, busNo,
522 POSTCODE_SEVERITY_ERR);
523 result = CONTROLVM_RESP_ERROR_BUS_INVALID;
525 Away:
526 if (!msg->hdr.Flags.testMessage) {
527 uislib_iounmap(dev->chanptr);
528 dev->chanptr = NULL;
531 kfree(dev);
532 return result;
535 static int
536 pause_device(CONTROLVM_MESSAGE *msg)
538 u32 busNo, devNo;
539 struct bus_info *bus;
540 struct device_info *dev;
541 struct guest_msgs cmd;
543 busNo = msg->cmd.deviceChangeState.busNo;
544 devNo = msg->cmd.deviceChangeState.devNo;
546 read_lock(&BusListLock);
547 for (bus = BusListHead; bus; bus = bus->next) {
548 if (bus->busNo == busNo) {
549 /* make sure the device number is valid */
550 if (devNo >= bus->deviceCount) {
551 LOGERR("CONTROLVM_DEVICE_CHANGESTATE:pause Failed: device(%d) >= deviceCount(%d).",
552 devNo, bus->deviceCount);
553 read_unlock(&BusListLock);
554 return CONTROLVM_RESP_ERROR_DEVICE_INVALID;
556 /* make sure this device exists */
557 dev = bus->device[devNo];
558 if (!dev) {
559 LOGERR("CONTROLVM_DEVICE_CHANGESTATE:pause Failed: device %d does not exist.",
560 devNo);
561 read_unlock(&BusListLock);
562 return CONTROLVM_RESP_ERROR_ALREADY_DONE;
564 read_unlock(&BusListLock);
565 /* the msg is bound for virtpci; send
566 * guest_msgs struct to callback
568 if (!uuid_le_cmp(dev->channelTypeGuid,
569 UltraVhbaChannelProtocolGuid)) {
570 cmd.msgtype = GUEST_PAUSE_VHBA;
571 cmd.pause_vhba.chanptr = dev->chanptr;
572 } else
573 if (!uuid_le_cmp(dev->channelTypeGuid,
574 UltraVnicChannelProtocolGuid)) {
575 cmd.msgtype = GUEST_PAUSE_VNIC;
576 cmd.pause_vnic.chanptr = dev->chanptr;
577 } else {
578 LOGERR("CONTROLVM_DEVICE_CHANGESTATE:pause Failed: unknown channelTypeGuid.\n");
579 return
580 CONTROLVM_RESP_ERROR_CHANNEL_TYPE_UNKNOWN;
583 if (!VirtControlChanFunc) {
584 LOGERR("CONTROLVM_DEVICE_CHANGESTATE Failed: virtpci callback not registered.");
585 return
586 CONTROLVM_RESP_ERROR_VIRTPCI_DRIVER_FAILURE;
589 if (!VirtControlChanFunc(&cmd)) {
590 LOGERR("CONTROLVM_DEVICE_CHANGESTATE:pause Failed: virtpci GUEST_PAUSE_[VHBA||VNIC] returned error.");
591 return CONTROLVM_RESP_ERROR_VIRTPCI_DRIVER_CALLBACK_ERROR;
593 break;
597 if (!bus) {
598 LOGERR("CONTROLVM_DEVICE_CHANGESTATE:pause Failed: bus %d does not exist",
599 busNo);
600 read_unlock(&BusListLock);
601 return CONTROLVM_RESP_ERROR_BUS_INVALID;
604 return CONTROLVM_RESP_SUCCESS;
607 static int
608 resume_device(CONTROLVM_MESSAGE *msg)
610 u32 busNo, devNo;
611 struct bus_info *bus;
612 struct device_info *dev;
613 struct guest_msgs cmd;
615 busNo = msg->cmd.deviceChangeState.busNo;
616 devNo = msg->cmd.deviceChangeState.devNo;
618 read_lock(&BusListLock);
619 for (bus = BusListHead; bus; bus = bus->next) {
620 if (bus->busNo == busNo) {
621 /* make sure the device number is valid */
622 if (devNo >= bus->deviceCount) {
623 LOGERR("CONTROLVM_DEVICE_CHANGESTATE:resume Failed: device(%d) >= deviceCount(%d).",
624 devNo, bus->deviceCount);
625 read_unlock(&BusListLock);
626 return CONTROLVM_RESP_ERROR_DEVICE_INVALID;
628 /* make sure this device exists */
629 dev = bus->device[devNo];
630 if (!dev) {
631 LOGERR("CONTROLVM_DEVICE_CHANGESTATE:resume Failed: device %d does not exist.",
632 devNo);
633 read_unlock(&BusListLock);
634 return CONTROLVM_RESP_ERROR_ALREADY_DONE;
636 read_unlock(&BusListLock);
637 /* the msg is bound for virtpci; send
638 * guest_msgs struct to callback
640 if (!uuid_le_cmp(dev->channelTypeGuid,
641 UltraVhbaChannelProtocolGuid)) {
642 cmd.msgtype = GUEST_RESUME_VHBA;
643 cmd.resume_vhba.chanptr = dev->chanptr;
644 } else
645 if (!uuid_le_cmp(dev->channelTypeGuid,
646 UltraVnicChannelProtocolGuid)) {
647 cmd.msgtype = GUEST_RESUME_VNIC;
648 cmd.resume_vnic.chanptr = dev->chanptr;
649 } else {
650 LOGERR("CONTROLVM_DEVICE_CHANGESTATE:resume Failed: unknown channelTypeGuid.\n");
651 return
652 CONTROLVM_RESP_ERROR_CHANNEL_TYPE_UNKNOWN;
655 if (!VirtControlChanFunc) {
656 LOGERR("CONTROLVM_DEVICE_CHANGESTATE Failed: virtpci callback not registered.");
657 return
658 CONTROLVM_RESP_ERROR_VIRTPCI_DRIVER_FAILURE;
661 if (!VirtControlChanFunc(&cmd)) {
662 LOGERR("CONTROLVM_DEVICE_CHANGESTATE:resume Failed: virtpci GUEST_RESUME_[VHBA||VNIC] returned error.");
663 return CONTROLVM_RESP_ERROR_VIRTPCI_DRIVER_CALLBACK_ERROR;
665 break;
669 if (!bus) {
670 LOGERR("CONTROLVM_DEVICE_CHANGESTATE:resume Failed: bus %d does not exist",
671 busNo);
672 read_unlock(&BusListLock);
673 return CONTROLVM_RESP_ERROR_BUS_INVALID;
676 return CONTROLVM_RESP_SUCCESS;
679 static int
680 destroy_device(CONTROLVM_MESSAGE *msg, char *buf)
682 u32 busNo, devNo;
683 struct bus_info *bus;
684 struct device_info *dev;
685 struct guest_msgs cmd;
687 busNo = msg->cmd.destroyDevice.busNo;
688 devNo = msg->cmd.destroyDevice.devNo;
690 read_lock(&BusListLock);
691 LOGINF("destroy_device called for busNo=%u, devNo=%u", busNo, devNo);
692 for (bus = BusListHead; bus; bus = bus->next) {
693 if (bus->busNo == busNo) {
694 /* make sure the device number is valid */
695 if (devNo >= bus->deviceCount) {
696 LOGERR("CONTROLVM_DEVICE_DESTORY Failed: device(%d) >= deviceCount(%d).",
697 devNo, bus->deviceCount);
698 read_unlock(&BusListLock);
699 return CONTROLVM_RESP_ERROR_DEVICE_INVALID;
701 /* make sure this device exists */
702 dev = bus->device[devNo];
703 if (!dev) {
704 LOGERR("CONTROLVM_DEVICE_DESTROY Failed: device %d does not exist.",
705 devNo);
706 read_unlock(&BusListLock);
707 return CONTROLVM_RESP_ERROR_ALREADY_DONE;
709 read_unlock(&BusListLock);
710 /* the msg is bound for virtpci; send
711 * guest_msgs struct to callback
713 if (!uuid_le_cmp(dev->channelTypeGuid,
714 UltraVhbaChannelProtocolGuid)) {
715 cmd.msgtype = GUEST_DEL_VHBA;
716 cmd.del_vhba.chanptr = dev->chanptr;
717 } else
718 if (!uuid_le_cmp(dev->channelTypeGuid,
719 UltraVnicChannelProtocolGuid)) {
720 cmd.msgtype = GUEST_DEL_VNIC;
721 cmd.del_vnic.chanptr = dev->chanptr;
722 } else {
723 LOGERR("CONTROLVM_DEVICE_DESTROY Failed: unknown channelTypeGuid.\n");
724 return
725 CONTROLVM_RESP_ERROR_CHANNEL_TYPE_UNKNOWN;
728 if (!VirtControlChanFunc) {
729 LOGERR("CONTROLVM_DEVICE_DESTORY Failed: virtpci callback not registered.");
730 return
731 CONTROLVM_RESP_ERROR_VIRTPCI_DRIVER_FAILURE;
734 if (!VirtControlChanFunc(&cmd)) {
735 LOGERR("CONTROLVM_DEVICE_DESTROY Failed: virtpci GUEST_DEL_[VHBA||VNIC] returned error.");
736 return CONTROLVM_RESP_ERROR_VIRTPCI_DRIVER_CALLBACK_ERROR;
738 /* you must disable channel interrupts BEFORE you unmap the channel,
739 * because if you unmap first, there may still be some activity going
740 * on which accesses the channel and you will get a "unable to handle
741 * kernel paging request"
743 if (dev->polling) {
744 LOGINF("calling uislib_disable_channel_interrupts");
745 uislib_disable_channel_interrupts(busNo, devNo);
747 /* unmap the channel memory for the device. */
748 if (!msg->hdr.Flags.testMessage) {
749 LOGINF("destroy_device, doing iounmap");
750 uislib_iounmap(dev->chanptr);
752 kfree(dev);
753 bus->device[devNo] = NULL;
754 break;
758 if (!bus) {
759 LOGERR("CONTROLVM_DEVICE_DESTROY Failed: bus %d does not exist",
760 busNo);
761 read_unlock(&BusListLock);
762 return CONTROLVM_RESP_ERROR_BUS_INVALID;
765 return CONTROLVM_RESP_SUCCESS;
768 static int
769 init_chipset(CONTROLVM_MESSAGE *msg, char *buf)
771 POSTCODE_LINUX_2(CHIPSET_INIT_ENTRY_PC, POSTCODE_SEVERITY_INFO);
773 MaxBusCount = msg->cmd.initChipset.busCount;
774 PlatformNumber = msg->cmd.initChipset.platformNumber;
775 PhysicalDataChan = 0;
777 /* We need to make sure we have our functions registered
778 * before processing messages. If we are a test vehicle the
779 * testMessage for init_chipset will be set. We can ignore the
780 * waits for the callbacks, since this will be manually entered
781 * from a user. If no testMessage is set, we will wait for the
782 * functions.
784 if (!msg->hdr.Flags.testMessage)
785 WAIT_ON_CALLBACK(VirtControlChanFunc);
787 chipset_inited = 1;
788 POSTCODE_LINUX_2(CHIPSET_INIT_EXIT_PC, POSTCODE_SEVERITY_INFO);
790 return CONTROLVM_RESP_SUCCESS;
793 static int
794 delete_bus_glue(u32 busNo)
796 CONTROLVM_MESSAGE msg;
798 init_msg_header(&msg, CONTROLVM_BUS_DESTROY, 0, 0);
799 msg.cmd.destroyBus.busNo = busNo;
800 if (destroy_bus(&msg, NULL) != CONTROLVM_RESP_SUCCESS) {
801 LOGERR("destroy_bus failed. busNo=0x%x\n", busNo);
802 return 0;
804 return 1;
807 static int
808 delete_device_glue(u32 busNo, u32 devNo)
810 CONTROLVM_MESSAGE msg;
812 init_msg_header(&msg, CONTROLVM_DEVICE_DESTROY, 0, 0);
813 msg.cmd.destroyDevice.busNo = busNo;
814 msg.cmd.destroyDevice.devNo = devNo;
815 if (destroy_device(&msg, NULL) != CONTROLVM_RESP_SUCCESS) {
816 LOGERR("destroy_device failed. busNo=0x%x devNo=0x%x\n", busNo,
817 devNo);
818 return 0;
820 return 1;
824 uislib_client_inject_add_bus(u32 busNo, uuid_le instGuid,
825 U64 channelAddr, ulong nChannelBytes)
827 CONTROLVM_MESSAGE msg;
829 LOGINF("enter busNo=0x%x\n", busNo);
830 /* step 0: init the chipset */
831 POSTCODE_LINUX_3(CHIPSET_INIT_ENTRY_PC, busNo, POSTCODE_SEVERITY_INFO);
833 if (!chipset_inited) {
834 /* step: initialize the chipset */
835 init_msg_header(&msg, CONTROLVM_CHIPSET_INIT, 0, 0);
836 /* this change is needed so that console will come up
837 * OK even when the bus 0 create comes in late. If the
838 * bus 0 create is the first create, then the add_vnic
839 * will work fine, but if the bus 0 create arrives
840 * after number 4, then the add_vnic will fail, and the
841 * ultraboot will fail.
843 msg.cmd.initChipset.busCount = 23;
844 msg.cmd.initChipset.switchCount = 0;
845 if (init_chipset(&msg, NULL) != CONTROLVM_RESP_SUCCESS) {
846 LOGERR("init_chipset failed.\n");
847 return 0;
849 LOGINF("chipset initialized\n");
850 POSTCODE_LINUX_3(CHIPSET_INIT_EXIT_PC, busNo,
851 POSTCODE_SEVERITY_INFO);
854 /* step 1: create a bus */
855 POSTCODE_LINUX_3(BUS_CREATE_ENTRY_PC, busNo, POSTCODE_SEVERITY_WARNING);
856 init_msg_header(&msg, CONTROLVM_BUS_CREATE, 0, 0);
857 msg.cmd.createBus.busNo = busNo;
858 msg.cmd.createBus.deviceCount = 23; /* devNo+1; */
859 msg.cmd.createBus.channelAddr = channelAddr;
860 msg.cmd.createBus.channelBytes = nChannelBytes;
861 if (create_bus(&msg, NULL) != CONTROLVM_RESP_SUCCESS) {
862 LOGERR("create_bus failed.\n");
863 POSTCODE_LINUX_3(BUS_CREATE_FAILURE_PC, busNo,
864 POSTCODE_SEVERITY_ERR);
865 return 0;
867 POSTCODE_LINUX_3(BUS_CREATE_EXIT_PC, busNo, POSTCODE_SEVERITY_INFO);
869 return 1;
871 EXPORT_SYMBOL_GPL(uislib_client_inject_add_bus);
875 uislib_client_inject_del_bus(u32 busNo)
877 return delete_bus_glue(busNo);
879 EXPORT_SYMBOL_GPL(uislib_client_inject_del_bus);
882 uislib_client_inject_pause_vhba(u32 busNo, u32 devNo)
884 CONTROLVM_MESSAGE msg;
885 int rc;
887 init_msg_header(&msg, CONTROLVM_DEVICE_CHANGESTATE, 0, 0);
888 msg.cmd.deviceChangeState.busNo = busNo;
889 msg.cmd.deviceChangeState.devNo = devNo;
890 msg.cmd.deviceChangeState.state = SegmentStateStandby;
891 rc = pause_device(&msg);
892 if (rc != CONTROLVM_RESP_SUCCESS) {
893 LOGERR("VHBA pause_device failed. busNo=0x%x devNo=0x%x\n",
894 busNo, devNo);
895 return rc;
897 return 0;
899 EXPORT_SYMBOL_GPL(uislib_client_inject_pause_vhba);
902 uislib_client_inject_resume_vhba(u32 busNo, u32 devNo)
904 CONTROLVM_MESSAGE msg;
905 int rc;
907 init_msg_header(&msg, CONTROLVM_DEVICE_CHANGESTATE, 0, 0);
908 msg.cmd.deviceChangeState.busNo = busNo;
909 msg.cmd.deviceChangeState.devNo = devNo;
910 msg.cmd.deviceChangeState.state = SegmentStateRunning;
911 rc = resume_device(&msg);
912 if (rc != CONTROLVM_RESP_SUCCESS) {
913 LOGERR("VHBA resume_device failed. busNo=0x%x devNo=0x%x\n",
914 busNo, devNo);
915 return rc;
917 return 0;
920 EXPORT_SYMBOL_GPL(uislib_client_inject_resume_vhba);
923 uislib_client_inject_add_vhba(u32 busNo, u32 devNo,
924 U64 phys_chan_addr, u32 chan_bytes,
925 int is_test_addr, uuid_le instGuid,
926 struct InterruptInfo *intr)
928 CONTROLVM_MESSAGE msg;
930 LOGINF(" enter busNo=0x%x devNo=0x%x\n", busNo, devNo);
931 /* chipset init'ed with bus bus has been previously created -
932 * Verify it still exists step 2: create the VHBA device on the
933 * bus
935 POSTCODE_LINUX_4(VHBA_CREATE_ENTRY_PC, devNo, busNo,
936 POSTCODE_SEVERITY_INFO);
938 init_msg_header(&msg, CONTROLVM_DEVICE_CREATE, 0, 0);
939 if (is_test_addr)
940 /* signify that the physical channel address does NOT
941 * need to be ioremap()ed
943 msg.hdr.Flags.testMessage = 1;
944 msg.cmd.createDevice.busNo = busNo;
945 msg.cmd.createDevice.devNo = devNo;
946 msg.cmd.createDevice.devInstGuid = instGuid;
947 if (intr)
948 msg.cmd.createDevice.intr = *intr;
949 else
950 memset(&msg.cmd.createDevice.intr, 0,
951 sizeof(struct InterruptInfo));
952 msg.cmd.createDevice.channelAddr = phys_chan_addr;
953 if (chan_bytes < MIN_IO_CHANNEL_SIZE) {
954 LOGERR("wrong channel size.chan_bytes = 0x%x IO_CHANNEL_SIZE= 0x%x\n",
955 chan_bytes, (unsigned int) MIN_IO_CHANNEL_SIZE);
956 POSTCODE_LINUX_4(VHBA_CREATE_FAILURE_PC, chan_bytes,
957 MIN_IO_CHANNEL_SIZE, POSTCODE_SEVERITY_ERR);
958 return 0;
960 msg.cmd.createDevice.channelBytes = chan_bytes;
961 msg.cmd.createDevice.dataTypeGuid = UltraVhbaChannelProtocolGuid;
962 if (create_device(&msg, NULL) != CONTROLVM_RESP_SUCCESS) {
963 LOGERR("VHBA create_device failed.\n");
964 POSTCODE_LINUX_4(VHBA_CREATE_FAILURE_PC, devNo, busNo,
965 POSTCODE_SEVERITY_ERR);
966 return 0;
968 POSTCODE_LINUX_4(VHBA_CREATE_SUCCESS_PC, devNo, busNo,
969 POSTCODE_SEVERITY_INFO);
970 return 1;
972 EXPORT_SYMBOL_GPL(uislib_client_inject_add_vhba);
975 uislib_client_inject_del_vhba(u32 busNo, u32 devNo)
977 return delete_device_glue(busNo, devNo);
979 EXPORT_SYMBOL_GPL(uislib_client_inject_del_vhba);
982 uislib_client_inject_add_vnic(u32 busNo, u32 devNo,
983 U64 phys_chan_addr, u32 chan_bytes,
984 int is_test_addr, uuid_le instGuid,
985 struct InterruptInfo *intr)
987 CONTROLVM_MESSAGE msg;
989 LOGINF(" enter busNo=0x%x devNo=0x%x\n", busNo, devNo);
990 /* chipset init'ed with bus bus has been previously created -
991 * Verify it still exists step 2: create the VNIC device on the
992 * bus
994 POSTCODE_LINUX_4(VNIC_CREATE_ENTRY_PC, devNo, busNo,
995 POSTCODE_SEVERITY_INFO);
997 init_msg_header(&msg, CONTROLVM_DEVICE_CREATE, 0, 0);
998 if (is_test_addr)
999 /* signify that the physical channel address does NOT
1000 * need to be ioremap()ed
1002 msg.hdr.Flags.testMessage = 1;
1003 msg.cmd.createDevice.busNo = busNo;
1004 msg.cmd.createDevice.devNo = devNo;
1005 msg.cmd.createDevice.devInstGuid = instGuid;
1006 if (intr)
1007 msg.cmd.createDevice.intr = *intr;
1008 else
1009 memset(&msg.cmd.createDevice.intr, 0,
1010 sizeof(struct InterruptInfo));
1011 msg.cmd.createDevice.channelAddr = phys_chan_addr;
1012 if (chan_bytes < MIN_IO_CHANNEL_SIZE) {
1013 LOGERR("wrong channel size.chan_bytes = 0x%x IO_CHANNEL_SIZE= 0x%x\n",
1014 chan_bytes, (unsigned int) MIN_IO_CHANNEL_SIZE);
1015 POSTCODE_LINUX_4(VNIC_CREATE_FAILURE_PC, chan_bytes,
1016 MIN_IO_CHANNEL_SIZE, POSTCODE_SEVERITY_ERR);
1017 return 0;
1019 msg.cmd.createDevice.channelBytes = chan_bytes;
1020 msg.cmd.createDevice.dataTypeGuid = UltraVnicChannelProtocolGuid;
1021 if (create_device(&msg, NULL) != CONTROLVM_RESP_SUCCESS) {
1022 LOGERR("VNIC create_device failed.\n");
1023 POSTCODE_LINUX_4(VNIC_CREATE_FAILURE_PC, devNo, busNo,
1024 POSTCODE_SEVERITY_ERR);
1025 return 0;
1028 POSTCODE_LINUX_4(VNIC_CREATE_SUCCESS_PC, devNo, busNo,
1029 POSTCODE_SEVERITY_INFO);
1030 return 1;
1032 EXPORT_SYMBOL_GPL(uislib_client_inject_add_vnic);
1035 uislib_client_inject_pause_vnic(u32 busNo, u32 devNo)
1037 CONTROLVM_MESSAGE msg;
1038 int rc;
1040 init_msg_header(&msg, CONTROLVM_DEVICE_CHANGESTATE, 0, 0);
1041 msg.cmd.deviceChangeState.busNo = busNo;
1042 msg.cmd.deviceChangeState.devNo = devNo;
1043 msg.cmd.deviceChangeState.state = SegmentStateStandby;
1044 rc = pause_device(&msg);
1045 if (rc != CONTROLVM_RESP_SUCCESS) {
1046 LOGERR("VNIC pause_device failed. busNo=0x%x devNo=0x%x\n",
1047 busNo, devNo);
1048 return -1;
1050 return 0;
1052 EXPORT_SYMBOL_GPL(uislib_client_inject_pause_vnic);
1055 uislib_client_inject_resume_vnic(u32 busNo, u32 devNo)
1057 CONTROLVM_MESSAGE msg;
1058 int rc;
1060 init_msg_header(&msg, CONTROLVM_DEVICE_CHANGESTATE, 0, 0);
1061 msg.cmd.deviceChangeState.busNo = busNo;
1062 msg.cmd.deviceChangeState.devNo = devNo;
1063 msg.cmd.deviceChangeState.state = SegmentStateRunning;
1064 rc = resume_device(&msg);
1065 if (rc != CONTROLVM_RESP_SUCCESS) {
1066 LOGERR("VNIC resume_device failed. busNo=0x%x devNo=0x%x\n",
1067 busNo, devNo);
1068 return -1;
1070 return 0;
1073 EXPORT_SYMBOL_GPL(uislib_client_inject_resume_vnic);
1076 uislib_client_inject_del_vnic(u32 busNo, u32 devNo)
1078 return delete_device_glue(busNo, devNo);
1080 EXPORT_SYMBOL_GPL(uislib_client_inject_del_vnic);
1082 static int
1083 uislib_client_add_vnic(u32 busNo)
1085 BOOL busCreated = FALSE;
1086 int devNo = 0; /* Default to 0, since only one device
1087 * will be created for this bus... */
1088 CONTROLVM_MESSAGE msg;
1090 init_msg_header(&msg, CONTROLVM_BUS_CREATE, 0, 0);
1091 msg.hdr.Flags.testMessage = 1;
1092 msg.cmd.createBus.busNo = busNo;
1093 msg.cmd.createBus.deviceCount = 4;
1094 msg.cmd.createBus.channelAddr = 0;
1095 msg.cmd.createBus.channelBytes = 0;
1096 if (create_bus(&msg, NULL) != CONTROLVM_RESP_SUCCESS) {
1097 LOGERR("client create_bus failed");
1098 return 0;
1100 busCreated = TRUE;
1102 init_msg_header(&msg, CONTROLVM_DEVICE_CREATE, 0, 0);
1103 msg.hdr.Flags.testMessage = 1;
1104 msg.cmd.createDevice.busNo = busNo;
1105 msg.cmd.createDevice.devNo = devNo;
1106 msg.cmd.createDevice.devInstGuid = NULL_UUID_LE;
1107 memset(&msg.cmd.createDevice.intr, 0, sizeof(struct InterruptInfo));
1108 msg.cmd.createDevice.channelAddr = PhysicalDataChan;
1109 msg.cmd.createDevice.channelBytes = MIN_IO_CHANNEL_SIZE;
1110 msg.cmd.createDevice.dataTypeGuid = UltraVnicChannelProtocolGuid;
1111 if (create_device(&msg, NULL) != CONTROLVM_RESP_SUCCESS) {
1112 LOGERR("client create_device failed");
1113 goto AwayCleanup;
1116 return 1;
1118 AwayCleanup:
1119 if (busCreated) {
1120 init_msg_header(&msg, CONTROLVM_BUS_DESTROY, 0, 0);
1121 msg.hdr.Flags.testMessage = 1;
1122 msg.cmd.destroyBus.busNo = busNo;
1123 if (destroy_bus(&msg, NULL) != CONTROLVM_RESP_SUCCESS)
1124 LOGERR("client destroy_bus failed.\n");
1127 return 0;
1128 } /* end uislib_client_add_vnic */
1129 EXPORT_SYMBOL_GPL(uislib_client_add_vnic);
1131 static int
1132 uislib_client_delete_vnic(u32 busNo)
1134 int devNo = 0; /* Default to 0, since only one device
1135 * will be created for this bus... */
1136 CONTROLVM_MESSAGE msg;
1138 init_msg_header(&msg, CONTROLVM_DEVICE_DESTROY, 0, 0);
1139 msg.hdr.Flags.testMessage = 1;
1140 msg.cmd.destroyDevice.busNo = busNo;
1141 msg.cmd.destroyDevice.devNo = devNo;
1142 if (destroy_device(&msg, NULL) != CONTROLVM_RESP_SUCCESS) {
1143 /* Don't error exit - try to see if bus can be destroyed... */
1144 LOGERR("client destroy_device failed.\n");
1147 init_msg_header(&msg, CONTROLVM_BUS_DESTROY, 0, 0);
1148 msg.hdr.Flags.testMessage = 1;
1149 msg.cmd.destroyBus.busNo = busNo;
1150 if (destroy_bus(&msg, NULL) != CONTROLVM_RESP_SUCCESS)
1151 LOGERR("client destroy_bus failed.\n");
1153 return 1;
1155 EXPORT_SYMBOL_GPL(uislib_client_delete_vnic);
1156 /* end client_delete_vnic */
1158 void *
1159 uislib_cache_alloc(struct kmem_cache *cur_pool, char *fn, int ln)
1161 /* __GFP_NORETRY means "ok to fail", meaning kmalloc() can
1162 * return NULL. If you do NOT specify __GFP_NORETRY, Linux
1163 * will go to extreme measures to get memory for you (like,
1164 * invoke oom killer), which will probably cripple the system.
1166 void *p = kmem_cache_alloc(cur_pool, GFP_ATOMIC | __GFP_NORETRY);
1167 if (p == NULL) {
1168 LOGERR("uislib_malloc failed to alloc uiscmdrsp @%s:%d",
1169 fn, ln);
1170 return NULL;
1172 return p;
1174 EXPORT_SYMBOL_GPL(uislib_cache_alloc);
1176 void
1177 uislib_cache_free(struct kmem_cache *cur_pool, void *p, char *fn, int ln)
1179 if (p == NULL) {
1180 LOGERR("uislib_free NULL pointer @%s:%d", fn, ln);
1181 return;
1183 kmem_cache_free(cur_pool, p);
1185 EXPORT_SYMBOL_GPL(uislib_cache_free);
1187 /*****************************************************/
1188 /* proc filesystem callback functions */
1189 /*****************************************************/
1191 #define PLINE(...) uisutil_add_proc_line_ex(&tot, buff, \
1192 buff_len, __VA_ARGS__)
1194 static int
1195 info_debugfs_read_helper(char **buff, int *buff_len)
1197 int i, tot = 0;
1198 struct bus_info *bus;
1200 if (PLINE("\nBuses:\n") < 0)
1201 goto err_done;
1203 read_lock(&BusListLock);
1204 for (bus = BusListHead; bus; bus = bus->next) {
1206 if (PLINE(" bus=0x%p, busNo=%d, deviceCount=%d\n",
1207 bus, bus->busNo, bus->deviceCount) < 0)
1208 goto err_done_unlock;
1211 if (PLINE(" Devices:\n") < 0)
1212 goto err_done_unlock;
1214 for (i = 0; i < bus->deviceCount; i++) {
1215 if (bus->device[i]) {
1216 if (PLINE(" busNo %d, device[%i]: 0x%p, chanptr=0x%p, swtch=0x%p\n",
1217 bus->busNo, i, bus->device[i],
1218 bus->device[i]->chanptr,
1219 bus->device[i]->swtch) < 0)
1220 goto err_done_unlock;
1222 if (PLINE(" first_busy_cnt=%llu, moved_to_tail_cnt=%llu, last_on_list_cnt=%llu\n",
1223 bus->device[i]->first_busy_cnt,
1224 bus->device[i]->moved_to_tail_cnt,
1225 bus->device[i]->last_on_list_cnt) < 0)
1226 goto err_done_unlock;
1230 read_unlock(&BusListLock);
1232 if (PLINE("UisUtils_Registered_Services: %d\n",
1233 atomic_read(&UisUtils_Registered_Services)) < 0)
1234 goto err_done;
1235 if (PLINE("cycles_before_wait %llu wait_cycles:%llu\n",
1236 cycles_before_wait, wait_cycles) < 0)
1237 goto err_done;
1238 if (PLINE("tot_wakeup_cnt %llu:tot_wait_cnt %llu:tot_schedule_cnt %llu\n",
1239 tot_wakeup_cnt, tot_wait_cnt, tot_schedule_cnt) < 0)
1240 goto err_done;
1241 if (PLINE("en_smart_wakeup %d\n", en_smart_wakeup) < 0)
1242 goto err_done;
1243 if (PLINE("tot_moved_to_tail_cnt %llu\n", tot_moved_to_tail_cnt) < 0)
1244 goto err_done;
1246 return tot;
1248 err_done_unlock:
1249 read_unlock(&BusListLock);
1250 err_done:
1251 return -1;
1254 static ssize_t
1255 info_debugfs_read(struct file *file, char __user *buf,
1256 size_t len, loff_t *offset)
1258 char *temp;
1259 int totalBytes = 0;
1260 int remaining_bytes = PROC_READ_BUFFER_SIZE;
1262 /* *start = buf; */
1263 if (ProcReadBuffer == NULL) {
1264 DBGINF("ProcReadBuffer == NULL; allocating buffer.\n.");
1265 ProcReadBuffer = vmalloc(PROC_READ_BUFFER_SIZE);
1267 if (ProcReadBuffer == NULL) {
1268 LOGERR("failed to allocate buffer to provide proc data.\n");
1269 return -ENOMEM;
1273 temp = ProcReadBuffer;
1275 if ((*offset == 0) || (!ProcReadBufferValid)) {
1276 DBGINF("calling info_debugfs_read_helper.\n");
1277 /* if the read fails, then -1 will be returned */
1278 totalBytes = info_debugfs_read_helper(&temp, &remaining_bytes);
1279 ProcReadBufferValid = 1;
1280 } else
1281 totalBytes = strlen(ProcReadBuffer);
1283 return simple_read_from_buffer(buf, len, offset,
1284 ProcReadBuffer, totalBytes);
1287 static struct device_info *
1288 find_dev(u32 busNo, u32 devNo)
1290 struct bus_info *bus;
1291 struct device_info *dev = NULL;
1293 read_lock(&BusListLock);
1294 for (bus = BusListHead; bus; bus = bus->next) {
1295 if (bus->busNo == busNo) {
1296 /* make sure the device number is valid */
1297 if (devNo >= bus->deviceCount) {
1298 LOGERR("%s bad busNo, devNo=%d,%d",
1299 __func__,
1300 (int) (busNo), (int) (devNo));
1301 goto Away;
1303 dev = bus->device[devNo];
1304 if (!dev)
1305 LOGERR("%s bad busNo, devNo=%d,%d",
1306 __func__,
1307 (int) (busNo), (int) (devNo));
1308 goto Away;
1311 Away:
1312 read_unlock(&BusListLock);
1313 return dev;
1316 /* This thread calls the "interrupt" function for each device that has
1317 * enabled such using uislib_enable_channel_interrupts(). The "interrupt"
1318 * function typically reads and processes the devices's channel input
1319 * queue. This thread repeatedly does this, until the thread is told to stop
1320 * (via uisthread_stop()). Sleeping rules:
1321 * - If we have called the "interrupt" function for all devices, and all of
1322 * them have reported "nothing processed" (returned 0), then we will go to
1323 * sleep for a maximum of POLLJIFFIES_NORMAL jiffies.
1324 * - If anyone calls uislib_force_channel_interrupt(), the above jiffy
1325 * sleep will be interrupted, and we will resume calling the "interrupt"
1326 * function for all devices.
1327 * - The list of devices is dynamically re-ordered in order to
1328 * attempt to preserve fairness. Whenever we spin thru the list of
1329 * devices and call the dev->interrupt() function, if we find
1330 * devices which report that there is still more work to do, the
1331 * the first such device we find is moved to the end of the device
1332 * list. This ensures that extremely busy devices don't starve out
1333 * less-busy ones.
1336 static int
1337 Process_Incoming(void *v)
1339 unsigned long long cur_cycles, old_cycles, idle_cycles, delta_cycles;
1340 struct list_head *new_tail = NULL;
1341 int i;
1342 UIS_DAEMONIZE("dev_incoming");
1343 for (i = 0; i < 16; i++) {
1344 old_cycles = get_cycles();
1345 wait_event_timeout(Wakeup_Polling_Device_Channels,
1346 0, POLLJIFFIES_NORMAL);
1347 cur_cycles = get_cycles();
1348 if (wait_cycles == 0) {
1349 wait_cycles = (cur_cycles - old_cycles);
1350 } else {
1351 if (wait_cycles < (cur_cycles - old_cycles))
1352 wait_cycles = (cur_cycles - old_cycles);
1355 LOGINF("wait_cycles=%llu", wait_cycles);
1356 cycles_before_wait = wait_cycles;
1357 idle_cycles = 0;
1358 Go_Polling_Device_Channels = 0;
1359 while (1) {
1360 struct list_head *lelt, *tmp;
1361 struct device_info *dev = NULL;
1363 /* poll each channel for input */
1364 LOCKSEM_UNINTERRUPTIBLE(&Lock_Polling_Device_Channels);
1365 new_tail = NULL;
1366 list_for_each_safe(lelt, tmp, &List_Polling_Device_Channels) {
1367 int rc = 0;
1368 dev = list_entry(lelt, struct device_info,
1369 list_polling_device_channels);
1370 LOCKSEM_UNINTERRUPTIBLE(&dev->interrupt_callback_lock);
1371 if (dev->interrupt)
1372 rc = dev->interrupt(dev->interrupt_context);
1373 else
1374 continue;
1375 UNLOCKSEM(&dev->interrupt_callback_lock);
1376 if (rc) {
1377 /* dev->interrupt returned, but there
1378 * is still more work to do.
1379 * Reschedule work to occur as soon as
1380 * possible. */
1381 idle_cycles = 0;
1382 if (new_tail == NULL) {
1383 dev->first_busy_cnt++;
1384 if (!
1385 (list_is_last
1386 (lelt,
1387 &List_Polling_Device_Channels))) {
1388 new_tail = lelt;
1389 dev->moved_to_tail_cnt++;
1390 } else
1391 dev->last_on_list_cnt++;
1395 if (Incoming_ThreadInfo.should_stop)
1396 break;
1398 if (new_tail != NULL) {
1399 tot_moved_to_tail_cnt++;
1400 list_move_tail(new_tail, &List_Polling_Device_Channels);
1402 UNLOCKSEM(&Lock_Polling_Device_Channels);
1403 cur_cycles = get_cycles();
1404 delta_cycles = cur_cycles - old_cycles;
1405 old_cycles = cur_cycles;
1407 /* At this point, we have scanned thru all of the
1408 * channels, and at least one of the following is true:
1409 * - there is no input waiting on any of the channels
1410 * - we have received a signal to stop this thread
1412 if (Incoming_ThreadInfo.should_stop)
1413 break;
1414 if (en_smart_wakeup == 0xFF) {
1415 LOGINF("en_smart_wakeup set to 0xff, to force exiting process_incoming");
1416 break;
1418 /* wait for POLLJIFFIES_NORMAL jiffies, or until
1419 * someone wakes up Wakeup_Polling_Device_Channels,
1420 * whichever comes first only do a wait when we have
1421 * been idle for cycles_before_wait cycles.
1423 if (idle_cycles > cycles_before_wait) {
1424 Go_Polling_Device_Channels = 0;
1425 tot_wait_cnt++;
1426 wait_event_timeout(Wakeup_Polling_Device_Channels,
1427 Go_Polling_Device_Channels,
1428 POLLJIFFIES_NORMAL);
1429 Go_Polling_Device_Channels = 1;
1430 } else {
1431 tot_schedule_cnt++;
1432 schedule();
1433 idle_cycles = idle_cycles + delta_cycles;
1436 DBGINF("exiting.\n");
1437 complete_and_exit(&Incoming_ThreadInfo.has_stopped, 0);
1440 static BOOL
1441 Initialize_incoming_thread(void)
1443 if (Incoming_Thread_Started)
1444 return TRUE;
1445 if (!uisthread_start(&Incoming_ThreadInfo,
1446 &Process_Incoming, NULL, "dev_incoming")) {
1447 LOGERR("uisthread_start Initialize_incoming_thread ****FAILED");
1448 return FALSE;
1450 Incoming_Thread_Started = TRUE;
1451 return TRUE;
1454 /* Add a new device/channel to the list being processed by
1455 * Process_Incoming().
1456 * <interrupt> - indicates the function to call periodically.
1457 * <interrupt_context> - indicates the data to pass to the <interrupt>
1458 * function.
1460 void
1461 uislib_enable_channel_interrupts(u32 busNo, u32 devNo,
1462 int (*interrupt)(void *),
1463 void *interrupt_context)
1465 struct device_info *dev;
1466 dev = find_dev(busNo, devNo);
1467 if (!dev) {
1468 LOGERR("%s busNo=%d, devNo=%d", __func__, (int) (busNo),
1469 (int) (devNo));
1470 return;
1472 LOCKSEM_UNINTERRUPTIBLE(&Lock_Polling_Device_Channels);
1473 Initialize_incoming_thread();
1474 dev->interrupt = interrupt;
1475 dev->interrupt_context = interrupt_context;
1476 dev->polling = TRUE;
1477 list_add_tail(&(dev->list_polling_device_channels),
1478 &List_Polling_Device_Channels);
1479 UNLOCKSEM(&Lock_Polling_Device_Channels);
1481 EXPORT_SYMBOL_GPL(uislib_enable_channel_interrupts);
1483 /* Remove a device/channel from the list being processed by
1484 * Process_Incoming().
1486 void
1487 uislib_disable_channel_interrupts(u32 busNo, u32 devNo)
1489 struct device_info *dev;
1490 dev = find_dev(busNo, devNo);
1491 if (!dev) {
1492 LOGERR("%s busNo=%d, devNo=%d", __func__, (int) (busNo),
1493 (int) (devNo));
1494 return;
1496 LOCKSEM_UNINTERRUPTIBLE(&Lock_Polling_Device_Channels);
1497 list_del(&dev->list_polling_device_channels);
1498 dev->polling = FALSE;
1499 dev->interrupt = NULL;
1500 UNLOCKSEM(&Lock_Polling_Device_Channels);
1502 EXPORT_SYMBOL_GPL(uislib_disable_channel_interrupts);
1504 static void
1505 do_wakeup_polling_device_channels(struct work_struct *dummy)
1507 if (!Go_Polling_Device_Channels) {
1508 Go_Polling_Device_Channels = 1;
1509 wake_up(&Wakeup_Polling_Device_Channels);
1513 static DECLARE_WORK(Work_wakeup_polling_device_channels,
1514 do_wakeup_polling_device_channels);
1516 /* Call this function when you want to send a hint to Process_Incoming() that
1517 * your device might have more requests.
1519 void
1520 uislib_force_channel_interrupt(u32 busNo, u32 devNo)
1522 if (en_smart_wakeup == 0)
1523 return;
1524 if (Go_Polling_Device_Channels)
1525 return;
1526 /* The point of using schedule_work() instead of just doing
1527 * the work inline is to force a slight delay before waking up
1528 * the Process_Incoming() thread.
1530 tot_wakeup_cnt++;
1531 schedule_work(&Work_wakeup_polling_device_channels);
1533 EXPORT_SYMBOL_GPL(uislib_force_channel_interrupt);
1535 /*****************************************************/
1536 /* Module Init & Exit functions */
1537 /*****************************************************/
1539 static int __init
1540 uislib_mod_init(void)
1543 if (!unisys_spar_platform)
1544 return -ENODEV;
1546 LOGINF("MONITORAPIS");
1548 LOGINF("sizeof(struct uiscmdrsp):%lu bytes\n",
1549 (ulong) sizeof(struct uiscmdrsp));
1550 LOGINF("sizeof(struct phys_info):%lu\n",
1551 (ulong) sizeof(struct phys_info));
1552 LOGINF("sizeof(uiscmdrsp_scsi):%lu\n",
1553 (ulong) sizeof(struct uiscmdrsp_scsi));
1554 LOGINF("sizeof(uiscmdrsp_net):%lu\n",
1555 (ulong) sizeof(struct uiscmdrsp_net));
1556 LOGINF("sizeof(CONTROLVM_MESSAGE):%lu bytes\n",
1557 (ulong) sizeof(CONTROLVM_MESSAGE));
1558 LOGINF("sizeof(ULTRA_CONTROLVM_CHANNEL_PROTOCOL):%lu bytes\n",
1559 (ulong) sizeof(ULTRA_CONTROLVM_CHANNEL_PROTOCOL));
1560 LOGINF("sizeof(CHANNEL_HEADER):%lu bytes\n",
1561 (ulong) sizeof(CHANNEL_HEADER));
1562 LOGINF("sizeof(ULTRA_IO_CHANNEL_PROTOCOL):%lu bytes\n",
1563 (ulong) sizeof(ULTRA_IO_CHANNEL_PROTOCOL));
1564 LOGINF("SIZEOF_CMDRSP:%lu bytes\n", SIZEOF_CMDRSP);
1565 LOGINF("SIZEOF_PROTOCOL:%lu bytes\n", SIZEOF_PROTOCOL);
1567 /* initialize global pointers to NULL */
1568 BusListHead = NULL;
1569 BusListCount = MaxBusCount = 0;
1570 rwlock_init(&BusListLock);
1571 VirtControlChanFunc = NULL;
1573 /* Issue VMCALL_GET_CONTROLVM_ADDR to get CtrlChanPhysAddr and
1574 * then map this physical address to a virtual address. */
1575 POSTCODE_LINUX_2(DRIVER_ENTRY_PC, POSTCODE_SEVERITY_INFO);
1577 dir_debugfs = debugfs_create_dir(DIR_DEBUGFS_ENTRY, NULL);
1578 if (dir_debugfs) {
1579 info_debugfs_entry = debugfs_create_file(
1580 INFO_DEBUGFS_ENTRY_FN, 0444, dir_debugfs, NULL,
1581 &debugfs_info_fops);
1583 platformnumber_debugfs_read = debugfs_create_u32(
1584 PLATFORMNUMBER_DEBUGFS_ENTRY_FN, 0444, dir_debugfs,
1585 &PlatformNumber);
1587 cycles_before_wait_debugfs_read = debugfs_create_u64(
1588 CYCLES_BEFORE_WAIT_DEBUGFS_ENTRY_FN, 0666, dir_debugfs,
1589 &cycles_before_wait);
1591 smart_wakeup_debugfs_entry = debugfs_create_bool(
1592 SMART_WAKEUP_DEBUGFS_ENTRY_FN, 0666, dir_debugfs,
1593 &en_smart_wakeup);
1596 POSTCODE_LINUX_3(DRIVER_EXIT_PC, 0, POSTCODE_SEVERITY_INFO);
1597 return 0;
1600 static void __exit
1601 uislib_mod_exit(void)
1603 if (ProcReadBuffer) {
1604 vfree(ProcReadBuffer);
1605 ProcReadBuffer = NULL;
1608 debugfs_remove(info_debugfs_entry);
1609 debugfs_remove(smart_wakeup_debugfs_entry);
1610 debugfs_remove(cycles_before_wait_debugfs_read);
1611 debugfs_remove(platformnumber_debugfs_read);
1612 debugfs_remove(dir_debugfs);
1614 DBGINF("goodbye.\n");
1615 return;
1618 module_init(uislib_mod_init);
1619 module_exit(uislib_mod_exit);
1621 MODULE_LICENSE("GPL");
1622 MODULE_AUTHOR("Usha Srinivasan");
1623 MODULE_ALIAS("uislib");
1624 /* this is extracted during depmod and kept in modules.dep */