1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
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>
27
28#include <linux/types.h>
29#include <linux/uuid.h>
30
31#include <linux/version.h>
32#include "uniklog.h"
33#include "diagnostics/appos_subsystems.h"
34#include "uisutils.h"
35#include "vbuschannel.h"
36
37#include <linux/proc_fs.h>
38#include <linux/uaccess.h>
39#include <linux/ctype.h>
40#include <linux/list.h>
41
42#include "sparstop.h"
43#include "visorchipset.h"
44#include "chanstub.h"
45#include "version.h"
46#include "guestlinuxdebug.h"
47
48#define SET_PROC_OWNER(x, y)
49
50#define POLLJIFFIES_NORMAL 1
51
52
53
54
55
56#define CURRENT_FILE_PC UISLIB_PC_uislib_c
57#define __MYFILE__ "uislib.c"
58
59
60int (*VirtControlChanFunc)(struct guest_msgs *);
61
62static int ProcReadBufferValid;
63static char *ProcReadBuffer;
64
65static unsigned int chipset_inited;
66
67#define WAIT_ON_CALLBACK(handle) \
68 do { \
69 if (handle) \
70 break; \
71 UIS_THREAD_WAIT; \
72 } while (1)
73
74static struct bus_info *BusListHead;
75static rwlock_t BusListLock;
76static int BusListCount;
77static int MaxBusCount;
78static u64 PhysicalDataChan;
79static int PlatformNumber;
80
81static struct uisthread_info Incoming_ThreadInfo;
82static BOOL Incoming_Thread_Started = FALSE;
83static LIST_HEAD(List_Polling_Device_Channels);
84static unsigned long long tot_moved_to_tail_cnt;
85static unsigned long long tot_wait_cnt;
86static unsigned long long tot_wakeup_cnt;
87static unsigned long long tot_schedule_cnt;
88static int en_smart_wakeup = 1;
89static DEFINE_SEMAPHORE(Lock_Polling_Device_Channels);
90static DECLARE_WAIT_QUEUE_HEAD(Wakeup_Polling_Device_Channels);
91static int Go_Polling_Device_Channels;
92
93#define CALLHOME_PROC_ENTRY_FN "callhome"
94#define CALLHOME_THROTTLED_PROC_ENTRY_FN "callhome_throttled"
95
96#define DIR_DEBUGFS_ENTRY "uislib"
97static struct dentry *dir_debugfs;
98
99#define PLATFORMNUMBER_DEBUGFS_ENTRY_FN "platform"
100static struct dentry *platformnumber_debugfs_read;
101
102#define CYCLES_BEFORE_WAIT_DEBUGFS_ENTRY_FN "cycles_before_wait"
103static struct dentry *cycles_before_wait_debugfs_read;
104
105#define SMART_WAKEUP_DEBUGFS_ENTRY_FN "smart_wakeup"
106static struct dentry *smart_wakeup_debugfs_entry;
107
108#define INFO_DEBUGFS_ENTRY_FN "info"
109static struct dentry *info_debugfs_entry;
110
111static unsigned long long cycles_before_wait, wait_cycles;
112
113
114
115
116
117static ssize_t info_debugfs_read(struct file *file, char __user *buf,
118 size_t len, loff_t *offset);
119static const struct file_operations debugfs_info_fops = {
120 .read = info_debugfs_read,
121};
122
123static void
124init_msg_header(CONTROLVM_MESSAGE *msg, u32 id, uint rsp, uint svr)
125{
126 memset(msg, 0, sizeof(CONTROLVM_MESSAGE));
127 msg->hdr.Id = id;
128 msg->hdr.Flags.responseExpected = rsp;
129 msg->hdr.Flags.server = svr;
130}
131
132static __iomem void *
133init_vbus_channel(u64 channelAddr, u32 channelBytes)
134{
135 void __iomem *rc = NULL;
136 void __iomem *pChan = uislib_ioremap_cache(channelAddr, channelBytes);
137
138 if (!pChan) {
139 LOGERR("CONTROLVM_BUS_CREATE error: ioremap_cache of channelAddr:%Lx for channelBytes:%llu failed",
140 (unsigned long long) channelAddr,
141 (unsigned long long) channelBytes);
142 rc = NULL;
143 goto Away;
144 }
145 if (!ULTRA_VBUS_CHANNEL_OK_CLIENT(pChan, NULL)) {
146 ERRDRV("%s channel cannot be used", __func__);
147 uislib_iounmap(pChan);
148 rc = NULL;
149 goto Away;
150 }
151 rc = pChan;
152Away:
153 return rc;
154}
155
156static int
157create_bus(CONTROLVM_MESSAGE *msg, char *buf)
158{
159 u32 busNo, deviceCount;
160 struct bus_info *tmp, *bus;
161 size_t size;
162
163 if (MaxBusCount == BusListCount) {
164 LOGERR("CONTROLVM_BUS_CREATE Failed: max buses:%d already created\n",
165 MaxBusCount);
166 POSTCODE_LINUX_3(BUS_CREATE_FAILURE_PC, MaxBusCount,
167 POSTCODE_SEVERITY_ERR);
168 return CONTROLVM_RESP_ERROR_MAX_BUSES;
169 }
170
171 busNo = msg->cmd.createBus.busNo;
172 deviceCount = msg->cmd.createBus.deviceCount;
173
174 POSTCODE_LINUX_4(BUS_CREATE_ENTRY_PC, busNo, deviceCount,
175 POSTCODE_SEVERITY_INFO);
176
177 size =
178 sizeof(struct bus_info) +
179 (deviceCount * sizeof(struct device_info *));
180 bus = kzalloc(size, GFP_ATOMIC);
181 if (!bus) {
182 LOGERR("CONTROLVM_BUS_CREATE Failed: kmalloc for bus failed.\n");
183 POSTCODE_LINUX_3(BUS_CREATE_FAILURE_PC, busNo,
184 POSTCODE_SEVERITY_ERR);
185 return CONTROLVM_RESP_ERROR_KMALLOC_FAILED;
186 }
187
188
189
190
191 if (msg->hdr.Flags.testMessage) {
192
193 bus->guestHandle = 0;
194 bus->busNo = busNo;
195 bus->localVnic = 1;
196 } else
197 bus->busNo = bus->guestHandle = busNo;
198 sprintf(bus->name, "%d", (int) bus->busNo);
199 bus->deviceCount = deviceCount;
200 bus->device =
201 (struct device_info **) ((char *) bus + sizeof(struct bus_info));
202 bus->busInstGuid = msg->cmd.createBus.busInstGuid;
203 bus->busChannelBytes = 0;
204 bus->pBusChannel = NULL;
205
206
207 read_lock(&BusListLock);
208 for (tmp = BusListHead; tmp; tmp = tmp->next) {
209 if (tmp->busNo == bus->busNo)
210 break;
211 }
212 read_unlock(&BusListLock);
213 if (tmp) {
214
215
216
217 LOGERR("CONTROLVM_BUS_CREATE Failed: bus %d already exists.\n",
218 bus->busNo);
219 POSTCODE_LINUX_3(BUS_CREATE_FAILURE_PC, bus->busNo,
220 POSTCODE_SEVERITY_ERR);
221 kfree(bus);
222 return CONTROLVM_RESP_ERROR_ALREADY_DONE;
223 }
224 if ((msg->cmd.createBus.channelAddr != 0)
225 && (msg->cmd.createBus.channelBytes != 0)) {
226 bus->busChannelBytes = msg->cmd.createBus.channelBytes;
227 bus->pBusChannel =
228 init_vbus_channel(msg->cmd.createBus.channelAddr,
229 msg->cmd.createBus.channelBytes);
230 }
231
232 if (!msg->hdr.Flags.server) {
233 struct guest_msgs cmd;
234
235 cmd.msgtype = GUEST_ADD_VBUS;
236 cmd.add_vbus.busNo = busNo;
237 cmd.add_vbus.chanptr = bus->pBusChannel;
238 cmd.add_vbus.deviceCount = deviceCount;
239 cmd.add_vbus.busTypeGuid = msg->cmd.createBus.busDataTypeGuid;
240 cmd.add_vbus.busInstGuid = msg->cmd.createBus.busInstGuid;
241 if (!VirtControlChanFunc) {
242 LOGERR("CONTROLVM_BUS_CREATE Failed: virtpci callback not registered.");
243 POSTCODE_LINUX_3(BUS_CREATE_FAILURE_PC, bus->busNo,
244 POSTCODE_SEVERITY_ERR);
245 kfree(bus);
246 return CONTROLVM_RESP_ERROR_VIRTPCI_DRIVER_FAILURE;
247 }
248 if (!VirtControlChanFunc(&cmd)) {
249 LOGERR("CONTROLVM_BUS_CREATE Failed: virtpci GUEST_ADD_VBUS returned error.");
250 POSTCODE_LINUX_3(BUS_CREATE_FAILURE_PC, bus->busNo,
251 POSTCODE_SEVERITY_ERR);
252 kfree(bus);
253 return
254 CONTROLVM_RESP_ERROR_VIRTPCI_DRIVER_CALLBACK_ERROR;
255 }
256 }
257
258
259 write_lock(&BusListLock);
260 if (!BusListHead)
261 BusListHead = bus;
262 else {
263 bus->next = BusListHead;
264 BusListHead = bus;
265 }
266 BusListCount++;
267 write_unlock(&BusListLock);
268
269 POSTCODE_LINUX_3(BUS_CREATE_EXIT_PC, bus->busNo,
270 POSTCODE_SEVERITY_INFO);
271 return CONTROLVM_RESP_SUCCESS;
272}
273
274static int
275destroy_bus(CONTROLVM_MESSAGE *msg, char *buf)
276{
277 int i;
278 struct bus_info *bus, *prev = NULL;
279 struct guest_msgs cmd;
280 u32 busNo;
281
282 busNo = msg->cmd.destroyBus.busNo;
283
284 read_lock(&BusListLock);
285
286 bus = BusListHead;
287 while (bus) {
288 if (bus->busNo == busNo)
289 break;
290 prev = bus;
291 bus = bus->next;
292 }
293
294 if (!bus) {
295 LOGERR("CONTROLVM_BUS_DESTROY Failed: failed to find bus %d.\n",
296 busNo);
297 read_unlock(&BusListLock);
298 return CONTROLVM_RESP_ERROR_ALREADY_DONE;
299 }
300
301
302 for (i = 0; i < bus->deviceCount; i++) {
303 if (bus->device[i] != NULL) {
304 LOGERR("CONTROLVM_BUS_DESTROY Failed: device %i attached to bus %d.",
305 i, busNo);
306 read_unlock(&BusListLock);
307 return CONTROLVM_RESP_ERROR_BUS_DEVICE_ATTACHED;
308 }
309 }
310 read_unlock(&BusListLock);
311
312 if (msg->hdr.Flags.server)
313 goto remove;
314
315
316
317 cmd.msgtype = GUEST_DEL_VBUS;
318 cmd.del_vbus.bus_no = busNo;
319 if (!VirtControlChanFunc) {
320 LOGERR("CONTROLVM_BUS_DESTROY Failed: virtpci callback not registered.");
321 return CONTROLVM_RESP_ERROR_VIRTPCI_DRIVER_FAILURE;
322 }
323 if (!VirtControlChanFunc(&cmd)) {
324 LOGERR("CONTROLVM_BUS_DESTROY Failed: virtpci GUEST_DEL_VBUS returned error.");
325 return CONTROLVM_RESP_ERROR_VIRTPCI_DRIVER_CALLBACK_ERROR;
326 }
327
328
329remove:
330 write_lock(&BusListLock);
331 if (prev)
332 prev->next = bus->next;
333 else
334 BusListHead = bus->next;
335 BusListCount--;
336 write_unlock(&BusListLock);
337
338 if (bus->pBusChannel) {
339 uislib_iounmap(bus->pBusChannel);
340 bus->pBusChannel = NULL;
341 }
342
343 kfree(bus);
344 return CONTROLVM_RESP_SUCCESS;
345}
346
347static int
348create_device(CONTROLVM_MESSAGE *msg, char *buf)
349{
350 struct device_info *dev;
351 struct bus_info *bus;
352 u32 busNo, devNo;
353 int result = CONTROLVM_RESP_SUCCESS;
354 u64 minSize = MIN_IO_CHANNEL_SIZE;
355 ReqHandlerInfo_t *pReqHandler;
356
357 busNo = msg->cmd.createDevice.busNo;
358 devNo = msg->cmd.createDevice.devNo;
359
360 POSTCODE_LINUX_4(DEVICE_CREATE_ENTRY_PC, devNo, busNo,
361 POSTCODE_SEVERITY_INFO);
362
363 dev = kzalloc(sizeof(struct device_info), GFP_ATOMIC);
364 if (!dev) {
365 LOGERR("CONTROLVM_DEVICE_CREATE Failed: kmalloc for dev failed.\n");
366 POSTCODE_LINUX_4(DEVICE_CREATE_FAILURE_PC, devNo, busNo,
367 POSTCODE_SEVERITY_ERR);
368 return CONTROLVM_RESP_ERROR_KMALLOC_FAILED;
369 }
370
371 dev->channel_uuid = msg->cmd.createDevice.dataTypeGuid;
372 dev->intr = msg->cmd.createDevice.intr;
373 dev->channel_addr = msg->cmd.createDevice.channelAddr;
374 dev->bus_no = busNo;
375 dev->dev_no = devNo;
376 sema_init(&dev->interrupt_callback_lock, 1);
377 sprintf(dev->devid, "vbus%u:dev%u", (unsigned) busNo, (unsigned) devNo);
378
379 if (msg->hdr.Flags.testMessage)
380 dev->chanptr = (void __iomem *)__va(dev->channel_addr);
381 else {
382 pReqHandler = ReqHandlerFind(dev->channel_uuid);
383 if (pReqHandler)
384
385
386
387 minSize = pReqHandler->min_channel_bytes;
388 if (minSize > msg->cmd.createDevice.channelBytes) {
389 LOGERR("CONTROLVM_DEVICE_CREATE Failed: channel size is too small, channel size:0x%lx, required size:0x%lx",
390 (ulong) msg->cmd.createDevice.channelBytes,
391 (ulong) minSize);
392 POSTCODE_LINUX_4(DEVICE_CREATE_FAILURE_PC, devNo, busNo,
393 POSTCODE_SEVERITY_ERR);
394 result = CONTROLVM_RESP_ERROR_CHANNEL_SIZE_TOO_SMALL;
395 goto Away;
396 }
397 dev->chanptr =
398 uislib_ioremap_cache(dev->channel_addr,
399 msg->cmd.createDevice.channelBytes);
400 if (!dev->chanptr) {
401 LOGERR("CONTROLVM_DEVICE_CREATE Failed: ioremap_cache of channelAddr:%Lx for channelBytes:%llu failed",
402 dev->channel_addr,
403 msg->cmd.createDevice.channelBytes);
404 result = CONTROLVM_RESP_ERROR_IOREMAP_FAILED;
405 POSTCODE_LINUX_4(DEVICE_CREATE_FAILURE_PC, devNo, busNo,
406 POSTCODE_SEVERITY_ERR);
407 goto Away;
408 }
409 }
410 dev->instance_uuid = msg->cmd.createDevice.devInstGuid;
411 dev->channel_bytes = msg->cmd.createDevice.channelBytes;
412
413 read_lock(&BusListLock);
414 for (bus = BusListHead; bus; bus = bus->next) {
415 if (bus->busNo == busNo) {
416
417 if (devNo >= bus->deviceCount) {
418 LOGERR("CONTROLVM_DEVICE_CREATE Failed: device (%d) >= deviceCount (%d).",
419 devNo, bus->deviceCount);
420 result = CONTROLVM_RESP_ERROR_MAX_DEVICES;
421 POSTCODE_LINUX_4(DEVICE_CREATE_FAILURE_PC,
422 devNo, busNo,
423 POSTCODE_SEVERITY_ERR);
424 read_unlock(&BusListLock);
425 goto Away;
426 }
427
428 if (bus->device[devNo]) {
429 LOGERR("CONTROLVM_DEVICE_CREATE Failed: device %d is already exists.",
430 devNo);
431 POSTCODE_LINUX_4(DEVICE_CREATE_FAILURE_PC,
432 devNo, busNo,
433 POSTCODE_SEVERITY_ERR);
434 result = CONTROLVM_RESP_ERROR_ALREADY_DONE;
435 read_unlock(&BusListLock);
436 goto Away;
437 }
438 read_unlock(&BusListLock);
439
440
441
442 if (!msg->hdr.Flags.server) {
443 struct guest_msgs cmd;
444
445 if (!uuid_le_cmp(dev->channel_uuid,
446 UltraVhbaChannelProtocolGuid)) {
447 wait_for_valid_guid(&((CHANNEL_HEADER
448 __iomem *) (dev->
449 chanptr))->
450 Type);
451 if (!ULTRA_VHBA_CHANNEL_OK_CLIENT
452 (dev->chanptr, NULL)) {
453 LOGERR("CONTROLVM_DEVICE_CREATE Failed:[CLIENT]VHBA dev %d chan invalid.",
454 devNo);
455 POSTCODE_LINUX_4
456 (DEVICE_CREATE_FAILURE_PC,
457 devNo, busNo,
458 POSTCODE_SEVERITY_ERR);
459 result = CONTROLVM_RESP_ERROR_CHANNEL_INVALID;
460 goto Away;
461 }
462 cmd.msgtype = GUEST_ADD_VHBA;
463 cmd.add_vhba.chanptr = dev->chanptr;
464 cmd.add_vhba.bus_no = busNo;
465 cmd.add_vhba.device_no = devNo;
466 cmd.add_vhba.instance_uuid =
467 dev->instance_uuid;
468 cmd.add_vhba.intr = dev->intr;
469 } else
470 if (!uuid_le_cmp(dev->channel_uuid,
471 UltraVnicChannelProtocolGuid)) {
472 wait_for_valid_guid(&((CHANNEL_HEADER
473 __iomem *) (dev->
474 chanptr))->
475 Type);
476 if (!ULTRA_VNIC_CHANNEL_OK_CLIENT
477 (dev->chanptr, NULL)) {
478 LOGERR("CONTROLVM_DEVICE_CREATE Failed: VNIC[CLIENT] dev %d chan invalid.",
479 devNo);
480 POSTCODE_LINUX_4
481 (DEVICE_CREATE_FAILURE_PC,
482 devNo, busNo,
483 POSTCODE_SEVERITY_ERR);
484 result = CONTROLVM_RESP_ERROR_CHANNEL_INVALID;
485 goto Away;
486 }
487 cmd.msgtype = GUEST_ADD_VNIC;
488 cmd.add_vnic.chanptr = dev->chanptr;
489 cmd.add_vnic.bus_no = busNo;
490 cmd.add_vnic.device_no = devNo;
491 cmd.add_vnic.instance_uuid =
492 dev->instance_uuid;
493 cmd.add_vhba.intr = dev->intr;
494 } else {
495 LOGERR("CONTROLVM_DEVICE_CREATE Failed: unknown channelTypeGuid.\n");
496 POSTCODE_LINUX_4
497 (DEVICE_CREATE_FAILURE_PC, devNo,
498 busNo, POSTCODE_SEVERITY_ERR);
499 result = CONTROLVM_RESP_ERROR_CHANNEL_TYPE_UNKNOWN;
500 goto Away;
501 }
502
503 if (!VirtControlChanFunc) {
504 LOGERR("CONTROLVM_DEVICE_CREATE Failed: virtpci callback not registered.");
505 POSTCODE_LINUX_4
506 (DEVICE_CREATE_FAILURE_PC, devNo,
507 busNo, POSTCODE_SEVERITY_ERR);
508 result = CONTROLVM_RESP_ERROR_VIRTPCI_DRIVER_FAILURE;
509 goto Away;
510 }
511
512 if (!VirtControlChanFunc(&cmd)) {
513 LOGERR("CONTROLVM_DEVICE_CREATE Failed: virtpci GUEST_ADD_[VHBA||VNIC] returned error.");
514 POSTCODE_LINUX_4
515 (DEVICE_CREATE_FAILURE_PC, devNo,
516 busNo, POSTCODE_SEVERITY_ERR);
517 result = CONTROLVM_RESP_ERROR_VIRTPCI_DRIVER_CALLBACK_ERROR;
518 goto Away;
519 }
520 }
521 bus->device[devNo] = dev;
522 POSTCODE_LINUX_4(DEVICE_CREATE_SUCCESS_PC, devNo, busNo,
523 POSTCODE_SEVERITY_INFO);
524 return CONTROLVM_RESP_SUCCESS;
525 }
526 }
527 read_unlock(&BusListLock);
528
529 LOGERR("CONTROLVM_DEVICE_CREATE Failed: failed to find bus %d.", busNo);
530 POSTCODE_LINUX_4(DEVICE_CREATE_FAILURE_PC, devNo, busNo,
531 POSTCODE_SEVERITY_ERR);
532 result = CONTROLVM_RESP_ERROR_BUS_INVALID;
533
534Away:
535 if (!msg->hdr.Flags.testMessage) {
536 uislib_iounmap(dev->chanptr);
537 dev->chanptr = NULL;
538 }
539
540 kfree(dev);
541 return result;
542}
543
544static int
545pause_device(CONTROLVM_MESSAGE *msg)
546{
547 u32 busNo, devNo;
548 struct bus_info *bus;
549 struct device_info *dev;
550 struct guest_msgs cmd;
551 int retval = CONTROLVM_RESP_SUCCESS;
552
553 busNo = msg->cmd.deviceChangeState.busNo;
554 devNo = msg->cmd.deviceChangeState.devNo;
555
556 read_lock(&BusListLock);
557 for (bus = BusListHead; bus; bus = bus->next) {
558 if (bus->busNo == busNo) {
559
560 if (devNo >= bus->deviceCount) {
561 LOGERR("CONTROLVM_DEVICE_CHANGESTATE:pause Failed: device(%d) >= deviceCount(%d).",
562 devNo, bus->deviceCount);
563 retval = CONTROLVM_RESP_ERROR_DEVICE_INVALID;
564 } else {
565
566 dev = bus->device[devNo];
567 if (!dev) {
568 LOGERR("CONTROLVM_DEVICE_CHANGESTATE:pause Failed: device %d does not exist.",
569 devNo);
570 retval =
571 CONTROLVM_RESP_ERROR_ALREADY_DONE;
572 }
573 }
574 break;
575 }
576 }
577 if (!bus) {
578 LOGERR("CONTROLVM_DEVICE_CHANGESTATE:pause Failed: bus %d does not exist",
579 busNo);
580 retval = CONTROLVM_RESP_ERROR_BUS_INVALID;
581 }
582 read_unlock(&BusListLock);
583 if (retval == CONTROLVM_RESP_SUCCESS) {
584
585
586
587 if (!uuid_le_cmp(dev->channel_uuid,
588 UltraVhbaChannelProtocolGuid)) {
589 cmd.msgtype = GUEST_PAUSE_VHBA;
590 cmd.pause_vhba.chanptr = dev->chanptr;
591 } else if (!uuid_le_cmp(dev->channel_uuid,
592 UltraVnicChannelProtocolGuid)) {
593 cmd.msgtype = GUEST_PAUSE_VNIC;
594 cmd.pause_vnic.chanptr = dev->chanptr;
595 } else {
596 LOGERR("CONTROLVM_DEVICE_CHANGESTATE:pause Failed: unknown channelTypeGuid.\n");
597 return CONTROLVM_RESP_ERROR_CHANNEL_TYPE_UNKNOWN;
598 }
599 if (!VirtControlChanFunc) {
600 LOGERR("CONTROLVM_DEVICE_CHANGESTATE Failed: virtpci callback not registered.");
601 return CONTROLVM_RESP_ERROR_VIRTPCI_DRIVER_FAILURE;
602 }
603 if (!VirtControlChanFunc(&cmd)) {
604 LOGERR("CONTROLVM_DEVICE_CHANGESTATE:pause Failed: virtpci GUEST_PAUSE_[VHBA||VNIC] returned error.");
605 return
606 CONTROLVM_RESP_ERROR_VIRTPCI_DRIVER_CALLBACK_ERROR;
607 }
608 }
609 return retval;
610}
611
612static int
613resume_device(CONTROLVM_MESSAGE *msg)
614{
615 u32 busNo, devNo;
616 struct bus_info *bus;
617 struct device_info *dev;
618 struct guest_msgs cmd;
619 int retval = CONTROLVM_RESP_SUCCESS;
620
621 busNo = msg->cmd.deviceChangeState.busNo;
622 devNo = msg->cmd.deviceChangeState.devNo;
623
624 read_lock(&BusListLock);
625 for (bus = BusListHead; bus; bus = bus->next) {
626 if (bus->busNo == busNo) {
627
628 if (devNo >= bus->deviceCount) {
629 LOGERR("CONTROLVM_DEVICE_CHANGESTATE:resume Failed: device(%d) >= deviceCount(%d).",
630 devNo, bus->deviceCount);
631 retval = CONTROLVM_RESP_ERROR_DEVICE_INVALID;
632 } else {
633
634 dev = bus->device[devNo];
635 if (!dev) {
636 LOGERR("CONTROLVM_DEVICE_CHANGESTATE:resume Failed: device %d does not exist.",
637 devNo);
638 retval =
639 CONTROLVM_RESP_ERROR_ALREADY_DONE;
640 }
641 }
642 break;
643 }
644 }
645
646 if (!bus) {
647 LOGERR("CONTROLVM_DEVICE_CHANGESTATE:resume Failed: bus %d does not exist",
648 busNo);
649 retval = CONTROLVM_RESP_ERROR_BUS_INVALID;
650 }
651 read_unlock(&BusListLock);
652
653
654
655 if (retval == CONTROLVM_RESP_SUCCESS) {
656 if (!uuid_le_cmp(dev->channel_uuid,
657 UltraVhbaChannelProtocolGuid)) {
658 cmd.msgtype = GUEST_RESUME_VHBA;
659 cmd.resume_vhba.chanptr = dev->chanptr;
660 } else if (!uuid_le_cmp(dev->channel_uuid,
661 UltraVnicChannelProtocolGuid)) {
662 cmd.msgtype = GUEST_RESUME_VNIC;
663 cmd.resume_vnic.chanptr = dev->chanptr;
664 } else {
665 LOGERR("CONTROLVM_DEVICE_CHANGESTATE:resume Failed: unknown channelTypeGuid.\n");
666 return CONTROLVM_RESP_ERROR_CHANNEL_TYPE_UNKNOWN;
667 }
668 if (!VirtControlChanFunc) {
669 LOGERR("CONTROLVM_DEVICE_CHANGESTATE Failed: virtpci callback not registered.");
670 return CONTROLVM_RESP_ERROR_VIRTPCI_DRIVER_FAILURE;
671 }
672 if (!VirtControlChanFunc(&cmd)) {
673 LOGERR("CONTROLVM_DEVICE_CHANGESTATE:resume Failed: virtpci GUEST_RESUME_[VHBA||VNIC] returned error.");
674 return
675 CONTROLVM_RESP_ERROR_VIRTPCI_DRIVER_CALLBACK_ERROR;
676 }
677 }
678 return retval;
679}
680
681static int
682destroy_device(CONTROLVM_MESSAGE *msg, char *buf)
683{
684 u32 busNo, devNo;
685 struct bus_info *bus;
686 struct device_info *dev;
687 struct guest_msgs cmd;
688 int retval = CONTROLVM_RESP_SUCCESS;
689
690 busNo = msg->cmd.destroyDevice.busNo;
691 devNo = msg->cmd.destroyDevice.devNo;
692
693 read_lock(&BusListLock);
694 LOGINF("destroy_device called for busNo=%u, devNo=%u", busNo, devNo);
695 for (bus = BusListHead; bus; bus = bus->next) {
696 if (bus->busNo == busNo) {
697
698 if (devNo >= bus->deviceCount) {
699 LOGERR("CONTROLVM_DEVICE_DESTORY Failed: device(%d) >= deviceCount(%d).",
700 devNo, bus->deviceCount);
701 retval = CONTROLVM_RESP_ERROR_DEVICE_INVALID;
702 } else {
703
704 dev = bus->device[devNo];
705 if (!dev) {
706 LOGERR("CONTROLVM_DEVICE_DESTROY Failed: device %d does not exist.",
707 devNo);
708 retval =
709 CONTROLVM_RESP_ERROR_ALREADY_DONE;
710 }
711 }
712 break;
713 }
714 }
715
716 if (!bus) {
717 LOGERR("CONTROLVM_DEVICE_DESTROY Failed: bus %d does not exist",
718 busNo);
719 retval = CONTROLVM_RESP_ERROR_BUS_INVALID;
720 }
721 read_unlock(&BusListLock);
722 if (retval == CONTROLVM_RESP_SUCCESS) {
723
724
725
726 if (!uuid_le_cmp(dev->channel_uuid,
727 UltraVhbaChannelProtocolGuid)) {
728 cmd.msgtype = GUEST_DEL_VHBA;
729 cmd.del_vhba.chanptr = dev->chanptr;
730 } else if (!uuid_le_cmp(dev->channel_uuid,
731 UltraVnicChannelProtocolGuid)) {
732 cmd.msgtype = GUEST_DEL_VNIC;
733 cmd.del_vnic.chanptr = dev->chanptr;
734 } else {
735 LOGERR("CONTROLVM_DEVICE_DESTROY Failed: unknown channelTypeGuid.\n");
736 return
737 CONTROLVM_RESP_ERROR_CHANNEL_TYPE_UNKNOWN;
738 }
739 if (!VirtControlChanFunc) {
740 LOGERR("CONTROLVM_DEVICE_DESTORY Failed: virtpci callback not registered.");
741 return
742 CONTROLVM_RESP_ERROR_VIRTPCI_DRIVER_FAILURE;
743 }
744 if (!VirtControlChanFunc(&cmd)) {
745 LOGERR("CONTROLVM_DEVICE_DESTROY Failed: virtpci GUEST_DEL_[VHBA||VNIC] returned error.");
746 return
747 CONTROLVM_RESP_ERROR_VIRTPCI_DRIVER_CALLBACK_ERROR;
748 }
749
750
751
752
753
754 if (dev->polling) {
755 LOGINF("calling uislib_disable_channel_interrupts");
756 uislib_disable_channel_interrupts(busNo, devNo);
757 }
758
759 if (!msg->hdr.Flags.testMessage) {
760 LOGINF("destroy_device, doing iounmap");
761 uislib_iounmap(dev->chanptr);
762 }
763 kfree(dev);
764 bus->device[devNo] = NULL;
765 }
766 return retval;
767}
768
769static int
770init_chipset(CONTROLVM_MESSAGE *msg, char *buf)
771{
772 POSTCODE_LINUX_2(CHIPSET_INIT_ENTRY_PC, POSTCODE_SEVERITY_INFO);
773
774 MaxBusCount = msg->cmd.initChipset.busCount;
775 PlatformNumber = msg->cmd.initChipset.platformNumber;
776 PhysicalDataChan = 0;
777
778
779
780
781
782
783
784
785 if (!msg->hdr.Flags.testMessage)
786 WAIT_ON_CALLBACK(VirtControlChanFunc);
787
788 chipset_inited = 1;
789 POSTCODE_LINUX_2(CHIPSET_INIT_EXIT_PC, POSTCODE_SEVERITY_INFO);
790
791 return CONTROLVM_RESP_SUCCESS;
792}
793
794static int
795delete_bus_glue(u32 busNo)
796{
797 CONTROLVM_MESSAGE msg;
798
799 init_msg_header(&msg, CONTROLVM_BUS_DESTROY, 0, 0);
800 msg.cmd.destroyBus.busNo = busNo;
801 if (destroy_bus(&msg, NULL) != CONTROLVM_RESP_SUCCESS) {
802 LOGERR("destroy_bus failed. busNo=0x%x\n", busNo);
803 return 0;
804 }
805 return 1;
806}
807
808static int
809delete_device_glue(u32 busNo, u32 devNo)
810{
811 CONTROLVM_MESSAGE msg;
812
813 init_msg_header(&msg, CONTROLVM_DEVICE_DESTROY, 0, 0);
814 msg.cmd.destroyDevice.busNo = busNo;
815 msg.cmd.destroyDevice.devNo = devNo;
816 if (destroy_device(&msg, NULL) != CONTROLVM_RESP_SUCCESS) {
817 LOGERR("destroy_device failed. busNo=0x%x devNo=0x%x\n", busNo,
818 devNo);
819 return 0;
820 }
821 return 1;
822}
823
824int
825uislib_client_inject_add_bus(u32 busNo, uuid_le instGuid,
826 u64 channelAddr, ulong nChannelBytes)
827{
828 CONTROLVM_MESSAGE msg;
829
830 LOGINF("enter busNo=0x%x\n", busNo);
831
832 POSTCODE_LINUX_3(CHIPSET_INIT_ENTRY_PC, busNo, POSTCODE_SEVERITY_INFO);
833
834 if (!chipset_inited) {
835
836 init_msg_header(&msg, CONTROLVM_CHIPSET_INIT, 0, 0);
837
838
839
840
841
842
843
844 msg.cmd.initChipset.busCount = 23;
845 msg.cmd.initChipset.switchCount = 0;
846 if (init_chipset(&msg, NULL) != CONTROLVM_RESP_SUCCESS) {
847 LOGERR("init_chipset failed.\n");
848 return 0;
849 }
850 LOGINF("chipset initialized\n");
851 POSTCODE_LINUX_3(CHIPSET_INIT_EXIT_PC, busNo,
852 POSTCODE_SEVERITY_INFO);
853 }
854
855
856 POSTCODE_LINUX_3(BUS_CREATE_ENTRY_PC, busNo, POSTCODE_SEVERITY_WARNING);
857 init_msg_header(&msg, CONTROLVM_BUS_CREATE, 0, 0);
858 msg.cmd.createBus.busNo = busNo;
859 msg.cmd.createBus.deviceCount = 23;
860 msg.cmd.createBus.channelAddr = channelAddr;
861 msg.cmd.createBus.channelBytes = nChannelBytes;
862 if (create_bus(&msg, NULL) != CONTROLVM_RESP_SUCCESS) {
863 LOGERR("create_bus failed.\n");
864 POSTCODE_LINUX_3(BUS_CREATE_FAILURE_PC, busNo,
865 POSTCODE_SEVERITY_ERR);
866 return 0;
867 }
868 POSTCODE_LINUX_3(BUS_CREATE_EXIT_PC, busNo, POSTCODE_SEVERITY_INFO);
869
870 return 1;
871}
872EXPORT_SYMBOL_GPL(uislib_client_inject_add_bus);
873
874
875int
876uislib_client_inject_del_bus(u32 busNo)
877{
878 return delete_bus_glue(busNo);
879}
880EXPORT_SYMBOL_GPL(uislib_client_inject_del_bus);
881
882int
883uislib_client_inject_pause_vhba(u32 busNo, u32 devNo)
884{
885 CONTROLVM_MESSAGE msg;
886 int rc;
887
888 init_msg_header(&msg, CONTROLVM_DEVICE_CHANGESTATE, 0, 0);
889 msg.cmd.deviceChangeState.busNo = busNo;
890 msg.cmd.deviceChangeState.devNo = devNo;
891 msg.cmd.deviceChangeState.state = SegmentStateStandby;
892 rc = pause_device(&msg);
893 if (rc != CONTROLVM_RESP_SUCCESS) {
894 LOGERR("VHBA pause_device failed. busNo=0x%x devNo=0x%x\n",
895 busNo, devNo);
896 return rc;
897 }
898 return 0;
899}
900EXPORT_SYMBOL_GPL(uislib_client_inject_pause_vhba);
901
902int
903uislib_client_inject_resume_vhba(u32 busNo, u32 devNo)
904{
905 CONTROLVM_MESSAGE msg;
906 int rc;
907
908 init_msg_header(&msg, CONTROLVM_DEVICE_CHANGESTATE, 0, 0);
909 msg.cmd.deviceChangeState.busNo = busNo;
910 msg.cmd.deviceChangeState.devNo = devNo;
911 msg.cmd.deviceChangeState.state = SegmentStateRunning;
912 rc = resume_device(&msg);
913 if (rc != CONTROLVM_RESP_SUCCESS) {
914 LOGERR("VHBA resume_device failed. busNo=0x%x devNo=0x%x\n",
915 busNo, devNo);
916 return rc;
917 }
918 return 0;
919
920}
921EXPORT_SYMBOL_GPL(uislib_client_inject_resume_vhba);
922
923int
924uislib_client_inject_add_vhba(u32 busNo, u32 devNo,
925 u64 phys_chan_addr, u32 chan_bytes,
926 int is_test_addr, uuid_le instGuid,
927 struct InterruptInfo *intr)
928{
929 CONTROLVM_MESSAGE msg;
930
931 LOGINF(" enter busNo=0x%x devNo=0x%x\n", busNo, devNo);
932
933
934
935
936 POSTCODE_LINUX_4(VHBA_CREATE_ENTRY_PC, devNo, busNo,
937 POSTCODE_SEVERITY_INFO);
938
939 init_msg_header(&msg, CONTROLVM_DEVICE_CREATE, 0, 0);
940 if (is_test_addr)
941
942
943
944 msg.hdr.Flags.testMessage = 1;
945 msg.cmd.createDevice.busNo = busNo;
946 msg.cmd.createDevice.devNo = devNo;
947 msg.cmd.createDevice.devInstGuid = instGuid;
948 if (intr)
949 msg.cmd.createDevice.intr = *intr;
950 else
951 memset(&msg.cmd.createDevice.intr, 0,
952 sizeof(struct InterruptInfo));
953 msg.cmd.createDevice.channelAddr = phys_chan_addr;
954 if (chan_bytes < MIN_IO_CHANNEL_SIZE) {
955 LOGERR("wrong channel size.chan_bytes = 0x%x IO_CHANNEL_SIZE= 0x%x\n",
956 chan_bytes, (unsigned int) MIN_IO_CHANNEL_SIZE);
957 POSTCODE_LINUX_4(VHBA_CREATE_FAILURE_PC, chan_bytes,
958 MIN_IO_CHANNEL_SIZE, POSTCODE_SEVERITY_ERR);
959 return 0;
960 }
961 msg.cmd.createDevice.channelBytes = chan_bytes;
962 msg.cmd.createDevice.dataTypeGuid = UltraVhbaChannelProtocolGuid;
963 if (create_device(&msg, NULL) != CONTROLVM_RESP_SUCCESS) {
964 LOGERR("VHBA create_device failed.\n");
965 POSTCODE_LINUX_4(VHBA_CREATE_FAILURE_PC, devNo, busNo,
966 POSTCODE_SEVERITY_ERR);
967 return 0;
968 }
969 POSTCODE_LINUX_4(VHBA_CREATE_SUCCESS_PC, devNo, busNo,
970 POSTCODE_SEVERITY_INFO);
971 return 1;
972}
973EXPORT_SYMBOL_GPL(uislib_client_inject_add_vhba);
974
975int
976uislib_client_inject_del_vhba(u32 busNo, u32 devNo)
977{
978 return delete_device_glue(busNo, devNo);
979}
980EXPORT_SYMBOL_GPL(uislib_client_inject_del_vhba);
981
982int
983uislib_client_inject_add_vnic(u32 busNo, u32 devNo,
984 u64 phys_chan_addr, u32 chan_bytes,
985 int is_test_addr, uuid_le instGuid,
986 struct InterruptInfo *intr)
987{
988 CONTROLVM_MESSAGE msg;
989
990 LOGINF(" enter busNo=0x%x devNo=0x%x\n", busNo, devNo);
991
992
993
994
995 POSTCODE_LINUX_4(VNIC_CREATE_ENTRY_PC, devNo, busNo,
996 POSTCODE_SEVERITY_INFO);
997
998 init_msg_header(&msg, CONTROLVM_DEVICE_CREATE, 0, 0);
999 if (is_test_addr)
1000
1001
1002
1003 msg.hdr.Flags.testMessage = 1;
1004 msg.cmd.createDevice.busNo = busNo;
1005 msg.cmd.createDevice.devNo = devNo;
1006 msg.cmd.createDevice.devInstGuid = instGuid;
1007 if (intr)
1008 msg.cmd.createDevice.intr = *intr;
1009 else
1010 memset(&msg.cmd.createDevice.intr, 0,
1011 sizeof(struct InterruptInfo));
1012 msg.cmd.createDevice.channelAddr = phys_chan_addr;
1013 if (chan_bytes < MIN_IO_CHANNEL_SIZE) {
1014 LOGERR("wrong channel size.chan_bytes = 0x%x IO_CHANNEL_SIZE= 0x%x\n",
1015 chan_bytes, (unsigned int) MIN_IO_CHANNEL_SIZE);
1016 POSTCODE_LINUX_4(VNIC_CREATE_FAILURE_PC, chan_bytes,
1017 MIN_IO_CHANNEL_SIZE, POSTCODE_SEVERITY_ERR);
1018 return 0;
1019 }
1020 msg.cmd.createDevice.channelBytes = chan_bytes;
1021 msg.cmd.createDevice.dataTypeGuid = UltraVnicChannelProtocolGuid;
1022 if (create_device(&msg, NULL) != CONTROLVM_RESP_SUCCESS) {
1023 LOGERR("VNIC create_device failed.\n");
1024 POSTCODE_LINUX_4(VNIC_CREATE_FAILURE_PC, devNo, busNo,
1025 POSTCODE_SEVERITY_ERR);
1026 return 0;
1027 }
1028
1029 POSTCODE_LINUX_4(VNIC_CREATE_SUCCESS_PC, devNo, busNo,
1030 POSTCODE_SEVERITY_INFO);
1031 return 1;
1032}
1033EXPORT_SYMBOL_GPL(uislib_client_inject_add_vnic);
1034
1035int
1036uislib_client_inject_pause_vnic(u32 busNo, u32 devNo)
1037{
1038 CONTROLVM_MESSAGE msg;
1039 int rc;
1040
1041 init_msg_header(&msg, CONTROLVM_DEVICE_CHANGESTATE, 0, 0);
1042 msg.cmd.deviceChangeState.busNo = busNo;
1043 msg.cmd.deviceChangeState.devNo = devNo;
1044 msg.cmd.deviceChangeState.state = SegmentStateStandby;
1045 rc = pause_device(&msg);
1046 if (rc != CONTROLVM_RESP_SUCCESS) {
1047 LOGERR("VNIC pause_device failed. busNo=0x%x devNo=0x%x\n",
1048 busNo, devNo);
1049 return -1;
1050 }
1051 return 0;
1052}
1053EXPORT_SYMBOL_GPL(uislib_client_inject_pause_vnic);
1054
1055int
1056uislib_client_inject_resume_vnic(u32 busNo, u32 devNo)
1057{
1058 CONTROLVM_MESSAGE msg;
1059 int rc;
1060
1061 init_msg_header(&msg, CONTROLVM_DEVICE_CHANGESTATE, 0, 0);
1062 msg.cmd.deviceChangeState.busNo = busNo;
1063 msg.cmd.deviceChangeState.devNo = devNo;
1064 msg.cmd.deviceChangeState.state = SegmentStateRunning;
1065 rc = resume_device(&msg);
1066 if (rc != CONTROLVM_RESP_SUCCESS) {
1067 LOGERR("VNIC resume_device failed. busNo=0x%x devNo=0x%x\n",
1068 busNo, devNo);
1069 return -1;
1070 }
1071 return 0;
1072
1073}
1074EXPORT_SYMBOL_GPL(uislib_client_inject_resume_vnic);
1075
1076int
1077uislib_client_inject_del_vnic(u32 busNo, u32 devNo)
1078{
1079 return delete_device_glue(busNo, devNo);
1080}
1081EXPORT_SYMBOL_GPL(uislib_client_inject_del_vnic);
1082
1083static int
1084uislib_client_add_vnic(u32 busNo)
1085{
1086 BOOL busCreated = FALSE;
1087 int devNo = 0;
1088
1089 CONTROLVM_MESSAGE msg;
1090
1091 init_msg_header(&msg, CONTROLVM_BUS_CREATE, 0, 0);
1092 msg.hdr.Flags.testMessage = 1;
1093 msg.cmd.createBus.busNo = busNo;
1094 msg.cmd.createBus.deviceCount = 4;
1095 msg.cmd.createBus.channelAddr = 0;
1096 msg.cmd.createBus.channelBytes = 0;
1097 if (create_bus(&msg, NULL) != CONTROLVM_RESP_SUCCESS) {
1098 LOGERR("client create_bus failed");
1099 return 0;
1100 }
1101 busCreated = TRUE;
1102
1103 init_msg_header(&msg, CONTROLVM_DEVICE_CREATE, 0, 0);
1104 msg.hdr.Flags.testMessage = 1;
1105 msg.cmd.createDevice.busNo = busNo;
1106 msg.cmd.createDevice.devNo = devNo;
1107 msg.cmd.createDevice.devInstGuid = NULL_UUID_LE;
1108 memset(&msg.cmd.createDevice.intr, 0, sizeof(struct InterruptInfo));
1109 msg.cmd.createDevice.channelAddr = PhysicalDataChan;
1110 msg.cmd.createDevice.channelBytes = MIN_IO_CHANNEL_SIZE;
1111 msg.cmd.createDevice.dataTypeGuid = UltraVnicChannelProtocolGuid;
1112 if (create_device(&msg, NULL) != CONTROLVM_RESP_SUCCESS) {
1113 LOGERR("client create_device failed");
1114 goto AwayCleanup;
1115 }
1116
1117 return 1;
1118
1119AwayCleanup:
1120 if (busCreated) {
1121 init_msg_header(&msg, CONTROLVM_BUS_DESTROY, 0, 0);
1122 msg.hdr.Flags.testMessage = 1;
1123 msg.cmd.destroyBus.busNo = busNo;
1124 if (destroy_bus(&msg, NULL) != CONTROLVM_RESP_SUCCESS)
1125 LOGERR("client destroy_bus failed.\n");
1126 }
1127
1128 return 0;
1129}
1130EXPORT_SYMBOL_GPL(uislib_client_add_vnic);
1131
1132static int
1133uislib_client_delete_vnic(u32 busNo)
1134{
1135 int devNo = 0;
1136
1137 CONTROLVM_MESSAGE msg;
1138
1139 init_msg_header(&msg, CONTROLVM_DEVICE_DESTROY, 0, 0);
1140 msg.hdr.Flags.testMessage = 1;
1141 msg.cmd.destroyDevice.busNo = busNo;
1142 msg.cmd.destroyDevice.devNo = devNo;
1143 if (destroy_device(&msg, NULL) != CONTROLVM_RESP_SUCCESS) {
1144
1145 LOGERR("client destroy_device failed.\n");
1146 }
1147
1148 init_msg_header(&msg, CONTROLVM_BUS_DESTROY, 0, 0);
1149 msg.hdr.Flags.testMessage = 1;
1150 msg.cmd.destroyBus.busNo = busNo;
1151 if (destroy_bus(&msg, NULL) != CONTROLVM_RESP_SUCCESS)
1152 LOGERR("client destroy_bus failed.\n");
1153
1154 return 1;
1155}
1156EXPORT_SYMBOL_GPL(uislib_client_delete_vnic);
1157
1158
1159void *
1160uislib_cache_alloc(struct kmem_cache *cur_pool, char *fn, int ln)
1161{
1162
1163
1164
1165
1166
1167 void *p = kmem_cache_alloc(cur_pool, GFP_ATOMIC | __GFP_NORETRY);
1168
1169 if (p == NULL) {
1170 LOGERR("uislib_malloc failed to alloc uiscmdrsp @%s:%d",
1171 fn, ln);
1172 return NULL;
1173 }
1174 return p;
1175}
1176EXPORT_SYMBOL_GPL(uislib_cache_alloc);
1177
1178void
1179uislib_cache_free(struct kmem_cache *cur_pool, void *p, char *fn, int ln)
1180{
1181 if (p == NULL) {
1182 LOGERR("uislib_free NULL pointer @%s:%d", fn, ln);
1183 return;
1184 }
1185 kmem_cache_free(cur_pool, p);
1186}
1187EXPORT_SYMBOL_GPL(uislib_cache_free);
1188
1189
1190
1191
1192
1193#define PLINE(...) uisutil_add_proc_line_ex(&tot, buff, \
1194 buff_len, __VA_ARGS__)
1195
1196static int
1197info_debugfs_read_helper(char **buff, int *buff_len)
1198{
1199 int i, tot = 0;
1200 struct bus_info *bus;
1201
1202 if (PLINE("\nBuses:\n") < 0)
1203 goto err_done;
1204
1205 read_lock(&BusListLock);
1206 for (bus = BusListHead; bus; bus = bus->next) {
1207
1208 if (PLINE(" bus=0x%p, busNo=%d, deviceCount=%d\n",
1209 bus, bus->busNo, bus->deviceCount) < 0)
1210 goto err_done_unlock;
1211
1212
1213 if (PLINE(" Devices:\n") < 0)
1214 goto err_done_unlock;
1215
1216 for (i = 0; i < bus->deviceCount; i++) {
1217 if (bus->device[i]) {
1218 if (PLINE(" busNo %d, device[%i]: 0x%p, chanptr=0x%p, swtch=0x%p\n",
1219 bus->busNo, i, bus->device[i],
1220 bus->device[i]->chanptr,
1221 bus->device[i]->swtch) < 0)
1222 goto err_done_unlock;
1223
1224 if (PLINE(" first_busy_cnt=%llu, moved_to_tail_cnt=%llu, last_on_list_cnt=%llu\n",
1225 bus->device[i]->first_busy_cnt,
1226 bus->device[i]->moved_to_tail_cnt,
1227 bus->device[i]->last_on_list_cnt) < 0)
1228 goto err_done_unlock;
1229 }
1230 }
1231 }
1232 read_unlock(&BusListLock);
1233
1234 if (PLINE("UisUtils_Registered_Services: %d\n",
1235 atomic_read(&UisUtils_Registered_Services)) < 0)
1236 goto err_done;
1237 if (PLINE("cycles_before_wait %llu wait_cycles:%llu\n",
1238 cycles_before_wait, wait_cycles) < 0)
1239 goto err_done;
1240 if (PLINE("tot_wakeup_cnt %llu:tot_wait_cnt %llu:tot_schedule_cnt %llu\n",
1241 tot_wakeup_cnt, tot_wait_cnt, tot_schedule_cnt) < 0)
1242 goto err_done;
1243 if (PLINE("en_smart_wakeup %d\n", en_smart_wakeup) < 0)
1244 goto err_done;
1245 if (PLINE("tot_moved_to_tail_cnt %llu\n", tot_moved_to_tail_cnt) < 0)
1246 goto err_done;
1247
1248 return tot;
1249
1250err_done_unlock:
1251 read_unlock(&BusListLock);
1252err_done:
1253 return -1;
1254}
1255
1256static ssize_t
1257info_debugfs_read(struct file *file, char __user *buf,
1258 size_t len, loff_t *offset)
1259{
1260 char *temp;
1261 int totalBytes = 0;
1262 int remaining_bytes = PROC_READ_BUFFER_SIZE;
1263
1264
1265 if (ProcReadBuffer == NULL) {
1266 DBGINF("ProcReadBuffer == NULL; allocating buffer.\n.");
1267 ProcReadBuffer = vmalloc(PROC_READ_BUFFER_SIZE);
1268
1269 if (ProcReadBuffer == NULL) {
1270 LOGERR("failed to allocate buffer to provide proc data.\n");
1271 return -ENOMEM;
1272 }
1273 }
1274
1275 temp = ProcReadBuffer;
1276
1277 if ((*offset == 0) || (!ProcReadBufferValid)) {
1278 DBGINF("calling info_debugfs_read_helper.\n");
1279
1280 totalBytes = info_debugfs_read_helper(&temp, &remaining_bytes);
1281 ProcReadBufferValid = 1;
1282 } else
1283 totalBytes = strlen(ProcReadBuffer);
1284
1285 return simple_read_from_buffer(buf, len, offset,
1286 ProcReadBuffer, totalBytes);
1287}
1288
1289static struct device_info *
1290find_dev(u32 busNo, u32 devNo)
1291{
1292 struct bus_info *bus;
1293 struct device_info *dev = NULL;
1294
1295 read_lock(&BusListLock);
1296 for (bus = BusListHead; bus; bus = bus->next) {
1297 if (bus->busNo == busNo) {
1298
1299 if (devNo >= bus->deviceCount) {
1300 LOGERR("%s bad busNo, devNo=%d,%d",
1301 __func__,
1302 (int) (busNo), (int) (devNo));
1303 goto Away;
1304 }
1305 dev = bus->device[devNo];
1306 if (!dev)
1307 LOGERR("%s bad busNo, devNo=%d,%d",
1308 __func__,
1309 (int) (busNo), (int) (devNo));
1310 goto Away;
1311 }
1312 }
1313Away:
1314 read_unlock(&BusListLock);
1315 return dev;
1316}
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338static int
1339Process_Incoming(void *v)
1340{
1341 unsigned long long cur_cycles, old_cycles, idle_cycles, delta_cycles;
1342 struct list_head *new_tail = NULL;
1343 int i;
1344
1345 UIS_DAEMONIZE("dev_incoming");
1346 for (i = 0; i < 16; i++) {
1347 old_cycles = get_cycles();
1348 wait_event_timeout(Wakeup_Polling_Device_Channels,
1349 0, POLLJIFFIES_NORMAL);
1350 cur_cycles = get_cycles();
1351 if (wait_cycles == 0) {
1352 wait_cycles = (cur_cycles - old_cycles);
1353 } else {
1354 if (wait_cycles < (cur_cycles - old_cycles))
1355 wait_cycles = (cur_cycles - old_cycles);
1356 }
1357 }
1358 LOGINF("wait_cycles=%llu", wait_cycles);
1359 cycles_before_wait = wait_cycles;
1360 idle_cycles = 0;
1361 Go_Polling_Device_Channels = 0;
1362 while (1) {
1363 struct list_head *lelt, *tmp;
1364 struct device_info *dev = NULL;
1365
1366
1367 down(&Lock_Polling_Device_Channels);
1368 new_tail = NULL;
1369 list_for_each_safe(lelt, tmp, &List_Polling_Device_Channels) {
1370 int rc = 0;
1371
1372 dev = list_entry(lelt, struct device_info,
1373 list_polling_device_channels);
1374 down(&dev->interrupt_callback_lock);
1375 if (dev->interrupt)
1376 rc = dev->interrupt(dev->interrupt_context);
1377 else
1378 continue;
1379 up(&dev->interrupt_callback_lock);
1380 if (rc) {
1381
1382
1383
1384
1385 idle_cycles = 0;
1386 if (new_tail == NULL) {
1387 dev->first_busy_cnt++;
1388 if (!
1389 (list_is_last
1390 (lelt,
1391 &List_Polling_Device_Channels))) {
1392 new_tail = lelt;
1393 dev->moved_to_tail_cnt++;
1394 } else
1395 dev->last_on_list_cnt++;
1396 }
1397
1398 }
1399 if (Incoming_ThreadInfo.should_stop)
1400 break;
1401 }
1402 if (new_tail != NULL) {
1403 tot_moved_to_tail_cnt++;
1404 list_move_tail(new_tail, &List_Polling_Device_Channels);
1405 }
1406 up(&Lock_Polling_Device_Channels);
1407 cur_cycles = get_cycles();
1408 delta_cycles = cur_cycles - old_cycles;
1409 old_cycles = cur_cycles;
1410
1411
1412
1413
1414
1415
1416 if (Incoming_ThreadInfo.should_stop)
1417 break;
1418 if (en_smart_wakeup == 0xFF) {
1419 LOGINF("en_smart_wakeup set to 0xff, to force exiting process_incoming");
1420 break;
1421 }
1422
1423
1424
1425
1426
1427 if (idle_cycles > cycles_before_wait) {
1428 Go_Polling_Device_Channels = 0;
1429 tot_wait_cnt++;
1430 wait_event_timeout(Wakeup_Polling_Device_Channels,
1431 Go_Polling_Device_Channels,
1432 POLLJIFFIES_NORMAL);
1433 Go_Polling_Device_Channels = 1;
1434 } else {
1435 tot_schedule_cnt++;
1436 schedule();
1437 idle_cycles = idle_cycles + delta_cycles;
1438 }
1439 }
1440 DBGINF("exiting.\n");
1441 complete_and_exit(&Incoming_ThreadInfo.has_stopped, 0);
1442}
1443
1444static BOOL
1445Initialize_incoming_thread(void)
1446{
1447 if (Incoming_Thread_Started)
1448 return TRUE;
1449 if (!uisthread_start(&Incoming_ThreadInfo,
1450 &Process_Incoming, NULL, "dev_incoming")) {
1451 LOGERR("uisthread_start Initialize_incoming_thread ****FAILED");
1452 return FALSE;
1453 }
1454 Incoming_Thread_Started = TRUE;
1455 return TRUE;
1456}
1457
1458
1459
1460
1461
1462
1463
1464void
1465uislib_enable_channel_interrupts(u32 bus_no, u32 dev_no,
1466 int (*interrupt)(void *),
1467 void *interrupt_context)
1468{
1469 struct device_info *dev;
1470
1471 dev = find_dev(bus_no, dev_no);
1472 if (!dev) {
1473 LOGERR("%s busNo=%d, devNo=%d", __func__, (int) (bus_no),
1474 (int) (dev_no));
1475 return;
1476 }
1477 down(&Lock_Polling_Device_Channels);
1478 Initialize_incoming_thread();
1479 dev->interrupt = interrupt;
1480 dev->interrupt_context = interrupt_context;
1481 dev->polling = TRUE;
1482 list_add_tail(&(dev->list_polling_device_channels),
1483 &List_Polling_Device_Channels);
1484 up(&Lock_Polling_Device_Channels);
1485}
1486EXPORT_SYMBOL_GPL(uislib_enable_channel_interrupts);
1487
1488
1489
1490
1491void
1492uislib_disable_channel_interrupts(u32 bus_no, u32 dev_no)
1493{
1494 struct device_info *dev;
1495
1496 dev = find_dev(bus_no, dev_no);
1497 if (!dev) {
1498 LOGERR("%s busNo=%d, devNo=%d", __func__, (int) (bus_no),
1499 (int) (dev_no));
1500 return;
1501 }
1502 down(&Lock_Polling_Device_Channels);
1503 list_del(&dev->list_polling_device_channels);
1504 dev->polling = FALSE;
1505 dev->interrupt = NULL;
1506 up(&Lock_Polling_Device_Channels);
1507}
1508EXPORT_SYMBOL_GPL(uislib_disable_channel_interrupts);
1509
1510static void
1511do_wakeup_polling_device_channels(struct work_struct *dummy)
1512{
1513 if (!Go_Polling_Device_Channels) {
1514 Go_Polling_Device_Channels = 1;
1515 wake_up(&Wakeup_Polling_Device_Channels);
1516 }
1517}
1518
1519static DECLARE_WORK(Work_wakeup_polling_device_channels,
1520 do_wakeup_polling_device_channels);
1521
1522
1523
1524
1525void
1526uislib_force_channel_interrupt(u32 bus_no, u32 dev_no)
1527{
1528 if (en_smart_wakeup == 0)
1529 return;
1530 if (Go_Polling_Device_Channels)
1531 return;
1532
1533
1534
1535
1536 tot_wakeup_cnt++;
1537 schedule_work(&Work_wakeup_polling_device_channels);
1538}
1539EXPORT_SYMBOL_GPL(uislib_force_channel_interrupt);
1540
1541
1542
1543
1544
1545static int __init
1546uislib_mod_init(void)
1547{
1548
1549 if (!unisys_spar_platform)
1550 return -ENODEV;
1551
1552 LOGINF("MONITORAPIS");
1553
1554 LOGINF("sizeof(struct uiscmdrsp):%lu bytes\n",
1555 (ulong) sizeof(struct uiscmdrsp));
1556 LOGINF("sizeof(struct phys_info):%lu\n",
1557 (ulong) sizeof(struct phys_info));
1558 LOGINF("sizeof(uiscmdrsp_scsi):%lu\n",
1559 (ulong) sizeof(struct uiscmdrsp_scsi));
1560 LOGINF("sizeof(uiscmdrsp_net):%lu\n",
1561 (ulong) sizeof(struct uiscmdrsp_net));
1562 LOGINF("sizeof(CONTROLVM_MESSAGE):%lu bytes\n",
1563 (ulong) sizeof(CONTROLVM_MESSAGE));
1564 LOGINF("sizeof(ULTRA_CONTROLVM_CHANNEL_PROTOCOL):%lu bytes\n",
1565 (ulong) sizeof(ULTRA_CONTROLVM_CHANNEL_PROTOCOL));
1566 LOGINF("sizeof(CHANNEL_HEADER):%lu bytes\n",
1567 (ulong) sizeof(CHANNEL_HEADER));
1568 LOGINF("sizeof(ULTRA_IO_CHANNEL_PROTOCOL):%lu bytes\n",
1569 (ulong) sizeof(ULTRA_IO_CHANNEL_PROTOCOL));
1570 LOGINF("SIZEOF_CMDRSP:%lu bytes\n", SIZEOF_CMDRSP);
1571 LOGINF("SIZEOF_PROTOCOL:%lu bytes\n", SIZEOF_PROTOCOL);
1572
1573
1574 BusListHead = NULL;
1575 BusListCount = MaxBusCount = 0;
1576 rwlock_init(&BusListLock);
1577 VirtControlChanFunc = NULL;
1578
1579
1580
1581 POSTCODE_LINUX_2(DRIVER_ENTRY_PC, POSTCODE_SEVERITY_INFO);
1582
1583 dir_debugfs = debugfs_create_dir(DIR_DEBUGFS_ENTRY, NULL);
1584 if (dir_debugfs) {
1585 info_debugfs_entry = debugfs_create_file(
1586 INFO_DEBUGFS_ENTRY_FN, 0444, dir_debugfs, NULL,
1587 &debugfs_info_fops);
1588
1589 platformnumber_debugfs_read = debugfs_create_u32(
1590 PLATFORMNUMBER_DEBUGFS_ENTRY_FN, 0444, dir_debugfs,
1591 &PlatformNumber);
1592
1593 cycles_before_wait_debugfs_read = debugfs_create_u64(
1594 CYCLES_BEFORE_WAIT_DEBUGFS_ENTRY_FN, 0666, dir_debugfs,
1595 &cycles_before_wait);
1596
1597 smart_wakeup_debugfs_entry = debugfs_create_bool(
1598 SMART_WAKEUP_DEBUGFS_ENTRY_FN, 0666, dir_debugfs,
1599 &en_smart_wakeup);
1600 }
1601
1602 POSTCODE_LINUX_3(DRIVER_EXIT_PC, 0, POSTCODE_SEVERITY_INFO);
1603 return 0;
1604}
1605
1606static void __exit
1607uislib_mod_exit(void)
1608{
1609 if (ProcReadBuffer) {
1610 vfree(ProcReadBuffer);
1611 ProcReadBuffer = NULL;
1612 }
1613
1614 debugfs_remove(info_debugfs_entry);
1615 debugfs_remove(smart_wakeup_debugfs_entry);
1616 debugfs_remove(cycles_before_wait_debugfs_read);
1617 debugfs_remove(platformnumber_debugfs_read);
1618 debugfs_remove(dir_debugfs);
1619
1620 DBGINF("goodbye.\n");
1621}
1622
1623module_init(uislib_mod_init);
1624module_exit(uislib_mod_exit);
1625
1626MODULE_LICENSE("GPL");
1627MODULE_AUTHOR("Usha Srinivasan");
1628MODULE_ALIAS("uislib");
1629
1630