LinuxPPC-Dev Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 12/13] KVM: PPC: Implement MMU notifiers for Book3S HV guests
From: Paul Mackerras @ 2011-12-06  6:14 UTC (permalink / raw)
  To: Alexander Graf; +Cc: linuxppc-dev, kvm, kvm-ppc
In-Reply-To: <20111206060156.GD12389@drongo>

This adds the infrastructure to enable us to page out pages underneath
a Book3S HV guest, on processors that support virtualized partition
memory, that is, POWER7.  Instead of pinning all the guest's pages,
we now look in the host userspace Linux page tables to find the
mapping for a given guest page.  Then, if the userspace Linux PTE
gets invalidated, kvm_unmap_hva() gets called for that address, and
we replace all the guest HPTEs that refer to that page with absent
HPTEs, i.e. ones with the valid bit clear and the HPTE_V_ABSENT bit
set, which will cause an HDSI when the guest tries to access them.
Finally, the page fault handler is extended to reinstantiate the
guest HPTE when the guest tries to access a page which has been paged
out.

Since we can't intercept the guest DSI and ISI interrupts on PPC970,
we still have to pin all the guest pages on PPC970.  We have a new flag,
kvm->arch.using_mmu_notifiers, that indicates whether we can page
guest pages out.  If it is not set, the MMU notifier callbacks do
nothing and everything operates as before.

Signed-off-by: Paul Mackerras <paulus@samba.org>
---
 arch/powerpc/include/asm/kvm_book3s.h    |    4 +
 arch/powerpc/include/asm/kvm_book3s_64.h |   31 ++++
 arch/powerpc/include/asm/kvm_host.h      |   16 ++
 arch/powerpc/include/asm/reg.h           |    3 +
 arch/powerpc/kvm/Kconfig                 |    1 +
 arch/powerpc/kvm/book3s_64_mmu_hv.c      |  268 ++++++++++++++++++++++++++++--
 arch/powerpc/kvm/book3s_hv.c             |   25 ++--
 arch/powerpc/kvm/book3s_hv_rm_mmu.c      |  140 ++++++++++++----
 arch/powerpc/kvm/book3s_hv_rmhandlers.S  |   49 ++++++
 arch/powerpc/kvm/powerpc.c               |    3 +
 arch/powerpc/mm/hugetlbpage.c            |    2 +
 11 files changed, 483 insertions(+), 59 deletions(-)

diff --git a/arch/powerpc/include/asm/kvm_book3s.h b/arch/powerpc/include/asm/kvm_book3s.h
index 5ac53f9..72688d8 100644
--- a/arch/powerpc/include/asm/kvm_book3s.h
+++ b/arch/powerpc/include/asm/kvm_book3s.h
@@ -145,6 +145,10 @@ extern void kvmppc_set_bat(struct kvm_vcpu *vcpu, struct kvmppc_bat *bat,
 extern void kvmppc_giveup_ext(struct kvm_vcpu *vcpu, ulong msr);
 extern int kvmppc_emulate_paired_single(struct kvm_run *run, struct kvm_vcpu *vcpu);
 extern pfn_t kvmppc_gfn_to_pfn(struct kvm_vcpu *vcpu, gfn_t gfn);
+extern void kvmppc_add_revmap_chain(struct kvm *kvm, struct revmap_entry *rev,
+			unsigned long *rmap, long pte_index, int realmode);
+extern void kvmppc_invalidate_hpte(struct kvm *kvm, unsigned long *hptep,
+			unsigned long pte_index);
 extern void *kvmppc_pin_guest_page(struct kvm *kvm, unsigned long addr,
 			unsigned long *nb_ret);
 extern void kvmppc_unpin_guest_page(struct kvm *kvm, void *addr);
diff --git a/arch/powerpc/include/asm/kvm_book3s_64.h b/arch/powerpc/include/asm/kvm_book3s_64.h
index 9a59b6d..75a1b42 100644
--- a/arch/powerpc/include/asm/kvm_book3s_64.h
+++ b/arch/powerpc/include/asm/kvm_book3s_64.h
@@ -130,6 +130,37 @@ static inline int hpte_cache_flags_ok(unsigned long ptel, unsigned long io_type)
 	return (wimg & (HPTE_R_W | HPTE_R_I)) == io_type;
 }
 
