25 #include <linux/kernel.h>
26 #include <linux/module.h>
28 #include <linux/types.h>
34 #include <linux/slab.h>
35 #include <linux/poll.h>
37 #include <linux/reboot.h>
45 #include <linux/fsl_hypervisor.h>
62 param.ret = fh_partition_restart(
param.partition);
84 param.ret = fh_partition_get_status(
param.partition, &status);
129 param.ret = fh_partition_stop(
param.partition);
151 void *sg_list_unaligned =
NULL;
155 unsigned long lb_offset;
172 if ((
param.source == -1) == (
param.target == -1))
227 pr_debug(
"fsl-hv: could not allocate page list\n");
237 if (!sg_list_unaligned) {
238 pr_debug(
"fsl-hv: could not allocate S/G list\n");
247 param.local_vaddr - lb_offset, num_pages,
252 if (num_pinned != num_pages) {
254 pr_debug(
"fsl-hv: could not lock source buffer\n");
255 ret = (num_pinned < 0) ? num_pinned : -
EFAULT;
263 if (
param.source == -1) {
272 remote_paddr =
param.remote_paddr + sg_list[0].
size;
276 if (
param.source == -1) {
279 sg_list[
i].
target = remote_paddr;
282 sg_list[
i].
source = remote_paddr;
287 remote_paddr += sg_list[
i].
size;
288 count -= sg_list[
i].
size;
301 kfree(sg_list_unaligned);
335 char __user *upath, *upropname;
356 if (IS_ERR(propname)) {
357 ret = PTR_ERR(propname);
378 param.ret = fh_partition_set_dtprop(
param.handle,
384 param.ret = fh_partition_get_dtprop(
param.handle,
390 if (
param.ret == 0) {
413 static long fsl_hv_ioctl(
struct file *
file,
unsigned int cmd,
414 unsigned long argaddr)
421 ret = ioctl_restart(arg);
424 ret = ioctl_status(arg);
427 ret = ioctl_start(arg);
430 ret = ioctl_stop(arg);
433 ret = ioctl_memcpy(arg);
436 ret = ioctl_doorbell(arg);
439 ret = ioctl_dtprop(arg, 0);
442 ret = ioctl_dtprop(arg, 1);
445 pr_debug(
"fsl-hv: bad ioctl dir=%u type=%u cmd=%u size=%u\n",
464 #define nextp(x) (((x) + 1) & (QSIZE - 1))
511 spin_unlock_irqrestore(&db_list_lock, flags);
538 static irqreturn_t fsl_hv_state_change_thread(
int irq,
void *data)
551 static irqreturn_t fsl_hv_state_change_isr(
int irq,
void *data)
558 fsl_hv_queue_doorbell(dbisr->
doorbell);
561 ret = fh_partition_get_status(dbisr->
partition, &status);
579 poll_wait(filp, &dbq->
wait, p);
582 spin_unlock_irqrestore(&dbq->
lock, flags);
594 static ssize_t fsl_hv_read(
struct file *filp,
char __user *
buf,
size_t len,
614 spin_unlock_irqrestore(&dbq->
lock, flags);
638 dbell = dbq->
q[dbq->
head];
641 spin_unlock_irqrestore(&dbq->
lock, flags);
659 static int fsl_hv_open(
struct inode *
inode,
struct file *filp)
667 pr_err(
"fsl-hv: out of memory\n");
675 list_add(&dbq->
list, &db_list);
676 spin_unlock_irqrestore(&db_list_lock, flags);
686 static int fsl_hv_close(
struct inode *inode,
struct file *filp)
695 spin_unlock_irqrestore(&db_list_lock, flags);
705 .release = fsl_hv_close,
708 .unlocked_ioctl = fsl_hv_ioctl,
709 .compat_ioctl = fsl_hv_ioctl,
718 static irqreturn_t fsl_hv_shutdown_isr(
int irq,
void *data)
730 static int get_parent_handle(
struct device_node *np)
750 if (!prop || (len !=
sizeof(
uint32_t))) {
794 static int has_fsl_hypervisor(
void)
799 if (!(mfmsr() & MSR_GS))
821 static int __init fsl_hypervisor_init(
void)
827 pr_info(
"Freescale hypervisor management driver\n");
829 if (!has_fsl_hypervisor()) {
830 pr_info(
"fsl-hv: no hypervisor found\n");
836 pr_err(
"fsl-hv: cannot register device\n");
840 INIT_LIST_HEAD(&db_list);
843 for_each_compatible_node(np,
NULL,
"epapr,hv-receive-doorbell") {
849 if (!handle || (irq ==
NO_IRQ)) {
850 pr_err(
"fsl-hv: no 'interrupts' property in %s node\n",
867 "fsl,hv-state-change-doorbell")) {
876 dbisr->
partition = ret = get_parent_handle(np);
878 pr_err(
"fsl-hv: node %s has missing or "
884 fsl_hv_state_change_thread,
890 pr_err(
"fsl-hv: could not request irq %u for node %s\n",
898 pr_info(
"fsl-hv: registered handler for doorbell %u\n",
921 static void __exit fsl_hypervisor_exit(
void)