Merge tag 'iwlwifi-next-for-kalle-2014-12-30' of https://git.kernel.org/pub/scm/linux...
[cascardo/linux.git] / arch / s390 / kvm / sigp.c
index 9ee63e4..6651f9f 100644 (file)
@@ -46,15 +46,16 @@ static int __sigp_sense(struct kvm_vcpu *vcpu, struct kvm_vcpu *dst_vcpu,
        return rc;
 }
 
-static int __sigp_emergency(struct kvm_vcpu *vcpu, struct kvm_vcpu *dst_vcpu)
+static int __inject_sigp_emergency(struct kvm_vcpu *vcpu,
+                                   struct kvm_vcpu *dst_vcpu)
 {
-       struct kvm_s390_interrupt s390int = {
+       struct kvm_s390_irq irq = {
                .type = KVM_S390_INT_EMERGENCY,
-               .parm = vcpu->vcpu_id,
+               .u.emerg.code = vcpu->vcpu_id,
        };
        int rc = 0;
 
-       rc = kvm_s390_inject_vcpu(dst_vcpu, &s390int);
+       rc = kvm_s390_inject_vcpu(dst_vcpu, &irq);
        if (!rc)
                VCPU_EVENT(vcpu, 4, "sent sigp emerg to cpu %x",
                           dst_vcpu->vcpu_id);
@@ -62,6 +63,11 @@ static int __sigp_emergency(struct kvm_vcpu *vcpu, struct kvm_vcpu *dst_vcpu)
        return rc ? rc : SIGP_CC_ORDER_CODE_ACCEPTED;
 }
 
+static int __sigp_emergency(struct kvm_vcpu *vcpu, struct kvm_vcpu *dst_vcpu)
+{
+       return __inject_sigp_emergency(vcpu, dst_vcpu);
+}
+
 static int __sigp_conditional_emergency(struct kvm_vcpu *vcpu,
                                        struct kvm_vcpu *dst_vcpu,
                                        u16 asn, u64 *reg)
@@ -76,12 +82,12 @@ static int __sigp_conditional_emergency(struct kvm_vcpu *vcpu,
        p_asn = dst_vcpu->arch.sie_block->gcr[4] & 0xffff;  /* Primary ASN */
        s_asn = dst_vcpu->arch.sie_block->gcr[3] & 0xffff;  /* Secondary ASN */
 
-       /* Deliver the emergency signal? */
+       /* Inject the emergency signal? */
        if (!(flags & CPUSTAT_STOPPED)
            || (psw->mask & psw_int_mask) != psw_int_mask
            || ((flags & CPUSTAT_WAIT) && psw->addr != 0)
            || (!(flags & CPUSTAT_WAIT) && (asn == p_asn || asn == s_asn))) {
-               return __sigp_emergency(vcpu, dst_vcpu);
+               return __inject_sigp_emergency(vcpu, dst_vcpu);
        } else {
                *reg &= 0xffffffff00000000UL;
                *reg |= SIGP_STATUS_INCORRECT_STATE;
@@ -92,13 +98,13 @@ static int __sigp_conditional_emergency(struct kvm_vcpu *vcpu,
 static int __sigp_external_call(struct kvm_vcpu *vcpu,
                                struct kvm_vcpu *dst_vcpu)
 {
-       struct kvm_s390_interrupt s390int = {
+       struct kvm_s390_irq irq = {
                .type = KVM_S390_INT_EXTERNAL_CALL,
-               .parm = vcpu->vcpu_id,
+               .u.extcall.code = vcpu->vcpu_id,
        };
        int rc;
 
-       rc = kvm_s390_inject_vcpu(dst_vcpu, &s390int);
+       rc = kvm_s390_inject_vcpu(dst_vcpu, &irq);
        if (!rc)
                VCPU_EVENT(vcpu, 4, "sent sigp ext call to cpu %x",
                           dst_vcpu->vcpu_id);
@@ -109,29 +115,20 @@ static int __sigp_external_call(struct kvm_vcpu *vcpu,
 static int __inject_sigp_stop(struct kvm_vcpu *dst_vcpu, int action)
 {
        struct kvm_s390_local_interrupt *li = &dst_vcpu->arch.local_int;
-       struct kvm_s390_interrupt_info *inti;
        int rc = SIGP_CC_ORDER_CODE_ACCEPTED;
 
-       inti = kzalloc(sizeof(*inti), GFP_ATOMIC);
-       if (!inti)
-               return -ENOMEM;
-       inti->type = KVM_S390_SIGP_STOP;
-
        spin_lock(&li->lock);
        if (li->action_bits & ACTION_STOP_ON_STOP) {
                /* another SIGP STOP is pending */
-               kfree(inti);
                rc = SIGP_CC_BUSY;
                goto out;
        }
        if ((atomic_read(li->cpuflags) & CPUSTAT_STOPPED)) {
-               kfree(inti);
                if ((action & ACTION_STORE_ON_STOP) != 0)
                        rc = -ESHUTDOWN;
                goto out;
        }
-       list_add_tail(&inti->list, &li->list);
-       atomic_set(&li->active, 1);
+       set_bit(IRQ_PEND_SIGP_STOP, &li->pending_irqs);
        li->action_bits |= action;
        atomic_set_mask(CPUSTAT_STOP_INT, li->cpuflags);
        kvm_s390_vcpu_wakeup(dst_vcpu);
@@ -141,15 +138,27 @@ out:
        return rc;
 }
 
-static int __sigp_stop(struct kvm_vcpu *vcpu, struct kvm_vcpu *dst_vcpu,
-                      int action)
+static int __sigp_stop(struct kvm_vcpu *vcpu, struct kvm_vcpu *dst_vcpu)
 {
        int rc;
 
-       rc = __inject_sigp_stop(dst_vcpu, action);
+       rc = __inject_sigp_stop(dst_vcpu, ACTION_STOP_ON_STOP);
        VCPU_EVENT(vcpu, 4, "sent sigp stop to cpu %x", dst_vcpu->vcpu_id);
 
-       if ((action & ACTION_STORE_ON_STOP) != 0 && rc == -ESHUTDOWN) {
+       return rc;
+}
+
+static int __sigp_stop_and_store_status(struct kvm_vcpu *vcpu,
+                                       struct kvm_vcpu *dst_vcpu, u64 *reg)
+{
+       int rc;
+
+       rc = __inject_sigp_stop(dst_vcpu, ACTION_STOP_ON_STOP |
+                                             ACTION_STORE_ON_STOP);
+       VCPU_EVENT(vcpu, 4, "sent sigp stop and store status to cpu %x",
+                  dst_vcpu->vcpu_id);
+
+       if (rc == -ESHUTDOWN) {
                /* If the CPU has already been stopped, we still have
                 * to save the status when doing stop-and-store. This
                 * has to be done after unlocking all spinlocks. */
@@ -189,7 +198,6 @@ static int __sigp_set_prefix(struct kvm_vcpu *vcpu, struct kvm_vcpu *dst_vcpu,
                             u32 address, u64 *reg)
 {
        struct kvm_s390_local_interrupt *li;
-       struct kvm_s390_interrupt_info *inti;
        int rc;
 
        li = &dst_vcpu->arch.local_int;
@@ -206,25 +214,17 @@ static int __sigp_set_prefix(struct kvm_vcpu *vcpu, struct kvm_vcpu *dst_vcpu,
                return SIGP_CC_STATUS_STORED;
        }
 
-       inti = kzalloc(sizeof(*inti), GFP_KERNEL);
-       if (!inti)
-               return SIGP_CC_BUSY;
-
        spin_lock(&li->lock);
        /* cpu must be in stopped state */
        if (!(atomic_read(li->cpuflags) & CPUSTAT_STOPPED)) {
                *reg &= 0xffffffff00000000UL;
                *reg |= SIGP_STATUS_INCORRECT_STATE;
                rc = SIGP_CC_STATUS_STORED;
-               kfree(inti);
                goto out_li;
        }
 
-       inti->type = KVM_S390_SIGP_SET_PREFIX;
-       inti->prefix.address = address;
-
-       list_add_tail(&inti->list, &li->list);
-       atomic_set(&li->active, 1);
+       li->irq.prefix.address = address;
+       set_bit(IRQ_PEND_SET_PREFIX, &li->pending_irqs);
        kvm_s390_vcpu_wakeup(dst_vcpu);
        rc = SIGP_CC_ORDER_CODE_ACCEPTED;
 
@@ -341,12 +341,11 @@ static int handle_sigp_dst(struct kvm_vcpu *vcpu, u8 order_code,
                break;
        case SIGP_STOP:
                vcpu->stat.instruction_sigp_stop++;
-               rc = __sigp_stop(vcpu, dst_vcpu, ACTION_STOP_ON_STOP);
+               rc = __sigp_stop(vcpu, dst_vcpu);
                break;
        case SIGP_STOP_AND_STORE_STATUS:
                vcpu->stat.instruction_sigp_stop_store_status++;
-               rc = __sigp_stop(vcpu, dst_vcpu, ACTION_STORE_ON_STOP |
-                                                ACTION_STOP_ON_STOP);
+               rc = __sigp_stop_and_store_status(vcpu, dst_vcpu, status_reg);
                break;
        case SIGP_STORE_STATUS_AT_ADDRESS:
                vcpu->stat.instruction_sigp_store_status++;