+/*
+ * Lock and read a linux PTE.  If it's present and writable, atomically
+ * set dirty and referenced bits and return the PTE, otherwise return 0.
+ */
+static inline pte_t kvmppc_read_update_linux_pte(pte_t *p)
+{
+	pte_t pte, tmp;
+
+	/* wait until _PAGE_BUSY is clear then set it atomically */
+	__asm__ __volatile__ (
+		"1:	ldarx	%0,0,%3\n"
+		"	andi.	%1,%0,%4\n"
+		"	bne-	1b\n"
+		"	ori	%1,%0,%4\n"
+		"	stdcx.	%1,0,%3\n"
+		"	bne-	1b"
+		: "=&r" (pte), "=&r" (tmp), "=m" (*p)
+		: "r" (p), "i" (_PAGE_BUSY)
+		: "cc");
+
+	if (pte_present(pte)) {
+		pte = pte_mkyoung(pte);
+		if (pte_write(pte))
+			pte = pte_mkdirty(pte);
+	}
+
+	*p = pte;	/* clears _PAGE_BUSY */
+
+	return pte;
+}
+
 /* Return HPTE cache control bits corresponding to Linux pte bits */
 static inline unsigned long hpte_cache_bits(unsigned long pte_val)
 {
diff --git a/arch/powerpc/include/asm/kvm_host.h b/arch/powerpc/include/asm/kvm_host.h
index c9c92f0..eb20ddc 100644
--- a/arch/powerpc/include/asm/kvm_host.h
+++ b/arch/powerpc/include/asm/kvm_host.h
@@ -32,6 +32,7 @@
 #include <linux/atomic.h>
 #include <asm/kvm_asm.h>
 #include <asm/processor.h>
+#include <asm/page.h>
 
 #define KVM_MAX_VCPUS		NR_CPUS
 #define KVM_MAX_VCORES		NR_CPUS
@@ -43,6 +44,19 @@
 #define KVM_COALESCED_MMIO_PAGE_OFFSET 1
 #endif
 
+#ifdef CONFIG_KVM_BOOK3S_64_HV
+#include <linux/mmu_notifier.h>
+
+#define KVM_ARCH_WANT_MMU_NOTIFIER
+
+struct kvm;
+extern int kvm_unmap_hva(struct kvm *kvm, unsigned long hva);
+extern int kvm_age_hva(struct kvm *kvm, unsigned long hva);
+extern int kvm_test_age_hva(struct kvm *kvm, unsigned long hva);
+extern void kvm_set_spte_hva(struct kvm *kvm, unsigned long hva, pte_t pte);
+
+#endif
+
 /* We don't currently support large pages. */
 #define KVM_HPAGE_GFN_SHIFT(x)	0
 #define KVM_NR_PAGE_SIZES	1
@@ -211,6 +225,7 @@ struct kvm_arch {
 	struct kvmppc_rma_info *rma;
 	unsigned long vrma_slb_v;
 	int rma_setup_done;
+	int using_mmu_notifiers;
 	struct list_head spapr_tce_tables;
 	spinlock_t slot_phys_lock;
 	unsigned long *slot_phys[KVM_MEMORY_SLOTS + KVM_PRIVATE_MEM_SLOTS];
@@ -459,6 +474,7 @@ struct kvm_vcpu_arch {
 	struct list_head run_list;
 	struct task_struct *run_task;
 	struct kvm_run *kvm_run;
+	pgd_t *pgdir;
 #endif
 };
 
diff --git a/arch/powerpc/include/asm/reg.h b/arch/powerpc/include/asm/reg.h
index c74379a..209dc74 100644
--- a/arch/powerpc/include/asm/reg.h
+++ b/arch/powerpc/include/asm/reg.h
@@ -495,6 +495,9 @@
 #define SPRN_SPRG7	0x117	/* Special Purpose Register General 7 */
 #define SPRN_SRR0	0x01A	/* Save/Restore Register 0 */
 #define SPRN_SRR1	0x01B	/* Save/Restore Register 1 */
+#define   SRR1_ISI_NOPT		0x40000000 /* ISI: Not found in hash */
+#define   SRR1_ISI_N_OR_G	0x10000000 /* ISI: Access is no-exec or G */
+#define   SRR1_ISI_PROT		0x08000000 /* ISI: Other protection fault */
 #define   SRR1_WAKEMASK		0x00380000 /* reason for wakeup */
 #define   SRR1_WAKESYSERR	0x00300000 /* System error */
 #define   SRR1_WAKEEE		0x00200000 /* External interrupt */
diff --git a/arch/powerpc/kvm/Kconfig b/arch/powerpc/kvm/Kconfig
index 78133de..8f64709 100644
--- a/arch/powerpc/kvm/Kconfig
+++ b/arch/powerpc/kvm/Kconfig
@@ -69,6 +69,7 @@ config KVM_BOOK3S_64
 config KVM_BOOK3S_64_HV
 	bool "KVM support for POWER7 and PPC970 using hypervisor mode in host"
 	depends on KVM_BOOK3S_64
+	select MMU_NOTIFIER
 	---help---
 	  Support running unmodified book3s_64 guest kernels in
 	  virtual machines on POWER7 and PPC970 processors that have
diff --git a/arch/powerpc/kvm/book3s_64_mmu_hv.c b/arch/powerpc/kvm/book3s_64_mmu_hv.c
index 2d31519..6919d99 100644
--- a/arch/powerpc/kvm/book3s_64_mmu_hv.c
+++ b/arch/powerpc/kvm/book3s_64_mmu_hv.c
@@ -281,8 +281,9 @@ static long kvmppc_get_guest_page(struct kvm *kvm, unsigned long gfn,
 }
 
 /*
- * We come here on a H_ENTER call from the guest when
- * we don't have the requested page pinned already.
+ * We come here on a H_ENTER call from the guest when we are not
+ * using mmu notifiers and we don't have the requested page pinned
+ * already.
  */
 long kvmppc_virtmode_h_enter(struct kvm_vcpu *vcpu, unsigned long flags,
 			long pte_index, unsigned long pteh, unsigned long ptel)
@@ -292,6 +293,9 @@ long kvmppc_virtmode_h_enter(struct kvm_vcpu *vcpu, unsigned long flags,
 	struct kvm_memory_slot *memslot;
 	long ret;
 
+	if (kvm->arch.using_mmu_notifiers)
+		goto do_insert;
+
 	psize = hpte_page_size(pteh, ptel);
 	if (!psize)
 		return H_PARAMETER;
@@ -309,7 +313,9 @@ long kvmppc_virtmode_h_enter(struct kvm_vcpu *vcpu, unsigned long flags,
 			return H_PARAMETER;
 	}
 
+ do_insert:
 	preempt_disable();
+	vcpu->arch.pgdir = current->mm->pgd;
 	ret = kvmppc_h_enter(vcpu, flags, pte_index, pteh, ptel);
 	preempt_enable();
 	if (ret == H_TOO_HARD) {
@@ -488,11 +494,15 @@ int kvmppc_book3s_hv_page_fault(struct kvm_run *run, struct kvm_vcpu *vcpu,
 {
 	struct kvm *kvm = vcpu->kvm;
 	unsigned long *hptep, hpte[3];
-	unsigned long psize;
-	unsigned long gfn;
+	unsigned long mmu_seq, psize, pte_size;
+	unsigned long gfn, hva, pfn;
 	struct kvm_memory_slot *memslot;
+	unsigned long *rmap;
 	struct revmap_entry *rev;
-	long index;
+	struct page *page, *pages[1];
+	long index, ret, npages;
+	unsigned long is_io;
+	struct vm_area_struct *vma;
 
 	/*
 	 * Real-mode code has already searched the HPT and found the
@@ -531,8 +541,219 @@ int kvmppc_book3s_hv_page_fault(struct kvm_run *run, struct kvm_vcpu *vcpu,
 					      dsisr & DSISR_ISSTORE);
 	}
 
-	/* should never get here otherwise */
-	return -EFAULT;
+	if (!kvm->arch.using_mmu_notifiers)
+		return -EFAULT;		/* should never get here */
+
+	/* used to check for invalidations in progress */
+	mmu_seq = kvm->mmu_notifier_seq;
+	smp_rmb();
+
+	is_io = 0;
+	pfn = 0;
+	page = NULL;
+	pte_size = PAGE_SIZE;
+	hva = gfn_to_hva_memslot(memslot, gfn);
+	npages = get_user_pages_fast(hva, 1, 1, pages);
+	if (npages < 1) {
+		/* Check if it's an I/O mapping */
+		down_read(&current->mm->mmap_sem);
+		vma = find_vma(current->mm, hva);
+		if (vma && vma->vm_start <= hva && hva + psize <= vma->vm_end &&
+		    (vma->vm_flags & VM_PFNMAP)) {
+			pfn = vma->vm_pgoff +
+				((hva - vma->vm_start) >> PAGE_SHIFT);
+			pte_size = psize;
+			is_io = hpte_cache_bits(pgprot_val(vma->vm_page_prot));
+		}
+		up_read(&current->mm->mmap_sem);
+		if (!pfn)
+			return -EFAULT;
+	} else {
+		page = pages[0];
+		if (PageHuge(page)) {
+			page = compound_head(page);
+			pte_size <<= compound_order(page);
+		}
+		pfn = page_to_pfn(page);
+	}
+
+	ret = -EFAULT;
+	if (psize > pte_size)
+		goto out_put;
+
+	/* Check WIMG vs. the actual page we're accessing */
+	if (!hpte_cache_flags_ok(hpte[1], is_io))
+		return -EFAULT;
+
+	/* Set the HPTE to point to pfn */
+	ret = RESUME_GUEST;
+	while (!try_lock_hpte(hptep, HPTE_V_HVLOCK))
+		cpu_relax();
+	if ((hptep[0] & ~HPTE_V_HVLOCK) != hpte[0] || hptep[1] != hpte[1] ||
+	    rev->guest_rpte != hpte[2]) {
+		/* HPTE has been changed under us; let the guest retry */
+		hptep[0] &= ~HPTE_V_HVLOCK;
+		goto out_put;
+	}
+	hpte[0] = (hpte[0] & ~HPTE_V_ABSENT) | HPTE_V_VALID;
+	hpte[1] = (rev->guest_rpte & ~(HPTE_R_PP0 - pte_size)) |
+		(pfn << PAGE_SHIFT);
+
+	rmap = &memslot->rmap[gfn - memslot->base_gfn];
+	lock_rmap(rmap);
+
+	/* Check if we might have been invalidated; let the guest retry if so */
+	ret = RESUME_GUEST;
+	if (mmu_notifier_retry(vcpu, mmu_seq)) {
+		unlock_rmap(rmap);
+		hptep[0] &= ~HPTE_V_HVLOCK;
+		goto out_put;
+	}
+	kvmppc_add_revmap_chain(kvm, rev, rmap, index, 0);
+
+	hptep[1] = hpte[1];
+	eieio();
+	hptep[0] = hpte[0];
+	asm volatile("ptesync" : : : "memory");
+	if (page)
+		SetPageDirty(page);
+
+ out_put:
+	if (page)
+		put_page(page);
+	return ret;
+}
+
+static int kvm_handle_hva(struct kvm *kvm, unsigned long hva,
+			  int (*handler)(struct kvm *kvm, unsigned long *rmapp,
+					 unsigned long gfn))
+{
+	int i;
+	int ret;
+	int retval = 0;
+	struct kvm_memslots *slots;
+
+	slots = kvm_memslots(kvm);
+	for (i = 0; i < slots->nmemslots; i++) {
+		struct kvm_memory_slot *memslot = &slots->memslots[i];
+		unsigned long start = memslot->userspace_addr;
+		unsigned long end;
+
+		end = start + (memslot->npages << PAGE_SHIFT);
+		if (hva >= start && hva < end) {
+			gfn_t gfn_offset = (hva - start) >> PAGE_SHIFT;
+
+			ret = handler(kvm, &memslot->rmap[gfn_offset],
+				      memslot->base_gfn + gfn_offset);
+			retval |= ret;
+		}
+	}
+
+	return retval;
+}
+
+static int kvm_unmap_rmapp(struct kvm *kvm, unsigned long *rmapp,
+			   unsigned long gfn)
+{
+	struct revmap_entry *rev = kvm->arch.revmap;
+	unsigned long h, i, j;
+	unsigned long *hptep;
+	unsigned long ptel, psize;
+
+	for (;;) {
+		while (test_and_set_bit_lock(KVMPPC_RMAP_LOCK_BIT, rmapp))
+			cpu_relax();
+		if (!(*rmapp & KVMPPC_RMAP_PRESENT)) {
+			__clear_bit_unlock(KVMPPC_RMAP_LOCK_BIT, rmapp);
+			break;
+		}
+
+		/*
+		 * To avoid an ABBA deadlock with the HPTE lock bit,
+		 * we have to unlock the rmap chain before locking the HPTE.
+		 * Thus we remove the first entry, unlock the rmap chain,
+		 * lock the HPTE and then check that it is for the
+		 * page we're unmapping before changing it to non-present.
+		 */
+		i = *rmapp & KVMPPC_RMAP_INDEX;
+		j = rev[i].forw;
+		if (j == i) {
+			/* chain is now empty */
+			j = 0;
+		} else {
+			/* remove i from chain */
+			h = rev[i].back;
+			rev[h].forw = j;
+			rev[j].back = h;
+			rev[i].forw = rev[i].back = i;
+			j |= KVMPPC_RMAP_PRESENT;
+		}
+		smp_wmb();
+		*rmapp = j | (1ul << KVMPPC_RMAP_REF_BIT);
+
+		/* Now lock, check and modify the HPTE */
+		hptep = (unsigned long *) (kvm->arch.hpt_virt + (i << 4));
+		while (!try_lock_hpte(hptep, HPTE_V_HVLOCK))
+			cpu_relax();
+		ptel = rev[i].guest_rpte;
+		psize = hpte_page_size(hptep[0], ptel);
+		if ((hptep[0] & HPTE_V_VALID) &&
+		    hpte_rpn(ptel, psize) == gfn) {
+			kvmppc_invalidate_hpte(kvm, hptep, i);
+			hptep[0] |= HPTE_V_ABSENT;
+		}
+		hptep[0] &= ~HPTE_V_HVLOCK;
+	}
+	return 0;
+}
+
+int kvm_unmap_hva(struct kvm *kvm, unsigned long hva)
+{
+	if (kvm->arch.using_mmu_notifiers)
+		kvm_handle_hva(kvm, hva, kvm_unmap_rmapp);
+	return 0;
+}
+
+static int kvm_age_rmapp(struct kvm *kvm, unsigned long *rmapp,
+			 unsigned long gfn)
+{
+	if (!kvm->arch.using_mmu_notifiers)
+		return 0;
+	if (!(*rmapp & KVMPPC_RMAP_REFERENCED))
+		return 0;
+	kvm_unmap_rmapp(kvm, rmapp, gfn);
+	while (test_and_set_bit_lock(KVMPPC_RMAP_LOCK_BIT, rmapp))
+		cpu_relax();
+	__clear_bit(KVMPPC_RMAP_REF_BIT, rmapp);
+	__clear_bit_unlock(KVMPPC_RMAP_LOCK_BIT, rmapp);
+	return 1;
+}
+
+int kvm_age_hva(struct kvm *kvm, unsigned long hva)
+{
+	if (!kvm->arch.using_mmu_notifiers)
+		return 0;
+	return kvm_handle_hva(kvm, hva, kvm_age_rmapp);
+}
+
+static int kvm_test_age_rmapp(struct kvm *kvm, unsigned long *rmapp,
+			      unsigned long gfn)
+{
+	return !!(*rmapp & KVMPPC_RMAP_REFERENCED);
+}
+
+int kvm_test_age_hva(struct kvm *kvm, unsigned long hva)
+{
+	if (!kvm->arch.using_mmu_notifiers)
+		return 0;
+	return kvm_handle_hva(kvm, hva, kvm_test_age_rmapp);
+}
+
+void kvm_set_spte_hva(struct kvm *kvm, unsigned long hva, pte_t pte)
+{
+	if (!kvm->arch.using_mmu_notifiers)
+		return;
+	kvm_handle_hva(kvm, hva, kvm_unmap_rmapp);
 }
 
 void *kvmppc_pin_guest_page(struct kvm *kvm, unsigned long gpa,
@@ -540,31 +761,42 @@ void *kvmppc_pin_guest_page(struct kvm *kvm, unsigned long gpa,
 {
 	struct kvm_memory_slot *memslot;
 	unsigned long gfn = gpa >> PAGE_SHIFT;
-	struct page *page;
-	unsigned long psize, offset;
+	struct page *page, *pages[1];
+	int npages;
+	unsigned long hva, psize, offset;
 	unsigned long pa;
 	unsigned long *physp;
 
 	memslot = gfn_to_memslot(kvm, gfn);
 	if (!memslot || (memslot->flags & KVM_MEMSLOT_INVALID))
 		return NULL;
-	physp = kvm->arch.slot_phys[memslot->id];
-	if (!physp)
-		return NULL;
-	physp += gfn - memslot->base_gfn;
-	pa = *physp;
-	if (!pa) {
-		if (kvmppc_get_guest_page(kvm, gfn, memslot, PAGE_SIZE) < 0)
+	if (!kvm->arch.using_mmu_notifiers) {
+		physp = kvm->arch.slot_phys[memslot->id];
+		if (!physp)
 			return NULL;
+		physp += gfn - memslot->base_gfn;
 		pa = *physp;
+		if (!pa) {
+			if (kvmppc_get_guest_page(kvm, gfn, memslot,
+						  PAGE_SIZE) < 0)
+				return NULL;
+			pa = *physp;
+		}
+		page = pfn_to_page(pa >> PAGE_SHIFT);
+	} else {
+		hva = gfn_to_hva_memslot(memslot, gfn);
+		npages = get_user_pages_fast(hva, 1, 1, pages);
+		if (npages < 1)
+			return NULL;
+		page = pages[0];
 	}
-	page = pfn_to_page(pa >> PAGE_SHIFT);
 	psize = PAGE_SIZE;
 	if (PageHuge(page)) {
 		page = compound_head(page);
 		psize <<= compound_order(page);
 	}
-	get_page(page);
+	if (!kvm->arch.using_mmu_notifiers)
+		get_page(page);
 	offset = gpa & (psize - 1);
 	if (nb_ret)
 		*nb_ret = psize - offset;
diff --git a/arch/powerpc/kvm/book3s_hv.c b/arch/powerpc/kvm/book3s_hv.c
index 38f7d05..4d2fcb0 100644
--- a/arch/powerpc/kvm/book3s_hv.c
+++ b/arch/powerpc/kvm/book3s_hv.c
@@ -324,19 +324,19 @@ static int kvmppc_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu,
 		break;
 	}
 	/*
-	 * We get this if the guest accesses a page which it thinks
-	 * it has mapped but which is not actually present, because
-	 * it is for an emulated I/O device.
-	 * Any other HDSI interrupt has been handled already.
+	 * We get these next two if the guest accesses a page which it thinks
+	 * it has mapped but which is not actually present, either because
+	 * it is for an emulated I/O device or because the corresonding
+	 * host page has been paged out.  Any other HDSI/HISI interrupts
+	 * have been handled already.
 	 */
 	case BOOK3S_INTERRUPT_H_DATA_STORAGE:
 		r = kvmppc_book3s_hv_page_fault(run, vcpu,
 				vcpu->arch.fault_dar, vcpu->arch.fault_dsisr);
 		break;
 	case BOOK3S_INTERRUPT_H_INST_STORAGE:
-		kvmppc_inject_interrupt(vcpu, BOOK3S_INTERRUPT_INST_STORAGE,
-					vcpu->arch.shregs.msr & 0x58000000);
-		r = RESUME_GUEST;
+		r = kvmppc_book3s_hv_page_fault(run, vcpu,
+				kvmppc_get_pc(vcpu), 0);
 		break;
 	/*
 	 * This occurs if the guest executes an illegal instruction.
@@ -898,6 +898,7 @@ int kvmppc_vcpu_run(struct kvm_run *run, struct kvm_vcpu *vcpu)
 	flush_altivec_to_thread(current);
 	flush_vsx_to_thread(current);
 	vcpu->arch.wqp = &vcpu->arch.vcore->wq;
+	vcpu->arch.pgdir = current->mm->pgd;
 
 	do {
 		r = kvmppc_run_vcpu(run, vcpu);
@@ -1121,9 +1122,9 @@ int kvmppc_core_prepare_memory_region(struct kvm *kvm,
 	unsigned long *phys;
 
 	/* Allocate a slot_phys array */
-	npages = mem->memory_size >> PAGE_SHIFT;
 	phys = kvm->arch.slot_phys[mem->slot];
-	if (!phys) {
+	if (!kvm->arch.using_mmu_notifiers && !phys) {
+		npages = mem->memory_size >> PAGE_SHIFT;
 		phys = vzalloc(npages * sizeof(unsigned long));
 		if (!phys)
 			return -ENOMEM;
@@ -1329,6 +1330,7 @@ int kvmppc_core_init_vm(struct kvm *kvm)
 	}
 	kvm->arch.lpcr = lpcr;
 
+	kvm->arch.using_mmu_notifiers = !!cpu_has_feature(CPU_FTR_ARCH_206);
 	spin_lock_init(&kvm->arch.slot_phys_lock);
 	return 0;
 }
@@ -1337,8 +1339,9 @@ void kvmppc_core_destroy_vm(struct kvm *kvm)
 {
 	unsigned long i;
 
-	for (i = 0; i < KVM_MEMORY_SLOTS + KVM_PRIVATE_MEM_SLOTS; i++)
-		unpin_slot(kvm, i);
+	if (!kvm->arch.using_mmu_notifiers)
+		for (i = 0; i < KVM_MEMORY_SLOTS + KVM_PRIVATE_MEM_SLOTS; i++)
+			unpin_slot(kvm, i);
 
 	if (kvm->arch.rma) {
 		kvm_release_rma(kvm->arch.rma);
diff --git a/arch/powerpc/kvm/book3s_hv_rm_mmu.c b/arch/powerpc/kvm/book3s_hv_rm_mmu.c
index d58a885..6248536 100644
--- a/arch/powerpc/kvm/book3s_hv_rm_mmu.c
+++ b/arch/powerpc/kvm/book3s_hv_rm_mmu.c
@@ -61,7 +61,7 @@ static void *real_vmalloc_addr(void *x)
  * Add this HPTE into the chain for the real page.
  * Must be called with the chain locked; it unlocks the chain.
  */
-static void kvmppc_add_revmap_chain(struct kvm *kvm, struct revmap_entry *rev,
+void kvmppc_add_revmap_chain(struct kvm *kvm, struct revmap_entry *rev,
 			     unsigned long *rmap, long pte_index, int realmode)
 {
 	struct revmap_entry *head, *tail;
@@ -86,6 +86,7 @@ static void kvmppc_add_revmap_chain(struct kvm *kvm, struct revmap_entry *rev,
 	smp_wmb();
 	*rmap = i | KVMPPC_RMAP_REFERENCED | KVMPPC_RMAP_PRESENT; /* unlock */
 }
+EXPORT_SYMBOL_GPL(kvmppc_add_revmap_chain);
 
 /* Remove this HPTE from the chain for a real page */
 static void remove_revmap_chain(struct kvm *kvm, long pte_index,
@@ -121,12 +122,33 @@ static void remove_revmap_chain(struct kvm *kvm, long pte_index,
 	unlock_rmap(rmap);
 }
 
+static pte_t lookup_linux_pte(struct kvm_vcpu *vcpu, unsigned long hva,
+			      unsigned long *pte_sizep)
+{
+	pte_t *ptep;
+	unsigned long ps = *pte_sizep;
+	unsigned int shift;
+
+	ptep = find_linux_pte_or_hugepte(vcpu->arch.pgdir, hva, &shift);
+	if (!ptep)
+		return __pte(0);
+	if (shift)
+		*pte_sizep = 1ul << shift;
+	else
+		*pte_sizep = PAGE_SIZE;
+	if (ps > *pte_sizep)
+		return __pte(0);
+	if (!pte_present(*ptep))
+		return __pte(0);
+	return kvmppc_read_update_linux_pte(ptep);
+}
+
 long kvmppc_h_enter(struct kvm_vcpu *vcpu, unsigned long flags,
 		    long pte_index, unsigned long pteh, unsigned long ptel)
 {
 	struct kvm *kvm = vcpu->kvm;
 	unsigned long i, pa, gpa, gfn, psize;
-	unsigned long slot_fn;
+	unsigned long slot_fn, hva;
 	unsigned long *hpte;
 	struct revmap_entry *rev;
 	unsigned long g_ptel = ptel;
@@ -134,6 +156,8 @@ long kvmppc_h_enter(struct kvm_vcpu *vcpu, unsigned long flags,
 	unsigned long *physp, pte_size;
 	unsigned long is_io;
 	unsigned long *rmap;
+	pte_t pte;
+	unsigned long mmu_seq;
 	bool realmode = vcpu->arch.vcore->vcore_state == VCORE_RUNNING;
 
 	psize = hpte_page_size(pteh, ptel);
@@ -141,11 +165,16 @@ long kvmppc_h_enter(struct kvm_vcpu *vcpu, unsigned long flags,
 		return H_PARAMETER;
 	pteh &= ~(HPTE_V_HVLOCK | HPTE_V_ABSENT | HPTE_V_VALID);
 
+	/* used later to detect if we might have been invalidated */
+	mmu_seq = kvm->mmu_notifier_seq;
+	smp_rmb();
+
 	/* Find the memslot (if any) for this address */
 	gpa = (ptel & HPTE_R_RPN) & ~(psize - 1);
 	gfn = gpa >> PAGE_SHIFT;
 	memslot = builtin_gfn_to_memslot(kvm, gfn);
 	pa = 0;
+	is_io = ~0ul;
 	rmap = NULL;
 	if (!(memslot && !(memslot->flags & KVM_MEMSLOT_INVALID))) {
 		/* PPC970 can't do emulated MMIO */
@@ -163,19 +192,31 @@ long kvmppc_h_enter(struct kvm_vcpu *vcpu, unsigned long flags,
 	slot_fn = gfn - memslot->base_gfn;
 	rmap = &memslot->rmap[slot_fn];
 
-	physp = kvm->arch.slot_phys[memslot->id];
-	if (!physp)
-		return H_PARAMETER;
-	physp += slot_fn;
-	if (realmode)
-		physp = real_vmalloc_addr(physp);
-	pa = *physp;
-	if (!pa)
-		return H_TOO_HARD;
-	is_io = pa & (HPTE_R_I | HPTE_R_W);
-	pte_size = PAGE_SIZE << (pa & KVMPPC_PAGE_ORDER_MASK);
-	pa &= PAGE_MASK;
-
+	if (!kvm->arch.using_mmu_notifiers) {
+		physp = kvm->arch.slot_phys[memslot->id];
+		if (!physp)
+			return H_PARAMETER;
+		physp += slot_fn;
+		if (realmode)
+			physp = real_vmalloc_addr(physp);
+		pa = *physp;
+		if (!pa)
+			return H_TOO_HARD;
+		is_io = pa & (HPTE_R_I | HPTE_R_W);
+		pte_size = PAGE_SIZE << (pa & KVMPPC_PAGE_ORDER_MASK);
+		pa &= PAGE_MASK;
+	} else {
+		/* Translate to host virtual address */
+		hva = gfn_to_hva_memslot(memslot, gfn);
+
+		/* Look up the Linux PTE for the backing page */
+		pte_size = psize;
+		pte = lookup_linux_pte(vcpu, hva, &pte_size);
+		if (pte_present(pte)) {
+			is_io = hpte_cache_bits(pte_val(pte));
+			pa = pte_pfn(pte) << PAGE_SHIFT;
+		}
+	}
 	if (pte_size < psize)
 		return H_PARAMETER;
 	if (pa && pte_size > psize)
@@ -183,12 +224,17 @@ long kvmppc_h_enter(struct kvm_vcpu *vcpu, unsigned long flags,
 
 	ptel &= ~(HPTE_R_PP0 - psize);
 	ptel |= pa;
-	pteh |= HPTE_V_VALID;
+
+	if (pa)
+		pteh |= HPTE_V_VALID;
+	else
+		pteh |= HPTE_V_ABSENT;
 
 	/* Check WIMG */
-	if (!hpte_cache_flags_ok(ptel, is_io))
+	if (is_io != ~0ul && !hpte_cache_flags_ok(ptel, is_io))
 		return H_PARAMETER;
 
+	/* Find and lock the HPTEG slot to use */
  do_insert:
 	if (pte_index >= HPT_NPTE)
 		return H_PARAMETER;
@@ -248,7 +294,17 @@ long kvmppc_h_enter(struct kvm_vcpu *vcpu, unsigned long flags,
 		if (realmode)
 			rmap = real_vmalloc_addr(rmap);
 		lock_rmap(rmap);
-		kvmppc_add_revmap_chain(kvm, rev, rmap, pte_index, realmode);
+		/* Check for pending invalidations under the rmap chain lock */
+		if (kvm->arch.using_mmu_notifiers &&
+		    mmu_notifier_retry(vcpu, mmu_seq)) {
+			/* inval in progress, write a non-present HPTE */
+			pteh |= HPTE_V_ABSENT;
+			pteh &= ~HPTE_V_VALID;
+			unlock_rmap(rmap);
+		} else {
+			kvmppc_add_revmap_chain(kvm, rev, rmap, pte_index,
+						realmode);
+		}
 	}
 
 	hpte[1] = ptel;
@@ -511,6 +567,23 @@ long kvmppc_h_read(struct kvm_vcpu *vcpu, unsigned long flags,
 	return H_SUCCESS;
 }
 
+void kvmppc_invalidate_hpte(struct kvm *kvm, unsigned long *hptep,
+			unsigned long pte_index)
+{
+	unsigned long rb;
+
+	hptep[0] &= ~HPTE_V_VALID;
+	rb = compute_tlbie_rb(hptep[0], hptep[1], pte_index);
+	while (!try_lock_tlbie(&kvm->arch.tlbie_lock))
+		cpu_relax();
+	asm volatile("ptesync" : : : "memory");
+	asm volatile(PPC_TLBIE(%1,%0)"; eieio; tlbsync"
+		     : : "r" (rb), "r" (kvm->arch.lpid));
+	asm volatile("ptesync" : : : "memory");
+	kvm->arch.tlbie_lock = 0;
+}
+EXPORT_SYMBOL_GPL(kvmppc_invalidate_hpte);
+
 static int slb_base_page_shift[4] = {
 	24,	/* 16M */
 	16,	/* 64k */
@@ -600,15 +673,15 @@ EXPORT_SYMBOL(kvmppc_hv_find_lock_hpte);
 
 /*
  * Called in real mode to check whether an HPTE not found fault
- * is due to accessing an emulated MMIO page.
+ * is due to accessing a paged-out page or an emulated MMIO page.
  * Returns a possibly modified status (DSISR) value if not
  * (i.e. pass the interrupt to the guest),
  * -1 to pass the fault up to host kernel mode code, -2 to do that
- * and also load the instruction word,
+ * and also load the instruction word (for MMIO emulation),
  * or 0 if we should make the guest retry the access.
  */
 long kvmppc_hpte_hv_fault(struct kvm_vcpu *vcpu, unsigned long addr,
-			  unsigned long slb_v, unsigned int status)
+			  unsigned long slb_v, unsigned int status, bool data)
 {
 	struct kvm *kvm = vcpu->kvm;
 	long int index;
@@ -619,6 +692,7 @@ long kvmppc_hpte_hv_fault(struct kvm_vcpu *vcpu, unsigned long addr,
 	unsigned long pp, key;
 
 	valid = HPTE_V_VALID | HPTE_V_ABSENT;
+
 	index = kvmppc_hv_find_lock_hpte(kvm, addr, slb_v, valid);
 	if (index < 0)
 		return status;		/* there really was no HPTE */
@@ -640,22 +714,28 @@ long kvmppc_hpte_hv_fault(struct kvm_vcpu *vcpu, unsigned long addr,
 	/* Check access permissions to the page */
 	pp = gr & (HPTE_R_PP0 | HPTE_R_PP);
 	key = (vcpu->arch.shregs.msr & MSR_PR) ? SLB_VSID_KP : SLB_VSID_KS;
-	if (status & DSISR_ISSTORE) {
+	status &= ~DSISR_NOHPTE;	/* DSISR_NOHPTE == SRR1_ISI_NOPT */
+	if (!data) {
+		if (gr & (HPTE_R_N | HPTE_R_G))
+			return status | SRR1_ISI_N_OR_G;
+		if (!hpte_read_permission(pp, slb_v & key))
+			return status | SRR1_ISI_PROT;
+	} else if (status & DSISR_ISSTORE) {
 		/* check write permission */
 		if (!hpte_write_permission(pp, slb_v & key))
-			goto protfault;
+			return status | DSISR_PROTFAULT;
 	} else {
 		if (!hpte_read_permission(pp, slb_v & key))
-			goto protfault;
+			return status | DSISR_PROTFAULT;
 	}
 
 	/* Check storage key, if applicable */
-	if (vcpu->arch.shregs.msr & MSR_DR) {
+	if (data && (vcpu->arch.shregs.msr & MSR_DR)) {
 		unsigned int perm = hpte_get_skey_perm(gr, vcpu->arch.amr);
 		if (status & DSISR_ISSTORE)
 			perm >>= 1;
 		if (perm & 1)
-			return (status & ~DSISR_NOHPTE) | DSISR_KEYFAULT;
+			return status | DSISR_KEYFAULT;
 	}
 
 	/* Save HPTE info for virtual-mode handler */
@@ -664,11 +744,11 @@ long kvmppc_hpte_hv_fault(struct kvm_vcpu *vcpu, unsigned long addr,
 	vcpu->arch.pgfault_hpte[0] = v;
 	vcpu->arch.pgfault_hpte[1] = r;
 
-	if (vcpu->arch.shregs.msr & MSR_IR)
+	/* Check the storage key to see if it is possibly emulated MMIO */
+	if (data && (vcpu->arch.shregs.msr & MSR_IR) &&
+	    (r & (HPTE_R_KEY_HI | HPTE_R_KEY_LO)) ==
+	    (HPTE_R_KEY_HI | HPTE_R_KEY_LO))
 		return -2;	/* MMIO emulation - load instr word */
 
 	return -1;		/* send fault up to host kernel mode */
-
- protfault:
-	return (status & ~DSISR_NOHPTE) | DSISR_PROTFAULT;
 }
diff --git a/arch/powerpc/kvm/book3s_hv_rmhandlers.S b/arch/powerpc/kvm/book3s_hv_rmhandlers.S
index 3a04550..930e09e 100644
--- a/arch/powerpc/kvm/book3s_hv_rmhandlers.S
+++ b/arch/powerpc/kvm/book3s_hv_rmhandlers.S
@@ -618,6 +618,8 @@ BEGIN_FTR_SECTION
 	/* If this is a page table miss then see if it's theirs or ours */
 	cmpwi	r12, BOOK3S_INTERRUPT_H_DATA_STORAGE
 	beq	kvmppc_hdsi
+	cmpwi	r12, BOOK3S_INTERRUPT_H_INST_STORAGE
+	beq	kvmppc_hisi
 END_FTR_SECTION_IFSET(CPU_FTR_ARCH_206)
 
 	/* See if this is a leftover HDEC interrupt */
@@ -1122,6 +1124,7 @@ kvmppc_hdsi:
 
 	/* Search the hash table. */
 	mr	r3, r9			/* vcpu pointer */
+	li	r7, 1			/* data fault */
 	bl	.kvmppc_hpte_hv_fault
 	ld	r9, HSTATE_KVM_VCPU(r13)
 	ld	r10, VCPU_PC(r9)
@@ -1179,6 +1182,52 @@ kvmppc_hdsi:
 	b	nohpte_cont
 
 /*
+ * Similarly for an HISI, reflect it to the guest as an ISI unless
+ * it is an HPTE not found fault for a page that we have paged out.
+ */
+kvmppc_hisi:
+	andis.	r0, r11, SRR1_ISI_NOPT@h
+	beq	1f
+	andi.	r0, r11, MSR_IR		/* instruction relocation enabled? */
+	beq	3f
+	clrrdi	r0, r10, 28
+	PPC_SLBFEE_DOT(r5, r0)		/* if so, look up SLB */
+	bne	1f			/* if no SLB entry found */
+4:
+	/* Search the hash table. */
+	mr	r3, r9			/* vcpu pointer */
+	mr	r4, r10
+	mr	r6, r11
+	li	r7, 0			/* instruction fault */
+	bl	.kvmppc_hpte_hv_fault
+	ld	r9, HSTATE_KVM_VCPU(r13)
+	ld	r10, VCPU_PC(r9)
+	ld	r11, VCPU_MSR(r9)
+	li	r12, BOOK3S_INTERRUPT_H_INST_STORAGE
+	cmpdi	r3, 0			/* retry the instruction */
+	beq	6f
+	cmpdi	r3, -1			/* handle in kernel mode */
+	beq	nohpte_cont
+
+	/* Synthesize an ISI for the guest */
+	mr	r11, r3
+1:	mtspr	SPRN_SRR0, r10
+	mtspr	SPRN_SRR1, r11
+	li	r10, BOOK3S_INTERRUPT_INST_STORAGE
+	li	r11, (MSR_ME << 1) | 1	/* synthesize MSR_SF | MSR_ME */
+	rotldi	r11, r11, 63
+6:	ld	r7, VCPU_CTR(r9)
+	lwz	r8, VCPU_XER(r9)
+	mtctr	r7
+	mtxer	r8
+	mr	r4, r9
+	b	fast_guest_return
+
+3:	ld	r6, VCPU_KVM(r9)	/* not relocated, use VRMA */
+	ld	r5, KVM_VRMA_SLB_V(r6)
+	b	4b
+
+/*
  * Try to handle an hcall in real mode.
  * Returns to the guest if we handle it, or continues on up to
  * the kernel if we can't (i.e. if we don't have a handler for
diff --git a/arch/powerpc/kvm/powerpc.c b/arch/powerpc/kvm/powerpc.c
index 1239c6f..397d454 100644
--- a/arch/powerpc/kvm/powerpc.c
+++ b/arch/powerpc/kvm/powerpc.c
@@ -245,6 +245,9 @@ int kvm_dev_ioctl_check_extension(long ext)
 		if (cpu_has_feature(CPU_FTR_ARCH_201))
 			r = 2;
 		break;
+	case KVM_CAP_SYNC_MMU:
+		r = cpu_has_feature(CPU_FTR_ARCH_206) ? 1 : 0;
+		break;
 #endif
 	default:
 		r = 0;
diff --git a/arch/powerpc/mm/hugetlbpage.c b/arch/powerpc/mm/hugetlbpage.c
index 0b9a5c1..701e920 100644
--- a/arch/powerpc/mm/hugetlbpage.c
+++ b/arch/powerpc/mm/hugetlbpage.c
@@ -11,6 +11,7 @@
 #include <linux/io.h>
 #include <linux/slab.h>
 #include <linux/hugetlb.h>
+#include <linux/module.h>
 #include <asm/pgtable.h>
 #include <asm/pgalloc.h>
 #include <asm/tlb.h>
@@ -105,6 +106,7 @@ pte_t *find_linux_pte_or_hugepte(pgd_t *pgdir, unsigned long ea, unsigned *shift
 		*shift = hugepd_shift(*hpdp);
 	return hugepte_offset(hpdp, ea, pdshift);
 }
+EXPORT_SYMBOL_GPL(find_linux_pte_or_hugepte);
 
 pte_t *huge_pte_offset(struct mm_struct *mm, unsigned long addr)
 {
-- 
1.7.5.4

^ permalink raw reply related

* [PATCH 13/13] KVM: PPC: Allow for read-only pages backing a Book3S HV guest
From: Paul Mackerras @ 2011-12-06  6:14 UTC (permalink / raw)
  To: Alexander Graf; +Cc: linuxppc-dev, kvm, kvm-ppc
In-Reply-To: <20111206060156.GD12389@drongo>

With this, if a guest does an H_ENTER with a read/write HPTE on a page
which is currently read-only, we make the actual HPTE inserted be a
read-only version of the HPTE.  We now intercept protection faults as
well as HPTE not found faults, and for a protection fault we work out
whether it should be reflected to the guest (e.g. because the guest HPTE
didn't allow write access to usermode) or handled by switching to
kernel context and calling kvmppc_book3s_hv_page_fault, which will then
request write access to the page and update the actual HPTE.

Signed-off-by: Paul Mackerras <paulus@samba.org>
---
 arch/powerpc/include/asm/kvm_book3s_64.h |   20 ++++++++++++++++-
 arch/powerpc/kvm/book3s_64_mmu_hv.c      |   33 +++++++++++++++++++++++++++--
 arch/powerpc/kvm/book3s_hv_rm_mmu.c      |   32 ++++++++++++++++++++---------
 arch/powerpc/kvm/book3s_hv_rmhandlers.S  |    4 +-
 4 files changed, 72 insertions(+), 17 deletions(-)

diff --git a/arch/powerpc/include/asm/kvm_book3s_64.h b/arch/powerpc/include/asm/kvm_book3s_64.h
index 75a1b42..37755d0 100644
--- a/arch/powerpc/include/asm/kvm_book3s_64.h
+++ b/arch/powerpc/include/asm/kvm_book3s_64.h
@@ -115,6 +115,22 @@ static inline unsigned long hpte_rpn(unsigned long ptel, unsigned long psize)
 	return ((ptel & HPTE_R_RPN) & ~(psize - 1)) >> PAGE_SHIFT;
 }
 
+static inline int hpte_is_writable(unsigned long ptel)
+{
+	unsigned long pp = ptel & (HPTE_R_PP0 | HPTE_R_PP);
+
+	return pp != PP_RXRX && pp != PP_RXXX;
+}
+
+static inline unsigned long hpte_make_readonly(unsigned long ptel)
+{
+	if ((ptel & HPTE_R_PP0) || (ptel & HPTE_R_PP) == PP_RWXX)
+		ptel = (ptel & ~HPTE_R_PP) | PP_RXXX;
+	else
+		ptel |= PP_RXRX;
+	return ptel;
+}
+
 static inline int hpte_cache_flags_ok(unsigned long ptel, unsigned long io_type)
 {
 	unsigned int wimg = ptel & HPTE_R_WIMG;
@@ -134,7 +150,7 @@ static inline int hpte_cache_flags_ok(unsigned long ptel, unsigned long io_type)
  * Lock and read a linux PTE.  If it's present and writable, atomically
  * set dirty and referenced bits and return the PTE, otherwise return 0.
  */
-static inline pte_t kvmppc_read_update_linux_pte(pte_t *p)
+static inline pte_t kvmppc_read_update_linux_pte(pte_t *p, int writing)
 {
 	pte_t pte, tmp;
 
@@ -152,7 +168,7 @@ static inline pte_t kvmppc_read_update_linux_pte(pte_t *p)
 
 	if (pte_present(pte)) {
 		pte = pte_mkyoung(pte);
-		if (pte_write(pte))
+		if (writing && pte_write(pte))
 			pte = pte_mkdirty(pte);
 	}
 
diff --git a/arch/powerpc/kvm/book3s_64_mmu_hv.c b/arch/powerpc/kvm/book3s_64_mmu_hv.c
index 6919d99..b1b31c7 100644
--- a/arch/powerpc/kvm/book3s_64_mmu_hv.c
+++ b/arch/powerpc/kvm/book3s_64_mmu_hv.c
@@ -502,6 +502,7 @@ int kvmppc_book3s_hv_page_fault(struct kvm_run *run, struct kvm_vcpu *vcpu,
 	struct page *page, *pages[1];
 	long index, ret, npages;
 	unsigned long is_io;
+	unsigned int writing, write_ok;
 	struct vm_area_struct *vma;
 
 	/*
@@ -552,8 +553,11 @@ int kvmppc_book3s_hv_page_fault(struct kvm_run *run, struct kvm_vcpu *vcpu,
 	pfn = 0;
 	page = NULL;
 	pte_size = PAGE_SIZE;
+	writing = (dsisr & DSISR_ISSTORE) != 0;
+	/* If writing != 0, then the HPTE must allow writing, if we get here */
+	write_ok = writing;
 	hva = gfn_to_hva_memslot(memslot, gfn);
-	npages = get_user_pages_fast(hva, 1, 1, pages);
+	npages = get_user_pages_fast(hva, 1, writing, pages);
 	if (npages < 1) {
 		/* Check if it's an I/O mapping */
 		down_read(&current->mm->mmap_sem);
@@ -564,6 +568,7 @@ int kvmppc_book3s_hv_page_fault(struct kvm_run *run, struct kvm_vcpu *vcpu,
 				((hva - vma->vm_start) >> PAGE_SHIFT);
 			pte_size = psize;
 			is_io = hpte_cache_bits(pgprot_val(vma->vm_page_prot));
+			write_ok = vma->vm_flags & VM_WRITE;
 		}
 		up_read(&current->mm->mmap_sem);
 		if (!pfn)
@@ -574,6 +579,18 @@ int kvmppc_book3s_hv_page_fault(struct kvm_run *run, struct kvm_vcpu *vcpu,
 			page = compound_head(page);
 			pte_size <<= compound_order(page);
 		}
+		/* if the guest wants write access, see if that is OK */
+		if (!writing && hpte_is_writable(hpte[2])) {
+			pte_t *ptep, pte;
+
+			ptep = find_linux_pte_or_hugepte(current->mm->pgd,
+							 hva, NULL);
+			if (ptep && pte_present(*ptep)) {
+				pte = kvmppc_read_update_linux_pte(ptep, 1);
+				if (pte_write(pte))
+					write_ok = 1;
+			}
+		}
 		pfn = page_to_pfn(page);
 	}
 
@@ -598,6 +615,8 @@ int kvmppc_book3s_hv_page_fault(struct kvm_run *run, struct kvm_vcpu *vcpu,
 	hpte[0] = (hpte[0] & ~HPTE_V_ABSENT) | HPTE_V_VALID;
 	hpte[1] = (rev->guest_rpte & ~(HPTE_R_PP0 - pte_size)) |
 		(pfn << PAGE_SHIFT);
+	if (hpte_is_writable(hpte[1]) && !write_ok)
+		hpte[1] = hpte_make_readonly(hpte[1]);
 
 	rmap = &memslot->rmap[gfn - memslot->base_gfn];
 	lock_rmap(rmap);
@@ -609,13 +628,21 @@ int kvmppc_book3s_hv_page_fault(struct kvm_run *run, struct kvm_vcpu *vcpu,
 		hptep[0] &= ~HPTE_V_HVLOCK;
 		goto out_put;
 	}
-	kvmppc_add_revmap_chain(kvm, rev, rmap, index, 0);
+
+	if (hptep[0] & HPTE_V_VALID) {
+		/* HPTE was previously valid, so we need to invalidate it */
+		unlock_rmap(rmap);
+		hptep[0] |= HPTE_V_ABSENT;
+		kvmppc_invalidate_hpte(kvm, hptep, index);
+	} else {
+		kvmppc_add_revmap_chain(kvm, rev, rmap, index, 0);
+	}
 
 	hptep[1] = hpte[1];
 	eieio();
 	hptep[0] = hpte[0];
 	asm volatile("ptesync" : : : "memory");
-	if (page)
+	if (page && hpte_is_writable(hpte[1]))
 		SetPageDirty(page);
 
  out_put:
diff --git a/arch/powerpc/kvm/book3s_hv_rm_mmu.c b/arch/powerpc/kvm/book3s_hv_rm_mmu.c
index 6248536..2fded8a 100644
--- a/arch/powerpc/kvm/book3s_hv_rm_mmu.c
+++ b/arch/powerpc/kvm/book3s_hv_rm_mmu.c
@@ -123,7 +123,7 @@ static void remove_revmap_chain(struct kvm *kvm, long pte_index,
 }
 
 static pte_t lookup_linux_pte(struct kvm_vcpu *vcpu, unsigned long hva,
-			      unsigned long *pte_sizep)
+			      int writing, unsigned long *pte_sizep)
 {
 	pte_t *ptep;
 	unsigned long ps = *pte_sizep;
@@ -140,7 +140,7 @@ static pte_t lookup_linux_pte(struct kvm_vcpu *vcpu, unsigned long hva,
 		return __pte(0);
 	if (!pte_present(*ptep))
 		return __pte(0);
-	return kvmppc_read_update_linux_pte(ptep);
+	return kvmppc_read_update_linux_pte(ptep, writing);
 }
 
 long kvmppc_h_enter(struct kvm_vcpu *vcpu, unsigned long flags,
@@ -157,12 +157,14 @@ long kvmppc_h_enter(struct kvm_vcpu *vcpu, unsigned long flags,
 	unsigned long is_io;
 	unsigned long *rmap;
 	pte_t pte;
+	unsigned int writing;
 	unsigned long mmu_seq;
 	bool realmode = vcpu->arch.vcore->vcore_state == VCORE_RUNNING;
 
 	psize = hpte_page_size(pteh, ptel);
 	if (!psize)
 		return H_PARAMETER;
+	writing = hpte_is_writable(ptel);
 	pteh &= ~(HPTE_V_HVLOCK | HPTE_V_ABSENT | HPTE_V_VALID);
 
 	/* used later to detect if we might have been invalidated */
@@ -211,8 +213,11 @@ long kvmppc_h_enter(struct kvm_vcpu *vcpu, unsigned long flags,
 
 		/* Look up the Linux PTE for the backing page */
 		pte_size = psize;
-		pte = lookup_linux_pte(vcpu, hva, &pte_size);
+		pte = lookup_linux_pte(vcpu, hva, writing, &pte_size);
 		if (pte_present(pte)) {
+			if (writing && !pte_write(pte))
+				/* make the actual HPTE be read-only */
+				ptel = hpte_make_readonly(ptel);
 			is_io = hpte_cache_bits(pte_val(pte));
 			pa = pte_pfn(pte) << PAGE_SHIFT;
 		}
@@ -673,7 +678,9 @@ EXPORT_SYMBOL(kvmppc_hv_find_lock_hpte);
 
 /*
  * Called in real mode to check whether an HPTE not found fault
- * is due to accessing a paged-out page or an emulated MMIO page.
+ * is due to accessing a paged-out page or an emulated MMIO page,
+ * or if a protection fault is due to accessing a page that the
+ * guest wanted read/write access to but which we made read-only.
  * Returns a possibly modified status (DSISR) value if not
  * (i.e. pass the interrupt to the guest),
  * -1 to pass the fault up to host kernel mode code, -2 to do that
@@ -691,12 +698,17 @@ long kvmppc_hpte_hv_fault(struct kvm_vcpu *vcpu, unsigned long addr,
 	struct revmap_entry *rev;
 	unsigned long pp, key;
 
-	valid = HPTE_V_VALID | HPTE_V_ABSENT;
+	/* For protection fault, expect to find a valid HPTE */
+	valid = HPTE_V_VALID;
+	if (status & DSISR_NOHPTE)
+		valid |= HPTE_V_ABSENT;
 
 	index = kvmppc_hv_find_lock_hpte(kvm, addr, slb_v, valid);
-	if (index < 0)
-		return status;		/* there really was no HPTE */
-
+	if (index < 0) {
+		if (status & DSISR_NOHPTE)
+			return status;	/* there really was no HPTE */
+		return 0;		/* for prot fault, HPTE disappeared */
+	}
 	hpte = (unsigned long *)(kvm->arch.hpt_virt + (index << 4));
 	v = hpte[0] & ~HPTE_V_HVLOCK;
 	r = hpte[1];
@@ -707,8 +719,8 @@ long kvmppc_hpte_hv_fault(struct kvm_vcpu *vcpu, unsigned long addr,
 	asm volatile("lwsync" : : : "memory");
 	hpte[0] = v;
 
-	/* If the HPTE is valid by now, retry the instruction */
-	if (v & HPTE_V_VALID)
+	/* For not found, if the HPTE is valid by now, retry the instruction */
+	if ((status & DSISR_NOHPTE) && (v & HPTE_V_VALID))
 		return 0;
 
 	/* Check access permissions to the page */
diff --git a/arch/powerpc/kvm/book3s_hv_rmhandlers.S b/arch/powerpc/kvm/book3s_hv_rmhandlers.S
index 930e09e..7b8dbf6 100644
--- a/arch/powerpc/kvm/book3s_hv_rmhandlers.S
+++ b/arch/powerpc/kvm/book3s_hv_rmhandlers.S
@@ -1111,8 +1111,8 @@ END_FTR_SECTION_IFSET(CPU_FTR_ARCH_201)
 kvmppc_hdsi:
 	mfspr	r4, SPRN_HDAR
 	mfspr	r6, SPRN_HDSISR
-	/* HPTE not found fault? */
-	andis.	r0, r6, DSISR_NOHPTE@h
+	/* HPTE not found fault or protection fault? */
+	andis.	r0, r6, (DSISR_NOHPTE | DSISR_PROTFAULT)@h
 	beq	1f			/* if not, send it to the guest */
 	andi.	r0, r11, MSR_DR		/* data relocation enabled? */
 	beq	3f
-- 
1.7.5.4

^ permalink raw reply related

* [PATCH 1/2 v2] mtd/nand: fixup for fmr initialization of Freescale NAND controller
From: Shengzhou Liu @ 2011-12-06  8:54 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: scottwood, dwmw2, kumar.gala, linux-mtd, Shengzhou Liu

There was a bug for fmr initialization, which lead to  fmr was always 0x100
in fsl_elbc_chip_init() and caused FCM command timeout before calling
fsl_elbc_chip_init_tail(), now we initialize CWTO to maximum timeout value
and not relying on the setting of bootloader.

Signed-off-by: Shengzhou Liu <Shengzhou.Liu@freescale.com>
---
v2: make fmr not relying on the setting of bootloader.

 drivers/mtd/nand/fsl_elbc_nand.c |   10 +++++-----
 1 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/drivers/mtd/nand/fsl_elbc_nand.c b/drivers/mtd/nand/fsl_elbc_nand.c
index eedd8ee..4f405a0 100644
--- a/drivers/mtd/nand/fsl_elbc_nand.c
+++ b/drivers/mtd/nand/fsl_elbc_nand.c
@@ -659,9 +659,7 @@ static int fsl_elbc_chip_init_tail(struct mtd_info *mtd)
 	if (chip->pagemask & 0xff000000)
 		al++;
 
-	/* add to ECCM mode set in fsl_elbc_init */
-	priv->fmr |= (12 << FMR_CWTO_SHIFT) |  /* Timeout > 12 ms */
-	             (al << FMR_AL_SHIFT);
+	priv->fmr |= al << FMR_AL_SHIFT;
 
 	dev_dbg(priv->dev, "fsl_elbc_init: nand->numchips = %d\n",
 	        chip->numchips);
@@ -764,8 +762,10 @@ static int fsl_elbc_chip_init(struct fsl_elbc_mtd *priv)
 	priv->mtd.priv = chip;
 	priv->mtd.owner = THIS_MODULE;
 
-	/* Set the ECCM according to the settings in bootloader.*/
-	priv->fmr = in_be32(&lbc->fmr) & FMR_ECCM;
+	/* set timeout to maximum */
+	priv->fmr = 15 << FMR_CWTO_SHIFT;
+	if (in_be32(&lbc->bank[priv->bank].or) & OR_FCM_PGS)
+		priv->fmr |= FMR_ECCM;
 
 	/* fill in nand_chip structure */
 	/* set up function call table */
-- 
1.6.4

^ permalink raw reply related

* [PATCH 2/2 v2] mtd/nand: Add ONFI support for FSL NAND controller
From: Shengzhou Liu @ 2011-12-06  8:54 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: scottwood, dwmw2, kumar.gala, linux-mtd, Shengzhou Liu
In-Reply-To: <1323161655-19050-1-git-send-email-Shengzhou.Liu@freescale.com>

- fix NAND_CMD_READID command for ONFI detect.
- add NAND_CMD_PARAM command to read the ONFI parameter page.

Signed-off-by: Shengzhou Liu <Shengzhou.Liu@freescale.com>
---
v2: no changes

 drivers/mtd/nand/fsl_elbc_nand.c |   19 ++++++++++++-------
 1 files changed, 12 insertions(+), 7 deletions(-)

diff --git a/drivers/mtd/nand/fsl_elbc_nand.c b/drivers/mtd/nand/fsl_elbc_nand.c
index 4f405a0..b4db407 100644
--- a/drivers/mtd/nand/fsl_elbc_nand.c
+++ b/drivers/mtd/nand/fsl_elbc_nand.c
@@ -349,19 +349,24 @@ static void fsl_elbc_cmdfunc(struct mtd_info *mtd, unsigned int command,
 		fsl_elbc_run_command(mtd);
 		return;
 
-	/* READID must read all 5 possible bytes while CEB is active */
 	case NAND_CMD_READID:
-		dev_vdbg(priv->dev, "fsl_elbc_cmdfunc: NAND_CMD_READID.\n");
+	case NAND_CMD_PARAM:
+		dev_vdbg(priv->dev, "fsl_elbc_cmdfunc: NAND_CMD %x\n", command);
 
 		out_be32(&lbc->fir, (FIR_OP_CM0 << FIR_OP0_SHIFT) |
 		                    (FIR_OP_UA  << FIR_OP1_SHIFT) |
 		                    (FIR_OP_RBW << FIR_OP2_SHIFT));
-		out_be32(&lbc->fcr, NAND_CMD_READID << FCR_CMD0_SHIFT);
-		/* nand_get_flash_type() reads 8 bytes of entire ID string */
-		out_be32(&lbc->fbcr, 8);
-		elbc_fcm_ctrl->read_bytes = 8;
+		out_be32(&lbc->fcr, command << FCR_CMD0_SHIFT);
+		/* reads 8 bytes of entire ID string */
+		if (NAND_CMD_READID == command) {
+			out_be32(&lbc->fbcr, 8);
+			elbc_fcm_ctrl->read_bytes = 8;
+		} else {
+			out_be32(&lbc->fbcr, 256);
+			elbc_fcm_ctrl->read_bytes = 256;
+		}
 		elbc_fcm_ctrl->use_mdr = 1;
-		elbc_fcm_ctrl->mdr = 0;
+		elbc_fcm_ctrl->mdr = column;
 
 		set_addr(mtd, 0, 0, 0);
 		fsl_elbc_run_command(mtd);
-- 
1.6.4

^ permalink raw reply related

* Re: Problem with eLBC?
From: Joakim Tjernlund @ 2011-12-06  9:30 UTC (permalink / raw)
  To: Scott Wood; +Cc: Alexander Lyasin, linuxppc-dev
In-Reply-To: <4EDD32E1.7080009@freescale.com>

>
> On 12/05/2011 08:02 AM, Alexander Lyasin wrote:
> > In reply to your Service Request SR 1-807899446:
> >
> > Yes, due to several design peculiarities in local bus nand controller,
> > simultaneous accesses to nand flash and to other local bus memory
> > controller may cause nand flash controller access failure. Our linux
> > team suggested to use "software lock" method to avoid this problem -
> > please do not use other local bus controllers, when nand flash is accessed.
>
> What kernel version are you using?  The latest mainline kernel should
> not have this issue.
>
> Make sure you have these patches:
>
> commit d08e44570ed611c527a1062eb4f8c6ac61832e6e
> Author: Shengzhou Liu <Shengzhou.Liu@freescale.com>
> Date:   Thu May 19 18:48:01 2011 +0800
>
>     powerpc/fsl_lbc: Add workaround for ELBC-A001 erratum
>
>     Simultaneous FCM and GPCM or UPM operation may erroneously trigger
>     bus monitor timeout.
>
>     Set the local bus monitor timeout value to the maximum by setting
>     LBCR[BMT] = 0 and LBCR[BMTPS] = 0xF.
>
>     Signed-off-by: Shengzhou Liu <Shengzhou.Liu@freescale.com>
>     Signed-off-by: Kumar Gala <galak@kernel.crashing.org>
>
> and
>
> commit 476459a6cf46d20ec73d9b211f3894ced5f9871e
> Author: Scott Wood <scottwood@freescale.com>
> Date:   Fri Nov 13 14:13:01 2009 -0600
>
>     mtd: eLBC NAND: use recommended command sequences
>
>     Currently, the program and erase sequences do not wait for completion,
>     instead relying on a subsequent waitfunc() callback.  However, this
> causes
>     the chipselect to be deasserted while the NAND chip is still
> asserting the
>     busy pin, which can corrupt activity on other chipselects.
>
>     This patch switches to using the sequences recommended by the manual,
>     in which a wait is performed within the initial command sequence.
> We can
>     now re-use the status byte from the initial command sequence, rather
> than
>     having to do another status read in the waitfunc.
>
>     Since we're already touching the command sequences, it also cleans
> up some
>     cruft in SEQIN that isn't needed since we cannot program partial pages
>     outside of OOB.
>
>     Signed-off-by: Scott Wood <scottwood@freescale.com>
>     Reported-by: Suchit Lepcha <suchit.lepcha@freescale.com>
>     Signed-off-by: Artem Bityutskiy <Artem.Bityutskiy@nokia.com>
>     Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
>
> -Scott

Scott, you seem know something about eLBC and NAND. I have been told
that using NAND and other memory mapped devices on the same LB may
stall accesses to the other devices as the FCM may hold the bus for
long periods(a whole write or erase op.), is this so?

If still true, I guess the whole CPU "freezes" until the NAND op.
is complete?

 Jocke

^ permalink raw reply

* Re: "KVM: PPC: booke: Improve timer register emulation" breaks Book3s HV
From: Paul Mackerras @ 2011-12-06 11:43 UTC (permalink / raw)
  To: Alexander Graf, Scott Wood; +Cc: linuxppc-dev, kvm-ppc
In-Reply-To: <20111206040300.GA12018@drongo>

On Tue, Dec 06, 2011 at 03:03:00PM +1100, Paul Mackerras wrote:
> I'm not sure why yet, but commit 8a97c432 ("KVM: PPC: booke: Improve
> timer register emulation") in Alex's kvm-ppc-next branch is breaking
> Book3S HV KVM on POWER7.  Guest cpus fail to spin up, and even with
> just one cpu, the guest stalls every so often.  If I stop the guest
> and inspect the state with qemu, PC is at 0x900.  Reverting 8a97c432
> makes it work properly again.

This fixes it:

diff --git a/arch/powerpc/kvm/powerpc.c b/arch/powerpc/kvm/powerpc.c
index 534cbe1..83bcb44 100644
--- a/arch/powerpc/kvm/powerpc.c
+++ b/arch/powerpc/kvm/powerpc.c
@@ -560,7 +560,7 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *run)
 
 void kvm_vcpu_kick(struct kvm_vcpu *vcpu)
 {
-	if (waitqueue_active(&vcpu->wq)) {
+	if (waitqueue_active(vcpu->arch.wqp)) {
 		wake_up_interruptible(vcpu->arch.wqp);
 		vcpu->stat.halt_wakeup++;
 	} else if (vcpu->cpu != -1) {

Alex, do you want to roll that in with Scott's patch, or do you want me
to send a separate patch on top?

Paul.

^ permalink raw reply related

* Re: "KVM: PPC: booke: Improve timer register emulation" breaks Book3s HV
From: Alexander Graf @ 2011-12-06 11:46 UTC (permalink / raw)
  To: Paul Mackerras; +Cc: Scott Wood, linuxppc-dev, kvm-ppc
In-Reply-To: <20111206114347.GA14832@bloggs.ozlabs.ibm.com>


On 06.12.2011, at 12:43, Paul Mackerras wrote:

> On Tue, Dec 06, 2011 at 03:03:00PM +1100, Paul Mackerras wrote:
>> I'm not sure why yet, but commit 8a97c432 ("KVM: PPC: booke: Improve
>> timer register emulation") in Alex's kvm-ppc-next branch is breaking
>> Book3S HV KVM on POWER7.  Guest cpus fail to spin up, and even with
>> just one cpu, the guest stalls every so often.  If I stop the guest
>> and inspect the state with qemu, PC is at 0x900.  Reverting 8a97c432
>> makes it work properly again.
>=20
> This fixes it:
>=20
> diff --git a/arch/powerpc/kvm/powerpc.c b/arch/powerpc/kvm/powerpc.c
> index 534cbe1..83bcb44 100644
> --- a/arch/powerpc/kvm/powerpc.c
> +++ b/arch/powerpc/kvm/powerpc.c
> @@ -560,7 +560,7 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu, =
struct kvm_run *run)
>=20
> void kvm_vcpu_kick(struct kvm_vcpu *vcpu)
> {
> -	if (waitqueue_active(&vcpu->wq)) {
> +	if (waitqueue_active(vcpu->arch.wqp)) {

:(

> 		wake_up_interruptible(vcpu->arch.wqp);
> 		vcpu->stat.halt_wakeup++;
> 	} else if (vcpu->cpu !=3D -1) {
>=20
> Alex, do you want to roll that in with Scott's patch, or do you want =
me
> to send a separate patch on top?

I usually like praise where praise belongs, so I'll put this right after =
Scott's patch if you give me a nice and shiny patch description with a =
signed-off-by line :)


Alex

^ permalink raw reply

* Re: [PATCH 3/3] mtd/nand : workaround for Freescale FCM to support large-page Nand chip
From: Artem Bityutskiy @ 2011-12-06 11:49 UTC (permalink / raw)
  To: shuo.liu
  Cc: Artem.Bityutskiy, linuxppc-dev, linux-kernel, linux-mtd,
	scottwood, akpm, dwmw2
In-Reply-To: <1322973098-2528-3-git-send-email-shuo.liu@freescale.com>

On Sun, 2011-12-04 at 12:31 +0800, shuo.liu@freescale.com wrote:
> From: Liu Shuo <shuo.liu@freescale.com>
> 
> Freescale FCM controller has a 2K size limitation of buffer RAM. In order
> to support the Nand flash chip whose page size is larger than 2K bytes,
> we read/write 2k data repeatedly by issuing FIR_OP_RB/FIR_OP_WB and save
> them to a large buffer.
> 
> Signed-off-by: Liu Shuo <shuo.liu@freescale.com>

This patch does not apply on top of my l2-mtd-2.6.git tree. Could you
please send a patch that applies cleanly?

Thanks!

^ permalink raw reply

* Re: [PATCH 3/3] mtd/nand : workaround for Freescale FCM to support large-page Nand chip
From: Artem Bityutskiy @ 2011-12-06 11:49 UTC (permalink / raw)
  To: Scott Wood
  Cc: Artem.Bityutskiy, dwmw2, linux-kernel, shuo.liu, linux-mtd, akpm,
	linuxppc-dev
In-Reply-To: <4EDD1F90.300@freescale.com>

On Mon, 2011-12-05 at 13:46 -0600, Scott Wood wrote:
> Because this is a controller resource, shared by multiple NAND chips
> that may be different page sizes (even if not, it's adding another point
> of synchronization required between initialization of different chips).
>  I don't think it's worth the gymnastics to save a few KiB.

OK, I see.

Artem.

^ permalink raw reply

* [PATCH 01/16 v2] pmac_zilog: fix unexpected irq
From: Finn Thain @ 2011-12-06 15:13 UTC (permalink / raw)
  To: Geert Uytterhoeven; +Cc: linux-m68k, linuxppc-dev, linux-serial
In-Reply-To: <20111023141115.208699274@telegraphics.com.au>


On most 68k Macs the SCC IRQ is an autovector interrupt and cannot be 
masked. This can be a problem when pmac_zilog starts up.

For example, the serial debugging code in arch/m68k/kernel/head.S may be 
used beforehand. It disables the SCC interrupts at the chip but doesn't 
ack them. Then when a pmac_zilog port is opened and SCC chip interrupts 
become enabled, the machine locks up with "unexpected interrupt" because 
request_irq() hasn't happened yet.

Fix this by setting the interrupt enable bits only after the handler is 
installed and before it is uninstalled. Also move this bit flipping into a 
separate pmz_interrupt_control() routine. Replace all instances of these 
operations with calls to this routine.

Signed-off-by: Finn Thain <fthain@telegraphics.com.au>

---

Re-implemented since v1 using a simpler approach that avoids messing with 
the Master Interrupt Enable bit. As well as the ifdef problem, it turns 
out that v1 was not sufficient to entirely fix the problem.

This patch has been tested on a PowerBook 520 but no PowerMacs yet.

Index: linux-git/drivers/tty/serial/pmac_zilog.c
===================================================================
--- linux-git.orig/drivers/tty/serial/pmac_zilog.c	2011-12-07 01:56:43.000000000 +1100
+++ linux-git/drivers/tty/serial/pmac_zilog.c	2011-12-07 01:56:55.000000000 +1100
@@ -216,6 +216,18 @@ static void pmz_maybe_update_regs(struct
 	}
 }
 
+static void pmz_interrupt_control(struct uart_pmac_port *uap, int enable)
+{
+	if (enable) {
+		uap->curregs[1] |= INT_ALL_Rx | TxINT_ENAB;
+		if (!ZS_IS_EXTCLK(uap))
+			uap->curregs[1] |= EXT_INT_ENAB;
+	} else {
+		uap->curregs[1] &= ~(EXT_INT_ENAB | TxINT_ENAB | RxINT_MASK);
+	}
+	write_zsreg(uap, R1, uap->curregs[1]);
+}
+
 static struct tty_struct *pmz_receive_chars(struct uart_pmac_port *uap)
 {
 	struct tty_struct *tty = NULL;
@@ -339,9 +351,7 @@ static struct tty_struct *pmz_receive_ch
 
 	return tty;
  flood:
-	uap->curregs[R1] &= ~(EXT_INT_ENAB | TxINT_ENAB | RxINT_MASK);
-	write_zsreg(uap, R1, uap->curregs[R1]);
-	zssync(uap);
+	pmz_interrupt_control(uap, 0);
 	pmz_error("pmz: rx irq flood !\n");
 	return tty;
 }
@@ -990,12 +1000,9 @@ static int pmz_startup(struct uart_port
 	if (ZS_IS_IRDA(uap))
 		pmz_irda_reset(uap);
 
-	/* Enable interrupts emission from the chip */
+	/* Enable interrupt requests for the channel */
 	spin_lock_irqsave(&port->lock, flags);
-	uap->curregs[R1] |= INT_ALL_Rx | TxINT_ENAB;
-	if (!ZS_IS_EXTCLK(uap))
-		uap->curregs[R1] |= EXT_INT_ENAB;
-	write_zsreg(uap, R1, uap->curregs[R1]);
+	pmz_interrupt_control(uap, 1);
 	spin_unlock_irqrestore(&port->lock, flags);
 
 	pmz_debug("pmz: startup() done.\n");
@@ -1015,6 +1022,25 @@ static void pmz_shutdown(struct uart_por
 
 	mutex_lock(&pmz_irq_mutex);
 
+	if (!ZS_IS_ASLEEP(uap)) {
+		spin_lock_irqsave(&port->lock, flags);
+
+		if (!ZS_IS_CONS(uap)) {
+			/* Disable receiver and transmitter */
+			uap->curregs[R3] &= ~RxENABLE;
+			uap->curregs[R5] &= ~TxENABLE;
+
+			/* Disable BRK assertion */
+			uap->curregs[R5] &= ~SND_BRK;
+			pmz_maybe_update_regs(uap);
+		}
+
+		/* Disable interrupt requests for the channel */
+		pmz_interrupt_control(uap, 0);
+
+		spin_unlock_irqrestore(&port->lock, flags);
+	}
+
 	/* Release interrupt handler */
 	free_irq(uap->port.irq, uap);
 
@@ -1025,29 +1051,8 @@ static void pmz_shutdown(struct uart_por
 	if (!ZS_IS_OPEN(uap->mate))
 		pmz_get_port_A(uap)->flags &= ~PMACZILOG_FLAG_IS_IRQ_ON;
 
-	/* Disable interrupts */
-	if (!ZS_IS_ASLEEP(uap)) {
-		uap->curregs[R1] &= ~(EXT_INT_ENAB | TxINT_ENAB | RxINT_MASK);
-		write_zsreg(uap, R1, uap->curregs[R1]);
-		zssync(uap);
-	}
-
-	if (ZS_IS_CONS(uap) || ZS_IS_ASLEEP(uap)) {
-		spin_unlock_irqrestore(&port->lock, flags);
-		mutex_unlock(&pmz_irq_mutex);
-		return;
-	}
-
-	/* Disable receiver and transmitter.  */
-	uap->curregs[R3] &= ~RxENABLE;
-	uap->curregs[R5] &= ~TxENABLE;
-
-	/* Disable all interrupts and BRK assertion.  */
-	uap->curregs[R5] &= ~SND_BRK;
-	pmz_maybe_update_regs(uap);
-
-	/* Shut the chip down */
-	pmz_set_scc_power(uap, 0);
+	if (!ZS_IS_ASLEEP(uap) && !ZS_IS_CONS(uap))
+		pmz_set_scc_power(uap, 0);	/* Shut the chip down */
 
 	spin_unlock_irqrestore(&port->lock, flags);
 
@@ -1352,19 +1357,15 @@ static void pmz_set_termios(struct uart_
 	spin_lock_irqsave(&port->lock, flags);	
 
 	/* Disable IRQs on the port */
-	uap->curregs[R1] &= ~(EXT_INT_ENAB | TxINT_ENAB | RxINT_MASK);
-	write_zsreg(uap, R1, uap->curregs[R1]);
+	pmz_interrupt_control(uap, 0);
 
 	/* Setup new port configuration */
 	__pmz_set_termios(port, termios, old);
 
 	/* Re-enable IRQs on the port */
-	if (ZS_IS_OPEN(uap)) {
-		uap->curregs[R1] |= INT_ALL_Rx | TxINT_ENAB;
-		if (!ZS_IS_EXTCLK(uap))
-			uap->curregs[R1] |= EXT_INT_ENAB;
-		write_zsreg(uap, R1, uap->curregs[R1]);
-	}
+	if (ZS_IS_OPEN(uap))
+		pmz_interrupt_control(uap, 1);
+
 	spin_unlock_irqrestore(&port->lock, flags);
 }
 
@@ -1670,15 +1671,13 @@ static int pmz_suspend(struct macio_dev
 
 	spin_lock_irqsave(&uap->port.lock, flags);
 
+	/* Disable receiver and transmitter.  */
+	uap->curregs[R3] &= ~RxENABLE;
+	uap->curregs[R5] &= ~TxENABLE;
+
+	pmz_interrupt_control(uap, 0);
+
 	if (ZS_IS_OPEN(uap) || ZS_IS_CONS(uap)) {
-		/* Disable receiver and transmitter.  */
-		uap->curregs[R3] &= ~RxENABLE;
-		uap->curregs[R5] &= ~TxENABLE;
-
-		/* Disable all interrupts and BRK assertion.  */
-		uap->curregs[R1] &= ~(EXT_INT_ENAB | TxINT_ENAB | RxINT_MASK);
-		uap->curregs[R5] &= ~SND_BRK;
-		pmz_load_zsregs(uap, uap->curregs);
 		uap->flags |= PMACZILOG_FLAG_IS_ASLEEP;
 		mb();
 	}
@@ -1738,14 +1737,6 @@ static int pmz_resume(struct macio_dev *
 	/* Take care of config that may have changed while asleep */
 	__pmz_set_termios(&uap->port, &uap->termios_cache, NULL);
 
-	if (ZS_IS_OPEN(uap)) {
-		/* Enable interrupts */		
-		uap->curregs[R1] |= INT_ALL_Rx | TxINT_ENAB;
-		if (!ZS_IS_EXTCLK(uap))
-			uap->curregs[R1] |= EXT_INT_ENAB;
-		write_zsreg(uap, R1, uap->curregs[R1]);
-	}
-
 	spin_unlock_irqrestore(&uap->port.lock, flags);
 
 	if (ZS_IS_CONS(uap))
@@ -1757,6 +1748,12 @@ static int pmz_resume(struct macio_dev *
 		enable_irq(uap->port.irq);
 	}
 
+	if (ZS_IS_OPEN(uap)) {
+		spin_lock_irqsave(&uap->port.lock, flags);
+		pmz_interrupt_control(uap, 1);
+		spin_unlock_irqrestore(&uap->port.lock, flags);
+	}
+
  bail:
 	mutex_unlock(&state->port.mutex);
 	mutex_unlock(&pmz_irq_mutex);

^ permalink raw reply

* Re: [PATCH 01/16 v2] pmac_zilog: fix unexpected irq
From: Geert Uytterhoeven @ 2011-12-06 15:27 UTC (permalink / raw)
  To: Finn Thain; +Cc: linux-m68k, linuxppc-dev, linux-serial
In-Reply-To: <alpine.LNX.2.00.1112070203310.14968@nippy.intranet>

Hi Finn,

On Tue, Dec 6, 2011 at 16:13, Finn Thain <fthain@telegraphics.com.au> wrote=
:
> +static void pmz_interrupt_control(struct uart_pmac_port *uap, int enable=
)
> +{
> + =C2=A0 =C2=A0 =C2=A0 if (enable) {
> + =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 uap->curregs[1] |=3D I=
NT_ALL_Rx | TxINT_ENAB;
> + =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 if (!ZS_IS_EXTCLK(uap)=
)
> + =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =
=C2=A0 uap->curregs[1] |=3D EXT_INT_ENAB;
> + =C2=A0 =C2=A0 =C2=A0 } else {
> + =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 uap->curregs[1] &=3D ~=
(EXT_INT_ENAB | TxINT_ENAB | RxINT_MASK);

Should there be a call to zssync() here?
The old code always did that after disabling interrupts.

> + =C2=A0 =C2=A0 =C2=A0 }
> + =C2=A0 =C2=A0 =C2=A0 write_zsreg(uap, R1, uap->curregs[1]);
> +}
> +
> =C2=A0static struct tty_struct *pmz_receive_chars(struct uart_pmac_port *=
uap)
> =C2=A0{
> =C2=A0 =C2=A0 =C2=A0 =C2=A0struct tty_struct *tty =3D NULL;
> @@ -339,9 +351,7 @@ static struct tty_struct *pmz_receive_ch
>
> =C2=A0 =C2=A0 =C2=A0 =C2=A0return tty;
> =C2=A0flood:
> - =C2=A0 =C2=A0 =C2=A0 uap->curregs[R1] &=3D ~(EXT_INT_ENAB | TxINT_ENAB =
| RxINT_MASK);
> - =C2=A0 =C2=A0 =C2=A0 write_zsreg(uap, R1, uap->curregs[R1]);
> - =C2=A0 =C2=A0 =C2=A0 zssync(uap);

Cfr. e.g. here.

> + =C2=A0 =C2=A0 =C2=A0 pmz_interrupt_control(uap, 0);
> =C2=A0 =C2=A0 =C2=A0 =C2=A0pmz_error("pmz: rx irq flood !\n");
> =C2=A0 =C2=A0 =C2=A0 =C2=A0return tty;
> =C2=A0}

Gr{oetje,eeting}s,

=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 Geert

--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k=
.org

In personal conversations with technical people, I call myself a hacker. Bu=
t
when I'm talking to journalists I just say "programmer" or something like t=
hat.
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 =C2=A0 =C2=A0=C2=A0 =C2=A0=C2=A0 -- Linus Torvalds

^ permalink raw reply

* Re: [PATCH 01/16 v2] pmac_zilog: fix unexpected irq
From: Alan Cox @ 2011-12-06 15:39 UTC (permalink / raw)
  To: Finn Thain; +Cc: linux-m68k, Geert Uytterhoeven, linuxppc-dev, linux-serial
In-Reply-To: <alpine.LNX.2.00.1112070203310.14968@nippy.intranet>

On Wed, 7 Dec 2011 02:13:41 +1100 (EST)
Finn Thain <fthain@telegraphics.com.au> wrote:

> 
> On most 68k Macs the SCC IRQ is an autovector interrupt and cannot be 
> masked. This can be a problem when pmac_zilog starts up.
> 
> For example, the serial debugging code in arch/m68k/kernel/head.S may be 
> used beforehand. It disables the SCC interrupts at the chip but doesn't 
> ack them. Then when a pmac_zilog port is opened and SCC chip interrupts 
> become enabled, the machine locks up with "unexpected interrupt" because 
> request_irq() hasn't happened yet.
> 
> Fix this by setting the interrupt enable bits only after the handler is 
> installed and before it is uninstalled. Also move this bit flipping into a 
> separate pmz_interrupt_control() routine. Replace all instances of these 
> operations with calls to this routine.
> 
> Signed-off-by: Finn Thain <fthain@telegraphics.com.au>

Nice

Acked-by: Alan Cox <alan@linux.intel.com>

^ permalink raw reply

* Re: [PATCH v3 2/3] hvc_init(): Enforce one-time initialization.
From: Miche Baker-Harvey @ 2011-12-06 17:05 UTC (permalink / raw)
  To: Amit Shah
  Cc: Stephen Rothwell, xen-devel, Konrad Rzeszutek Wilk, Rusty Russell,
	linux-kernel, virtualization, Anton Blanchard, Mike Waychison,
	ppc-dev, Greg Kroah-Hartman, Eric Northrup
In-Reply-To: <20111205105452.GB27683@amit-x200.redhat.com>

Amit,

Ah, indeed.  I am not using MSI-X, so virtio_pci::vp_try_to_find_vqs()
calls vp_request_intx() and sets up an interrupt callback.  From
there, when an interrupt occurs, the stack looks something like this:

virtio_pci::vp_interrupt()
  virtio_pci::vp_vring_interrupt()
    virtio_ring::vring_interrupt()
      vq->vq.callback()  <-- in this case, that's virtio_console::control_i=
ntr()
        workqueue::schedule_work()
          workqueue::queue_work()
            queue_work_on(get_cpu())  <-- queues the work on the current CP=
U.

I'm not doing anything to keep multiple control message from being
sent concurrently to the guest, and we will take those interrupts on
any CPU. I've confirmed that the two instances of
handle_control_message() are occurring on different CPUs.

Should this work?  I don't see anywhere that QEMU is serializing the
sending of data to the control queue in the guest, and there's no
serialization in
the control_intr.  I don't understand why you are not seeing the
concurrent execution of handle_control_message().  Are you taking all
your interrupts on a single CPU, maybe?  Or is there some other
serialization in user space?

Miche


On Mon, Dec 5, 2011 at 2:54 AM, Amit Shah <amit.shah@redhat.com> wrote:
> On (Tue) 29 Nov 2011 [09:50:41], Miche Baker-Harvey wrote:
>> Good grief! =A0Sorry for the spacing mess-up! =A0Here's a resend with re=
formatting.
>>
>> Amit,
>> We aren't using either QEMU or kvmtool, but we are using KVM. =A0All
>
> So it's a different userspace? =A0Any chance this different userspace is
> causing these problems to appear? =A0Esp. since I couldn't reproduce
> with qemu.
>
>> the issues we are seeing happen when we try to establish multiple
>> virtioconsoles at boot time. =A0The command line isn't relevant, but I
>> can tell you the protocol that's passing between the host (kvm) and
>> the guest (see the end of this message).
>>
>> We do go through the control_work_handler(), but it's not
>> providing synchronization. =A0Here's a trace of the
>> control_work_handler() and handle_control_message() calls; note that
>> there are two concurrent calls to control_work_handler().
>
> Ah; how does that happen? =A0control_work_handler() should just be
> invoked once, and if there are any more pending work items to be
> consumed, they should be done within the loop inside
> control_work_handler().
>
>> I decorated control_work_handler() with a "lifetime" marker, and
>> passed this value to handle_control_message(), so we can see which
>> control messages are being handled from which instance of
>> the control_work_handler() thread.
>>
>> Notice that we enter control_work_handler() a second time before
>> the handling of the second PORT_ADD message is complete. The
>> first CONSOLE_PORT message is handled by the second
>> control_work_handler() call, but the second is handled by the first
>> control_work_handler() call.
>>
>> root@myubuntu:~# dmesg | grep MBH
>> [3371055.808738] control_work_handler #1
>> [3371055.809372] + #1 handle_control_message PORT_ADD
>> [3371055.810169] - handle_control_message PORT_ADD
>> [3371055.810170] + #1 handle_control_message PORT_ADD
>> [3371055.810244] =A0control_work_handler #2
>> [3371055.810245] + #2 handle_control_message CONSOLE_PORT
>> [3371055.810246] =A0got hvc_ports_mutex
>> [3371055.810578] - handle_control_message PORT_ADD
>> [3371055.810579] + #1 handle_control_message CONSOLE_PORT
>> [3371055.810580] =A0trylock of hvc_ports_mutex failed
>> [3371055.811352] =A0got hvc_ports_mutex
>> [3371055.811370] - handle_control_message CONSOLE_PORT
>> [3371055.816609] - handle_control_message CONSOLE_PORT
>>
>> So, I'm guessing the bug is that there shouldn't be two instances of
>> control_work_handler() running simultaneously?
>
> Yep, I assumed we did that but apparently not. =A0Do you plan to chase
> this one down?
>
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0Amit
>

^ permalink raw reply

* Re: [PATCH 1/2 v2] mtd/nand: fixup for fmr initialization of Freescale NAND controller
From: Scott Wood @ 2011-12-06 17:16 UTC (permalink / raw)
  To: Shengzhou Liu; +Cc: linux-mtd, kumar.gala, linuxppc-dev, dwmw2
In-Reply-To: <1323161655-19050-1-git-send-email-Shengzhou.Liu@freescale.com>

On 12/06/2011 02:54 AM, Shengzhou Liu wrote:
> There was a bug for fmr initialization, which lead to  fmr was always 0x100
> in fsl_elbc_chip_init() and caused FCM command timeout before calling
> fsl_elbc_chip_init_tail(), now we initialize CWTO to maximum timeout value
> and not relying on the setting of bootloader.
> 
> Signed-off-by: Shengzhou Liu <Shengzhou.Liu@freescale.com>
> ---
> v2: make fmr not relying on the setting of bootloader.
> 
>  drivers/mtd/nand/fsl_elbc_nand.c |   10 +++++-----
>  1 files changed, 5 insertions(+), 5 deletions(-)
> 
> diff --git a/drivers/mtd/nand/fsl_elbc_nand.c b/drivers/mtd/nand/fsl_elbc_nand.c
> index eedd8ee..4f405a0 100644
> --- a/drivers/mtd/nand/fsl_elbc_nand.c
> +++ b/drivers/mtd/nand/fsl_elbc_nand.c
> @@ -659,9 +659,7 @@ static int fsl_elbc_chip_init_tail(struct mtd_info *mtd)
>  	if (chip->pagemask & 0xff000000)
>  		al++;
>  
> -	/* add to ECCM mode set in fsl_elbc_init */
> -	priv->fmr |= (12 << FMR_CWTO_SHIFT) |  /* Timeout > 12 ms */
> -	             (al << FMR_AL_SHIFT);
> +	priv->fmr |= al << FMR_AL_SHIFT;
>  
>  	dev_dbg(priv->dev, "fsl_elbc_init: nand->numchips = %d\n",
>  	        chip->numchips);
> @@ -764,8 +762,10 @@ static int fsl_elbc_chip_init(struct fsl_elbc_mtd *priv)
>  	priv->mtd.priv = chip;
>  	priv->mtd.owner = THIS_MODULE;
>  
> -	/* Set the ECCM according to the settings in bootloader.*/
> -	priv->fmr = in_be32(&lbc->fmr) & FMR_ECCM;
> +	/* set timeout to maximum */
> +	priv->fmr = 15 << FMR_CWTO_SHIFT;
> +	if (in_be32(&lbc->bank[priv->bank].or) & OR_FCM_PGS)
> +		priv->fmr |= FMR_ECCM;

Please do not change the way ECCM is handled.  We probably should have
done it this way from the start, but at this point it breaks
compatibility if you have a large page flash and the firmware didn't
touch NAND.

-Scott

^ permalink raw reply

* Re: [PATCH 2/2 v2] mtd/nand: Add ONFI support for FSL NAND controller
From: Scott Wood @ 2011-12-06 17:17 UTC (permalink / raw)
  To: Shengzhou Liu; +Cc: linux-mtd, kumar.gala, linuxppc-dev, dwmw2
In-Reply-To: <1323161655-19050-2-git-send-email-Shengzhou.Liu@freescale.com>

On 12/06/2011 02:54 AM, Shengzhou Liu wrote:
> diff --git a/drivers/mtd/nand/fsl_elbc_nand.c b/drivers/mtd/nand/fsl_elbc_nand.c
> index 4f405a0..b4db407 100644
> --- a/drivers/mtd/nand/fsl_elbc_nand.c
> +++ b/drivers/mtd/nand/fsl_elbc_nand.c
> @@ -349,19 +349,24 @@ static void fsl_elbc_cmdfunc(struct mtd_info *mtd, unsigned int command,
>  		fsl_elbc_run_command(mtd);
>  		return;
>  
> -	/* READID must read all 5 possible bytes while CEB is active */
>  	case NAND_CMD_READID:
> -		dev_vdbg(priv->dev, "fsl_elbc_cmdfunc: NAND_CMD_READID.\n");
> +	case NAND_CMD_PARAM:
> +		dev_vdbg(priv->dev, "fsl_elbc_cmdfunc: NAND_CMD %x\n", command);
>  
>  		out_be32(&lbc->fir, (FIR_OP_CM0 << FIR_OP0_SHIFT) |
>  		                    (FIR_OP_UA  << FIR_OP1_SHIFT) |
>  		                    (FIR_OP_RBW << FIR_OP2_SHIFT));
> -		out_be32(&lbc->fcr, NAND_CMD_READID << FCR_CMD0_SHIFT);
> -		/* nand_get_flash_type() reads 8 bytes of entire ID string */
> -		out_be32(&lbc->fbcr, 8);
> -		elbc_fcm_ctrl->read_bytes = 8;
> +		out_be32(&lbc->fcr, command << FCR_CMD0_SHIFT);
> +		/* reads 8 bytes of entire ID string */
> +		if (NAND_CMD_READID == command) {

if (command == NAND_CMD_READID) {

> +			out_be32(&lbc->fbcr, 8);
> +			elbc_fcm_ctrl->read_bytes = 8;
> +		} else {
> +			out_be32(&lbc->fbcr, 256);
> +			elbc_fcm_ctrl->read_bytes = 256;
> +		}

Any harm in always using 256?

-Scott

^ permalink raw reply

* [PATCH] rapidio/tsi721: modify PCIe capability settings
From: Alexandre Bounine @ 2011-12-06 19:01 UTC (permalink / raw)
  To: akpm, linux-kernel, linuxppc-dev; +Cc: Alexandre Bounine
In-Reply-To: <1323198088-11669-1-git-send-email-alexandre.bounine@idt.com>

Change Completion Timeout Value to avoid data transfer aborts during
intensive data transfers.
Remove hardcoded offset for PCIe capability registers.

Signed-off-by: Alexandre Bounine <alexandre.bounine@idt.com>
---
 drivers/rapidio/devices/tsi721.c |   20 +++++++++++++++-----
 drivers/rapidio/devices/tsi721.h |    2 ++
 2 files changed, 17 insertions(+), 5 deletions(-)

diff --git a/drivers/rapidio/devices/tsi721.c b/drivers/rapidio/devices/tsi721.c
index 83ac8728..691b1ab 100644
--- a/drivers/rapidio/devices/tsi721.c
+++ b/drivers/rapidio/devices/tsi721.c
@@ -2154,7 +2154,7 @@ static int __devinit tsi721_probe(struct pci_dev *pdev,
 				  const struct pci_device_id *id)
 {
 	struct tsi721_device *priv;
-	int i;
+	int i, cap;
 	int err;
 	u32 regval;
 
@@ -2262,10 +2262,20 @@ static int __devinit tsi721_probe(struct pci_dev *pdev,
 			dev_info(&pdev->dev, "Unable to set consistent DMA mask\n");
 	}
 
-	/* Clear "no snoop" and "relaxed ordering" bits. */
-	pci_read_config_dword(pdev, 0x40 + PCI_EXP_DEVCTL, &regval);
-	regval &= ~(PCI_EXP_DEVCTL_RELAX_EN | PCI_EXP_DEVCTL_NOSNOOP_EN);
-	pci_write_config_dword(pdev, 0x40 + PCI_EXP_DEVCTL, regval);
+	cap = pci_pcie_cap(pdev);
+	BUG_ON(cap == 0);
+
+	/* Clear "no snoop" and "relaxed ordering" bits, use default MRRS. */
+	pci_read_config_dword(pdev, cap + PCI_EXP_DEVCTL, &regval);
+	regval &= ~(PCI_EXP_DEVCTL_READRQ | PCI_EXP_DEVCTL_RELAX_EN |
+		    PCI_EXP_DEVCTL_NOSNOOP_EN);
+	regval |= 0x2 << MAX_READ_REQUEST_SZ_SHIFT;
+	pci_write_config_dword(pdev, cap + PCI_EXP_DEVCTL, regval);
+
+	/* Adjust PCIe completion timeout. */
+	pci_read_config_dword(pdev, cap + PCI_EXP_DEVCTL2, &regval);
+	regval &= ~(0x0f);
+	pci_write_config_dword(pdev, cap + PCI_EXP_DEVCTL2, regval | 0x2);
 
 	/*
 	 * FIXUP: correct offsets of MSI-X tables in the MSI-X Capability Block
diff --git a/drivers/rapidio/devices/tsi721.h b/drivers/rapidio/devices/tsi721.h
index 58be4de..822e54c 100644
--- a/drivers/rapidio/devices/tsi721.h
+++ b/drivers/rapidio/devices/tsi721.h
@@ -72,6 +72,8 @@
 #define TSI721_MSIXPBA_OFFSET	0x2a000
 #define TSI721_PCIECFG_EPCTL	0x400
 
+#define MAX_READ_REQUEST_SZ_SHIFT	12
+
 /*
  * Event Management Registers
  */
-- 
1.7.6

^ permalink raw reply related

* [PATCH] rapidio/tsi721: Fix mailbox resource reporting
From: Alexandre Bounine @ 2011-12-06 19:01 UTC (permalink / raw)
  To: akpm, linux-kernel, linuxppc-dev; +Cc: Alexandre Bounine

Report support of four RapidIO mailboxes (MBOX0 - MBOX3) instead of MBOX0
only.

Signed-off-by: Alexandre Bounine <alexandre.bounine@idt.com>
---
 drivers/rapidio/devices/tsi721.c |    4 ++--
 1 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/rapidio/devices/tsi721.c b/drivers/rapidio/devices/tsi721.c
index 514c28c..83ac8728 100644
--- a/drivers/rapidio/devices/tsi721.c
+++ b/drivers/rapidio/devices/tsi721.c
@@ -2107,8 +2107,8 @@ static int __devinit tsi721_setup_mport(struct tsi721_device *priv)
 	INIT_LIST_HEAD(&mport->dbells);
 
 	rio_init_dbell_res(&mport->riores[RIO_DOORBELL_RESOURCE], 0, 0xffff);
-	rio_init_mbox_res(&mport->riores[RIO_INB_MBOX_RESOURCE], 0, 0);
-	rio_init_mbox_res(&mport->riores[RIO_OUTB_MBOX_RESOURCE], 0, 0);
+	rio_init_mbox_res(&mport->riores[RIO_INB_MBOX_RESOURCE], 0, 3);
+	rio_init_mbox_res(&mport->riores[RIO_OUTB_MBOX_RESOURCE], 0, 3);
 	strcpy(mport->name, "Tsi721 mport");
 
 	/* Hook up interrupt handler */
-- 
1.7.6

^ permalink raw reply related

* Re: [PATCH] rapidio/tsi721: Fix mailbox resource reporting
From: Andrew Morton @ 2011-12-06 22:36 UTC (permalink / raw)
  To: Alexandre Bounine; +Cc: linuxppc-dev, linux-kernel
In-Reply-To: <1323198088-11669-1-git-send-email-alexandre.bounine@idt.com>

On Tue,  6 Dec 2011 14:01:27 -0500
Alexandre Bounine <alexandre.bounine@idt.com> wrote:

> Report support of four RapidIO mailboxes (MBOX0 - MBOX3) instead of MBOX0
> only.

I don't know how important these changes are and I don't know what
their end user visible effects are.  Hence I am unable to decide which
kernel version(s) we should merge the patches into.

That's why these things should always be explained in changelogs,
please.

^ permalink raw reply

* Re: [PATCH][v2] powerpc/85xx: Rework P1022DS device tree
From: Tabi Timur-B04825 @ 2011-12-06 22:44 UTC (permalink / raw)
  To: Kumar Gala; +Cc: linuxppc-dev@ozlabs.org
In-Reply-To: <1321540377-3672-1-git-send-email-galak@kernel.crashing.org>

On Thu, Nov 17, 2011 at 8:32 AM, Kumar Gala <galak@kernel.crashing.org> wro=
te:=0A=
>=0A=
> @@ -585,30 +222,11 @@=0A=
> =A0 =A0 =A0 =A0};=0A=
>=0A=
> =A0 =A0 =A0 =A0pci1: pcie@fffe0a000 {=0A=
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 compatible =3D "fsl,p1022-pcie";=0A=
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 device_type =3D "pci";=0A=
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 #interrupt-cells =3D <1>;=0A=
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 #size-cells =3D <2>;=0A=
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 #address-cells =3D <3>;=0A=
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0reg =3D <0xf 0xffe0a000 0 0x1000>;=0A=
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 bus-range =3D <0 255>;=0A=
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0ranges =3D <0x2000000 0x0 0xc0000000 0xc 0=
x40000000 0x0 0x20000000=0A=
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A00x1000000 0x0 0x000000=
00 0xf 0xffc20000 0x0 0x10000>;=0A=
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 clock-frequency =3D <33333333>;=0A=
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 interrupts =3D <16 2 0 0>;=0A=
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 interrupt-map-mask =3D <0xf800 0 0 7>;=0A=
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 interrupt-map =3D <=0A=
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 /* IDSEL 0x0 */=0A=
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 0000 0 0 1 &mpic 0 1=0A=
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 0000 0 0 2 &mpic 1 1=0A=
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 0000 0 0 3 &mpic 2 1=0A=
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 0000 0 0 4 &mpic 3 1=0A=
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 >;=0A=
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0pcie@0 {=0A=
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0reg =3D <0x0 0x0 0x0 0x0 0=
x0>;=0A=
=0A=
Did you forget to delete this 'reg' line?=0A=
=0A=
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 #size-cells =3D <2>;=0A=
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 #address-cells =3D <3>;=0A=
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 device_type =3D "pci";=0A=
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0ranges =3D <0x2000000 0x0 =
0xe0000000=0A=
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A00x2000=
000 0x0 0xe0000000=0A=
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A00x0 0x=
20000000=0A=
=0A=
-- =0A=
Timur Tabi=0A=
Linux kernel developer at Freescale=0A=

^ permalink raw reply

* Re: [PATCH 3/3] mtd/nand : workaround for Freescale FCM to support large-page Nand chip
From: Scott Wood @ 2011-12-07  0:09 UTC (permalink / raw)
  To: shuo.liu
  Cc: Artem.Bityutskiy, linuxppc-dev, linux-kernel, linux-mtd, akpm,
	dwmw2
In-Reply-To: <1322973098-2528-3-git-send-email-shuo.liu@freescale.com>

On 12/03/2011 10:31 PM, shuo.liu@freescale.com wrote:
> From: Liu Shuo <shuo.liu@freescale.com>
> 
> Freescale FCM controller has a 2K size limitation of buffer RAM. In order
> to support the Nand flash chip whose page size is larger than 2K bytes,
> we read/write 2k data repeatedly by issuing FIR_OP_RB/FIR_OP_WB and save
> them to a large buffer.
> 
> Signed-off-by: Liu Shuo <shuo.liu@freescale.com>
> ---
> v3:
>     -remove page_size of struct fsl_elbc_mtd.
>     -do a oob write by NAND_CMD_RNDIN. 
> 
>  drivers/mtd/nand/fsl_elbc_nand.c |  243 ++++++++++++++++++++++++++++++++++----
>  1 files changed, 218 insertions(+), 25 deletions(-)

What is the plan for bad block marker migration?

> @@ -473,13 +568,72 @@ static void fsl_elbc_cmdfunc(struct mtd_info *mtd, unsigned int command,
>  		 * write so the HW generates the ECC.
>  		 */
>  		if (elbc_fcm_ctrl->oob || elbc_fcm_ctrl->column != 0 ||
> -		    elbc_fcm_ctrl->index != mtd->writesize + mtd->oobsize)
> -			out_be32(&lbc->fbcr,
> -				elbc_fcm_ctrl->index - elbc_fcm_ctrl->column);
> -		else
> +		    elbc_fcm_ctrl->index != mtd->writesize + mtd->oobsize) {
> +			if (elbc_fcm_ctrl->oob && mtd->writesize > 2048) {
> +				out_be32(&lbc->fbcr, 64);
> +			} else {
> +				out_be32(&lbc->fbcr, elbc_fcm_ctrl->index
> +						- elbc_fcm_ctrl->column);
> +			}

We need to limit ourselves to the regions that have actually been
written to in the buffer.  fbcr needs to be set separately for first and
last subpages, with intermediate subpages having 0, 64, or 2112 as
appropriate.  Subpages that are entirely before column or entirely after
column + index should be skipped.

> +		} else {
> +			out_be32(&lbc->fir, FIR_OP_WB << FIR_OP1_SHIFT);
> +			for (i = 1; i < n; i++) {
> +				if (i == n - 1) {
> +					elbc_fcm_ctrl->use_mdr = 1;
> +					out_be32(&lbc->fir,
> +						(FIR_OP_WB  << FIR_OP1_SHIFT) |
> +						(FIR_OP_CM3 << FIR_OP2_SHIFT) |
> +						(FIR_OP_CW1 << FIR_OP3_SHIFT) |
> +						(FIR_OP_RS  << FIR_OP4_SHIFT));

Please explicitly show the (FIR_OP_NOP << FIR_OP0_SHIFT) compenent.

> +	} else if (mtd->writesize >= 2048 && mtd->writesize <= 16 * 1024) {
> +
>  		setbits32(&lbc->bank[priv->bank].or, OR_FCM_PGS);

Don't insert a blank line here.

-Scott

^ permalink raw reply

* pata_sl82c105 is unable to properly handle dma (indeed it try to use mwdma2)
From: acrux_it @ 2011-12-07  1:15 UTC (permalink / raw)
  To: linuxppc-dev

New pata_sl82c105 is unable to properly handle dma (indeed it try to use 
mwdma2).
Old ide driver instead worked fine.

Tested on IBM 9114-275 where to use it i must boot with dma disabled i.e. with 
libata.dma=0

[...]
pata_sl82c105 0000:00:03.1: enabling device (0144 -> 0145)
scsi1 : pata_sl82c105
scsi2 : pata_sl82c105
ata1: PATA max MWDMA2 cmd 0x1f000 ctl 0x1f010 bmdma 0x1f040 irq 165
ata2: PATA max MWDMA2 cmd 0x1f020 ctl 0x1f030 bmdma 0x1f048 irq 165
ata1.00: ATAPI: IBM     DROM00205, NR38, max UDMA/33
ata1.00: configured for MWDMA2
[...]
scsi 1:0:0:0: CD-ROM            IBM      DROM00205        NR38 PQ: 0 ANSI: 2
sr0: scsi3-mmc drive: 24x/24x cd/rw xa/form2 cdda tray
cdrom: Uniform CD-ROM driver Revision: 3.20
sr 1:0:0:0: Attached scsi generic sg3 type 5
[...]
ata1: lost interrupt (Status 0x50)
ata1.00: exception Emask 0x0 SAct 0x0 SErr 0x0 action 0x6 frozen
sr 1:0:0:0: CDB: Get configuration: 46 00 00 00 00 00 00 00 20 00
ata1.00: cmd a0/01:00:00:20:00/00:00:00:00:00/a0 tag 0 dma 16416 in
         res 40/00:02:00:0c:00/00:00:00:00:00/a0 Emask 0x4 (timeout)
ata1.00: status: { DRDY }
ata1: soft resetting link
ata1.00: configured for MWDMA2
ata1: EH complete
sr0: CDROM (ioctl) error, command: Get configuration 46 00 00 00 00 00 00 00 
20 00
sr: Sense Key : Aborted Command [current] [descriptor]
sr: Add. Sense: No additional sense information
ata1: lost interrupt (Status 0x50)
ata1.00: exception Emask 0x0 SAct 0x0 SErr 0x0 action 0x6 frozen
sr 1:0:0:0: CDB: Xdread, Read track info: 52 01 00 00 00 01 00 00 20 00
ata1.00: cmd a0/01:00:00:20:00/00:00:00:00:00/a0 tag 0 dma 16416 in
         res 40/00:02:00:08:00/00:00:00:00:00/a0 Emask 0x4 (timeout)
ata1.00: status: { DRDY }
ata1: soft resetting link
ata1.00: configured for MWDMA2
ata1: EH complete
sr0: CDROM (ioctl) error, command: Xdread, Read track info 52 01 00 00 00 01 
00 000
sr: Sense Key : Aborted Command [current] [descriptor]
sr: Add. Sense: No additional sense information
ata1: lost interrupt (Status 0x50)
ata1.00: exception Emask 0x0 SAct 0x0 SErr 0x0 action 0x6 frozen
sr 1:0:0:0: CDB: Get configuration: 46 00 00 00 00 00 00 00 20 00
ata1.00: cmd a0/01:00:00:20:00/00:00:00:00:00/a0 tag 0 dma 16416 in
         res 40/00:02:00:0c:00/00:00:00:00:00/a0 Emask 0x4 (timeout)
ata1.00: status: { DRDY }
ata1: soft resetting link
ata1.00: configured for MWDMA2
ata1: EH complete
sr0: CDROM (ioctl) error, command: Get configuration 46 00 00 00 00 00 00 00 
20 00
sr: Sense Key : Aborted Command [current] [descriptor]
sr: Add. Sense: No additional sense information
ata1: lost interrupt (Status 0x50)
ata1.00: limiting speed to MWDMA1:PIO4
ata1.00: exception Emask 0x0 SAct 0x0 SErr 0x0 action 0x6 frozen
sr 1:0:0:0: CDB: Get configuration: 46 00 00 00 00 00 00 00 20 00
ata1.00: cmd a0/01:00:00:20:00/00:00:00:00:00/a0 tag 0 dma 16416 in
         res 40/00:02:00:0c:00/00:00:00:00:00/a0 Emask 0x4 (timeout)
ata1.00: status: { DRDY }
ata1: soft resetting link
ata1.00: configured for MWDMA1
ata1: EH complete
sr0: CDROM (ioctl) error, command: Get configuration 46 00 00 00 00 00 00 00 
20 00
sr: Sense Key : Aborted Command [current] [descriptor]
sr: Add. Sense: No additional sense information
ata1: lost interrupt (Status 0x50)
ata1.00: exception Emask 0x0 SAct 0x0 SErr 0x0 action 0x6 frozen
sr 1:0:0:0: CDB: Get configuration: 46 00 00 00 00 00 00 00 20 00
ata1.00: cmd a0/01:00:00:20:00/00:00:00:00:00/a0 tag 0 dma 16416 in
         res 40/00:02:00:0c:00/00:00:00:00:00/a0 Emask 0x4 (timeout)
ata1.00: status: { DRDY }
ata1: soft resetting link
ata1.00: configured for MWDMA1
ata1: EH complete
sr0: CDROM (ioctl) error, command: Get configuration 46 00 00 00 00 00 00 00 
20 00
sr: Sense Key : Aborted Command [current] [descriptor]
sr: Add. Sense: No additional sense information
ata1: lost interrupt (Status 0x50)
ata1.00: exception Emask 0x0 SAct 0x0 SErr 0x0 action 0x6 frozen
sr 1:0:0:0: CDB: Get configuration: 46 00 00 00 00 00 00 00 20 00
ata1.00: cmd a0/01:00:00:20:00/00:00:00:00:00/a0 tag 0 dma 16416 in
         res 40/00:02:00:0c:00/00:00:00:00:00/a0 Emask 0x4 (timeout)
ata1.00: status: { DRDY }
ata1: soft resetting link
ata1.00: configured for MWDMA1
ata1: EH complete
sr0: CDROM (ioctl) error, command: Get configuration 46 00 00 00 00 00 00 00 
20 00
sr: Sense Key : Aborted Command [current] [descriptor]
sr: Add. Sense: No additional sense information
ata1: lost interrupt (Status 0x50)
ata1.00: exception Emask 0x0 SAct 0x0 SErr 0x0 action 0x6 frozen
sr 1:0:0:0: CDB: Get configuration: 46 00 00 00 00 00 00 00 20 00
ata1.00: cmd a0/01:00:00:20:00/00:00:00:00:00/a0 tag 0 dma 16416 in
         res 40/00:02:00:0c:00/00:00:00:00:00/a0 Emask 0x4 (timeout)
ata1.00: status: { DRDY }
ata1: soft resetting link
ata1.00: configured for MWDMA1
ata1: EH complete
sr0: CDROM (ioctl) error, command: Get configuration 46 00 00 00 00 00 00 00 
20 00
sr: Sense Key : Aborted Command [current] [descriptor]
sr: Add. Sense: No additional sense information
ata1: lost interrupt (Status 0x50)
ata1.00: exception Emask 0x0 SAct 0x0 SErr 0x0 action 0x6 frozen
sr 1:0:0:0: CDB: Get configuration: 46 00 00 00 00 00 00 00 20 00
ata1.00: cmd a0/01:00:00:20:00/00:00:00:00:00/a0 tag 0 dma 16416 in
         res 40/00:02:00:0c:00/00:00:00:00:00/a0 Emask 0x4 (timeout)
ata1.00: status: { DRDY }
ata1: soft resetting link
ata1.00: configured for MWDMA1
ata1: EH complete







cheers,
--nico

^ permalink raw reply

* Re: [PATCH 01/16 v2] pmac_zilog: fix unexpected irq
From: Finn Thain @ 2011-12-07  1:26 UTC (permalink / raw)
  To: Geert Uytterhoeven; +Cc: linux-m68k, linuxppc-dev, linux-serial
In-Reply-To: <CAMuHMdUB-jQQB=ieumYTehdZz1EnoSazEAhsnEunHSnK2o=k8Q@mail.gmail.com>

[-- Attachment #1: Type: TEXT/PLAIN, Size: 2634 bytes --]


On Tue, 6 Dec 2011, Geert Uytterhoeven wrote:

> Hi Finn,
> 
> On Tue, Dec 6, 2011 at 16:13, Finn Thain <fthain@telegraphics.com.au> wrote:
> > +static void pmz_interrupt_control(struct uart_pmac_port *uap, int enable)
> > +{
> > +       if (enable) {
> > +               uap->curregs[1] |= INT_ALL_Rx | TxINT_ENAB;
> > +               if (!ZS_IS_EXTCLK(uap))
> > +                       uap->curregs[1] |= EXT_INT_ENAB;
> > +       } else {
> > +               uap->curregs[1] &= ~(EXT_INT_ENAB | TxINT_ENAB | RxINT_MASK);
> 
> Should there be a call to zssync() here?

I don't think so. Though I should have mentioned the change in the patch 
header.

> The old code always did that after disabling interrupts.

pmz_load_zsregs(), pmz_set_termios() and pmz_suspend() don't do it.

sunzilog only does it on sparc64 and only when writing to the data 
register or writing command modifiers to the control register ("On 64-bit 
sparc we only need to flush single writes to ensure completion.")

I can't find any purpose for control register reads in the chip manual.

The zssync() calls following some WR1 writes originate here: 
http://git.kernel.org/?p=linux/kernel/git/tglx/history.git;a=commitdiff;h=9e9d9f693c7def3900725c04c6b64311655eea51

So I don't see any need for control register reads but hopefully Ben can 
say for sure.

Reading the patch now I notice that I dropped a pmz_maybe_update_regs() or 
pmz_load_zsregs() in the suspend path. I will send a new patch.

Finn

> 
> > +       }
> > +       write_zsreg(uap, R1, uap->curregs[1]);
> > +}
> > +
> >  static struct tty_struct *pmz_receive_chars(struct uart_pmac_port *uap)
> >  {
> >        struct tty_struct *tty = NULL;
> > @@ -339,9 +351,7 @@ static struct tty_struct *pmz_receive_ch
> >
> >        return tty;
> >  flood:
> > -       uap->curregs[R1] &= ~(EXT_INT_ENAB | TxINT_ENAB | RxINT_MASK);
> > -       write_zsreg(uap, R1, uap->curregs[R1]);
> > -       zssync(uap);
> 
> Cfr. e.g. here.
> 
> > +       pmz_interrupt_control(uap, 0);
> >        pmz_error("pmz: rx irq flood !\n");
> >        return tty;
> >  }
> 
> Gr{oetje,eeting}s,
> 
>                         Geert
> 
> --
> Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org
> 
> In personal conversations with technical people, I call myself a hacker. But
> when I'm talking to journalists I just say "programmer" or something like that.
>                                 -- Linus Torvalds
> 

^ permalink raw reply

* Re: pata_sl82c105 is unable to properly handle dma (indeed it try to use mwdma2)
From: Benjamin Herrenschmidt @ 2011-12-07  2:21 UTC (permalink / raw)
  To: acrux_it@libero.it; +Cc: linux-ide, linuxppc-dev
In-Reply-To: <28546010.491181323220500482.JavaMail.defaultUser@defaultHost>

On Wed, 2011-12-07 at 02:15 +0100, acrux_it@libero.it wrote:
> New pata_sl82c105 is unable to properly handle dma (indeed it try to use 
> mwdma2).
> Old ide driver instead worked fine.
> 
> Tested on IBM 9114-275 where to use it i must boot with dma disabled i.e. with 
> libata.dma=0

Adding the linux-ide list on CC. Can you also send a dmesg with the old
IDE driver ? It might be useful to compare the values programmed by the
2 versions of the driver in the timing registers.

Cheers,
Ben.

> [...]
> pata_sl82c105 0000:00:03.1: enabling device (0144 -> 0145)
> scsi1 : pata_sl82c105
> scsi2 : pata_sl82c105
> ata1: PATA max MWDMA2 cmd 0x1f000 ctl 0x1f010 bmdma 0x1f040 irq 165
> ata2: PATA max MWDMA2 cmd 0x1f020 ctl 0x1f030 bmdma 0x1f048 irq 165
> ata1.00: ATAPI: IBM     DROM00205, NR38, max UDMA/33
> ata1.00: configured for MWDMA2
> [...]
> scsi 1:0:0:0: CD-ROM            IBM      DROM00205        NR38 PQ: 0 ANSI: 2
> sr0: scsi3-mmc drive: 24x/24x cd/rw xa/form2 cdda tray
> cdrom: Uniform CD-ROM driver Revision: 3.20
> sr 1:0:0:0: Attached scsi generic sg3 type 5
> [...]
> ata1: lost interrupt (Status 0x50)
> ata1.00: exception Emask 0x0 SAct 0x0 SErr 0x0 action 0x6 frozen
> sr 1:0:0:0: CDB: Get configuration: 46 00 00 00 00 00 00 00 20 00
> ata1.00: cmd a0/01:00:00:20:00/00:00:00:00:00/a0 tag 0 dma 16416 in
>          res 40/00:02:00:0c:00/00:00:00:00:00/a0 Emask 0x4 (timeout)
> ata1.00: status: { DRDY }
> ata1: soft resetting link
> ata1.00: configured for MWDMA2
> ata1: EH complete
> sr0: CDROM (ioctl) error, command: Get configuration 46 00 00 00 00 00 00 00 
> 20 00
> sr: Sense Key : Aborted Command [current] [descriptor]
> sr: Add. Sense: No additional sense information
> ata1: lost interrupt (Status 0x50)
> ata1.00: exception Emask 0x0 SAct 0x0 SErr 0x0 action 0x6 frozen
> sr 1:0:0:0: CDB: Xdread, Read track info: 52 01 00 00 00 01 00 00 20 00
> ata1.00: cmd a0/01:00:00:20:00/00:00:00:00:00/a0 tag 0 dma 16416 in
>          res 40/00:02:00:08:00/00:00:00:00:00/a0 Emask 0x4 (timeout)
> ata1.00: status: { DRDY }
> ata1: soft resetting link
> ata1.00: configured for MWDMA2
> ata1: EH complete
> sr0: CDROM (ioctl) error, command: Xdread, Read track info 52 01 00 00 00 01 
> 00 000
> sr: Sense Key : Aborted Command [current] [descriptor]
> sr: Add. Sense: No additional sense information
> ata1: lost interrupt (Status 0x50)
> ata1.00: exception Emask 0x0 SAct 0x0 SErr 0x0 action 0x6 frozen
> sr 1:0:0:0: CDB: Get configuration: 46 00 00 00 00 00 00 00 20 00
> ata1.00: cmd a0/01:00:00:20:00/00:00:00:00:00/a0 tag 0 dma 16416 in
>          res 40/00:02:00:0c:00/00:00:00:00:00/a0 Emask 0x4 (timeout)
> ata1.00: status: { DRDY }
> ata1: soft resetting link
> ata1.00: configured for MWDMA2
> ata1: EH complete
> sr0: CDROM (ioctl) error, command: Get configuration 46 00 00 00 00 00 00 00 
> 20 00
> sr: Sense Key : Aborted Command [current] [descriptor]
> sr: Add. Sense: No additional sense information
> ata1: lost interrupt (Status 0x50)
> ata1.00: limiting speed to MWDMA1:PIO4
> ata1.00: exception Emask 0x0 SAct 0x0 SErr 0x0 action 0x6 frozen
> sr 1:0:0:0: CDB: Get configuration: 46 00 00 00 00 00 00 00 20 00
> ata1.00: cmd a0/01:00:00:20:00/00:00:00:00:00/a0 tag 0 dma 16416 in
>          res 40/00:02:00:0c:00/00:00:00:00:00/a0 Emask 0x4 (timeout)
> ata1.00: status: { DRDY }
> ata1: soft resetting link
> ata1.00: configured for MWDMA1
> ata1: EH complete
> sr0: CDROM (ioctl) error, command: Get configuration 46 00 00 00 00 00 00 00 
> 20 00
> sr: Sense Key : Aborted Command [current] [descriptor]
> sr: Add. Sense: No additional sense information
> ata1: lost interrupt (Status 0x50)
> ata1.00: exception Emask 0x0 SAct 0x0 SErr 0x0 action 0x6 frozen
> sr 1:0:0:0: CDB: Get configuration: 46 00 00 00 00 00 00 00 20 00
> ata1.00: cmd a0/01:00:00:20:00/00:00:00:00:00/a0 tag 0 dma 16416 in
>          res 40/00:02:00:0c:00/00:00:00:00:00/a0 Emask 0x4 (timeout)
> ata1.00: status: { DRDY }
> ata1: soft resetting link
> ata1.00: configured for MWDMA1
> ata1: EH complete
> sr0: CDROM (ioctl) error, command: Get configuration 46 00 00 00 00 00 00 00 
> 20 00
> sr: Sense Key : Aborted Command [current] [descriptor]
> sr: Add. Sense: No additional sense information
> ata1: lost interrupt (Status 0x50)
> ata1.00: exception Emask 0x0 SAct 0x0 SErr 0x0 action 0x6 frozen
> sr 1:0:0:0: CDB: Get configuration: 46 00 00 00 00 00 00 00 20 00
> ata1.00: cmd a0/01:00:00:20:00/00:00:00:00:00/a0 tag 0 dma 16416 in
>          res 40/00:02:00:0c:00/00:00:00:00:00/a0 Emask 0x4 (timeout)
> ata1.00: status: { DRDY }
> ata1: soft resetting link
> ata1.00: configured for MWDMA1
> ata1: EH complete
> sr0: CDROM (ioctl) error, command: Get configuration 46 00 00 00 00 00 00 00 
> 20 00
> sr: Sense Key : Aborted Command [current] [descriptor]
> sr: Add. Sense: No additional sense information
> ata1: lost interrupt (Status 0x50)
> ata1.00: exception Emask 0x0 SAct 0x0 SErr 0x0 action 0x6 frozen
> sr 1:0:0:0: CDB: Get configuration: 46 00 00 00 00 00 00 00 20 00
> ata1.00: cmd a0/01:00:00:20:00/00:00:00:00:00/a0 tag 0 dma 16416 in
>          res 40/00:02:00:0c:00/00:00:00:00:00/a0 Emask 0x4 (timeout)
> ata1.00: status: { DRDY }
> ata1: soft resetting link
> ata1.00: configured for MWDMA1
> ata1: EH complete
> sr0: CDROM (ioctl) error, command: Get configuration 46 00 00 00 00 00 00 00 
> 20 00
> sr: Sense Key : Aborted Command [current] [descriptor]
> sr: Add. Sense: No additional sense information
> ata1: lost interrupt (Status 0x50)
> ata1.00: exception Emask 0x0 SAct 0x0 SErr 0x0 action 0x6 frozen
> sr 1:0:0:0: CDB: Get configuration: 46 00 00 00 00 00 00 00 20 00
> ata1.00: cmd a0/01:00:00:20:00/00:00:00:00:00/a0 tag 0 dma 16416 in
>          res 40/00:02:00:0c:00/00:00:00:00:00/a0 Emask 0x4 (timeout)
> ata1.00: status: { DRDY }
> ata1: soft resetting link
> ata1.00: configured for MWDMA1
> ata1: EH complete
> 
> 
> 
> 
> 
> 
> 
> cheers,
> --nico
> _______________________________________________
> Linuxppc-dev mailing list
> Linuxppc-dev@lists.ozlabs.org
> https://lists.ozlabs.org/listinfo/linuxppc-dev

^ permalink raw reply

* RE: [PATCH] rapidio/tsi721: Fix mailbox resource reporting
From: Bounine, Alexandre @ 2011-12-07  2:33 UTC (permalink / raw)
  To: Andrew Morton; +Cc: linuxppc-dev, linux-kernel
In-Reply-To: <20111206143638.12598c7b.akpm@linux-foundation.org>

[-- Attachment #1: Type: text/plain, Size: 1195 bytes --]

Tsi721 patches are applicable to 3.2-rc1 and newer only. Sorry for not describing it properly.
This and following patch are fixes for issues found since 3.2-rc1.
I will update changelogs for these patches with more details and resubmit them tomorrow.

________________________________

From: linuxppc-dev-bounces+alexandre.bounine=idt.com@lists.ozlabs.org on behalf of Andrew Morton
Sent: Tue 12/6/2011 5:36 PM
To: Bounine, Alexandre
Cc: linuxppc-dev@lists.ozlabs.org; linux-kernel@vger.kernel.org
Subject: Re: [PATCH] rapidio/tsi721: Fix mailbox resource reporting



On Tue,  6 Dec 2011 14:01:27 -0500
Alexandre Bounine <alexandre.bounine@idt.com> wrote:

> Report support of four RapidIO mailboxes (MBOX0 - MBOX3) instead of MBOX0
> only.

I don't know how important these changes are and I don't know what
their end user visible effects are.  Hence I am unable to decide which
kernel version(s) we should merge the patches into.

That's why these things should always be explained in changelogs,
please.

_______________________________________________
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev



[-- Attachment #2: Type: text/html, Size: 1916 bytes --]

^ permalink raw reply

* RE: [PATCH 2/2 v2] mtd/nand: Add ONFI support for FSL NAND controller
From: Liu Shengzhou-B36685 @ 2011-12-07  3:16 UTC (permalink / raw)
  To: Wood Scott-B07421
  Cc: linux-mtd@lists.infradead.org, Gala Kumar-B11780,
	linuxppc-dev@lists.ozlabs.org, dwmw2@infradead.org
In-Reply-To: <4EDE4E1D.4030408@freescale.com>

DQo+IC0tLS0tT3JpZ2luYWwgTWVzc2FnZS0tLS0tDQo+IEZyb206IFdvb2QgU2NvdHQtQjA3NDIx
DQo+IFNlbnQ6IFdlZG5lc2RheSwgRGVjZW1iZXIgMDcsIDIwMTEgMToxNyBBTQ0KPiBUbzogTGl1
IFNoZW5nemhvdS1CMzY2ODUNCj4gQ2M6IGxpbnV4cHBjLWRldkBsaXN0cy5vemxhYnMub3JnOyBs
aW51eC1tdGRAbGlzdHMuaW5mcmFkZWFkLm9yZzsNCj4gZHdtdzJAaW5mcmFkZWFkLm9yZzsgR2Fs
YSBLdW1hci1CMTE3ODANCj4gU3ViamVjdDogUmU6IFtQQVRDSCAyLzIgdjJdIG10ZC9uYW5kOiBB
ZGQgT05GSSBzdXBwb3J0IGZvciBGU0wgTkFORA0KPiBjb250cm9sbGVyDQo+IA0KPiBPbiAxMi8w
Ni8yMDExIDAyOjU0IEFNLCBTaGVuZ3pob3UgTGl1IHdyb3RlOg0KPiA+IGRpZmYgLS1naXQgYS9k
cml2ZXJzL210ZC9uYW5kL2ZzbF9lbGJjX25hbmQuYw0KPiBiL2RyaXZlcnMvbXRkL25hbmQvZnNs
X2VsYmNfbmFuZC5jDQo+ID4gaW5kZXggNGY0MDVhMC4uYjRkYjQwNyAxMDA2NDQNCj4gPiAtLS0g
YS9kcml2ZXJzL210ZC9uYW5kL2ZzbF9lbGJjX25hbmQuYw0KPiA+ICsrKyBiL2RyaXZlcnMvbXRk
L25hbmQvZnNsX2VsYmNfbmFuZC5jDQo+ID4gQEAgLTM0OSwxOSArMzQ5LDI0IEBAIHN0YXRpYyB2
b2lkIGZzbF9lbGJjX2NtZGZ1bmMoc3RydWN0IG10ZF9pbmZvICptdGQsDQo+IHVuc2lnbmVkIGlu
dCBjb21tYW5kLA0KPiA+ICAJCWZzbF9lbGJjX3J1bl9jb21tYW5kKG10ZCk7DQo+ID4gIAkJcmV0
dXJuOw0KPiA+DQo+ID4gLQkvKiBSRUFESUQgbXVzdCByZWFkIGFsbCA1IHBvc3NpYmxlIGJ5dGVz
IHdoaWxlIENFQiBpcyBhY3RpdmUgKi8NCj4gPiAgCWNhc2UgTkFORF9DTURfUkVBRElEOg0KPiA+
IC0JCWRldl92ZGJnKHByaXYtPmRldiwgImZzbF9lbGJjX2NtZGZ1bmM6IE5BTkRfQ01EX1JFQURJ
RC5cbiIpOw0KPiA+ICsJY2FzZSBOQU5EX0NNRF9QQVJBTToNCj4gPiArCQlkZXZfdmRiZyhwcml2
LT5kZXYsICJmc2xfZWxiY19jbWRmdW5jOiBOQU5EX0NNRCAleFxuIiwNCj4gY29tbWFuZCk7DQo+
ID4NCj4gPiAgCQlvdXRfYmUzMigmbGJjLT5maXIsIChGSVJfT1BfQ00wIDw8IEZJUl9PUDBfU0hJ
RlQpIHwNCj4gPiAgCQkgICAgICAgICAgICAgICAgICAgIChGSVJfT1BfVUEgIDw8IEZJUl9PUDFf
U0hJRlQpIHwNCj4gPiAgCQkgICAgICAgICAgICAgICAgICAgIChGSVJfT1BfUkJXIDw8IEZJUl9P
UDJfU0hJRlQpKTsNCj4gPiAtCQlvdXRfYmUzMigmbGJjLT5mY3IsIE5BTkRfQ01EX1JFQURJRCA8
PCBGQ1JfQ01EMF9TSElGVCk7DQo+ID4gLQkJLyogbmFuZF9nZXRfZmxhc2hfdHlwZSgpIHJlYWRz
IDggYnl0ZXMgb2YgZW50aXJlIElEIHN0cmluZyAqLw0KPiA+IC0JCW91dF9iZTMyKCZsYmMtPmZi
Y3IsIDgpOw0KPiA+IC0JCWVsYmNfZmNtX2N0cmwtPnJlYWRfYnl0ZXMgPSA4Ow0KPiA+ICsJCW91
dF9iZTMyKCZsYmMtPmZjciwgY29tbWFuZCA8PCBGQ1JfQ01EMF9TSElGVCk7DQo+ID4gKwkJLyog
cmVhZHMgOCBieXRlcyBvZiBlbnRpcmUgSUQgc3RyaW5nICovDQo+ID4gKwkJaWYgKE5BTkRfQ01E
X1JFQURJRCA9PSBjb21tYW5kKSB7DQo+IA0KPiBpZiAoY29tbWFuZCA9PSBOQU5EX0NNRF9SRUFE
SUQpIHsNCj4gDQo+ID4gKwkJCW91dF9iZTMyKCZsYmMtPmZiY3IsIDgpOw0KPiA+ICsJCQllbGJj
X2ZjbV9jdHJsLT5yZWFkX2J5dGVzID0gODsNCj4gPiArCQl9IGVsc2Ugew0KPiA+ICsJCQlvdXRf
YmUzMigmbGJjLT5mYmNyLCAyNTYpOw0KPiA+ICsJCQllbGJjX2ZjbV9jdHJsLT5yZWFkX2J5dGVz
ID0gMjU2Ow0KPiA+ICsJCX0NCj4gDQo+IEFueSBoYXJtIGluIGFsd2F5cyB1c2luZyAyNTY/DQo+
IA0KPiAtU2NvdHQNCltTaGVuZ3pob3VdIEZvciBOQU5EX0NNRF9SRUFESUQgY29tbWFuZCwgdGhl
IHRvdGFsIGJ5dGVzIG9mIGVudGlyZSBJRCBzdHJpbmcgYXJlIDgsIHRoZXJlIGFyZSBub3QgMjU2
IGJ5dGVzIHNvIG1hbnksIGl0J3MgdW5uZWNlc3NhcnkgYW5kIGxvb2tzIG5vdCBzbyB3ZWxsIGxv
Z2ljYWxseSB0byBhbHdheXMgdXNpbmcgMjU2LCB0aG91Z2ggaXQgd29ya3MuDQoNCg0K

^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox