From: Huang, Tao <huangtao@rock-chips.com>
Date: Thu, 20 Nov 2014 11:55:43 +0000 (+0800)
Subject: Merge branch develop-3.10 into develop-3.10-next
X-Git-Tag: firefly_0821_release~4158^2~573
X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=1f49c03ee0d79c6941697d40dae7ff1dddf95b79;p=firefly-linux-kernel-4.4.55.git

Merge branch develop-3.10 into develop-3.10-next
---

1f49c03ee0d79c6941697d40dae7ff1dddf95b79
diff --cc drivers/iommu/rockchip-iommu.c
index b5a815cb1d88,f01fe0e9cdfa..308ef650bdb6
--- a/drivers/iommu/rockchip-iommu.c
+++ b/drivers/iommu/rockchip-iommu.c
@@@ -461,216 -462,171 +462,175 @@@ static void rockchip_iommu_set_ptbase(v
  	__raw_writel(pgd, base + IOMMU_REGISTER_DTE_ADDR);
  }
  
- static bool iommu_reset(void __iomem *base, const char *dbgname)
+ static bool rockchip_iommu_reset(void __iomem *base, const char *dbgname)
  {
- 	bool err = true;
+ 	bool ret = true;
  
- 	err = iommu_enable_stall(base);
- 	if (!err) {
- 		pr_info("%s:stall failed: %s\n", __func__, dbgname);
- 		return err;
+ 	ret = rockchip_iommu_raw_reset(base);
+ 	if (!ret) {
+ 		pr_info("(%s), %s failed\n", dbgname, __func__);
+ 		return ret;
  	}
- 	err = iommu_raw_reset(base);
- 	if (err) {
- 		if (base != rk312x_vop_mmu_base)
- 			__raw_writel(IOMMU_INTERRUPT_PAGE_FAULT |
+ 
+ 	if (base != rk312x_vop_mmu_base)
+ 		__raw_writel(IOMMU_INTERRUPT_PAGE_FAULT |
  			     IOMMU_INTERRUPT_READ_BUS_ERROR,
- 			     base+IOMMU_REGISTER_INT_MASK);
- 		else
- 			__raw_writel(0x00, base + IOMMU_REGISTER_INT_MASK);
- 	}
- 	iommu_disable_stall(base);
- 	if (!err)
- 		pr_info("%s: failed: %s\n", __func__, dbgname);
- 	return err;
+ 			     base + IOMMU_REGISTER_INT_MASK);
+ 	else
+ 		__raw_writel(0x00, base + IOMMU_REGISTER_INT_MASK);
+ 
+ 	return ret;
  }
  
- static inline void pgtable_flush(void *vastart, void *vaend)
+ static inline void rockchip_pgtable_flush(void *vastart, void *vaend)
  {
 +#ifdef CONFIG_ARM
  	dmac_flush_range(vastart, vaend);
  	outer_flush_range(virt_to_phys(vastart), virt_to_phys(vaend));
 +#elif defined(CONFIG_ARM64)
 +	__dma_flush_range(vastart, vaend);
 +#endif
  }
  
- static void set_fault_handler(struct iommu_drvdata *data,
- 				rockchip_iommu_fault_handler_t handler)
+ static void dump_pagetbl(dma_addr_t fault_address, u32 addr_dte)
  {
- 	unsigned long flags;
- 
- 	write_lock_irqsave(&data->lock, flags);
- 	data->fault_handler = handler;
- 	write_unlock_irqrestore(&data->lock, flags);
+ 	u32 dte_index, pte_index, page_offset;
+ 	u32 mmu_dte_addr;
+ 	phys_addr_t mmu_dte_addr_phys, dte_addr_phys;
+ 	u32 *dte_addr;
+ 	u32 dte;
+ 	phys_addr_t pte_addr_phys = 0;
+ 	u32 *pte_addr = NULL;
+ 	u32 pte = 0;
+ 	phys_addr_t page_addr_phys = 0;
+ 	u32 page_flags = 0;
+ 
+ 	dte_index = rockchip_lv1ent_offset(fault_address);
+ 	pte_index = rockchip_lv2ent_offset(fault_address);
+ 	page_offset = (u32)(fault_address & 0x00000fff);
+ 
+ 	mmu_dte_addr = addr_dte;
+ 	mmu_dte_addr_phys = (phys_addr_t)mmu_dte_addr;
+ 
+ 	dte_addr_phys = mmu_dte_addr_phys + (4 * dte_index);
+ 	dte_addr = phys_to_virt(dte_addr_phys);
+ 	dte = *dte_addr;
+ 
+ 	if (!(IOMMU_FLAGS_PRESENT & dte))
+ 		goto print_it;
+ 
+ 	pte_addr_phys = ((phys_addr_t)dte & 0xfffff000) + (pte_index * 4);
+ 	pte_addr = phys_to_virt(pte_addr_phys);
+ 	pte = *pte_addr;
+ 
+ 	if (!(IOMMU_FLAGS_PRESENT & pte))
+ 		goto print_it;
+ 
+ 	page_addr_phys = ((phys_addr_t)pte & 0xfffff000) + page_offset;
+ 	page_flags = pte & 0x000001fe;
+ 
+ print_it:
+ 	pr_err("iova = %pad: dte_index: 0x%03x pte_index: 0x%03x page_offset: 0x%03x\n",
+ 		&fault_address, dte_index, pte_index, page_offset);
+ 	pr_err("mmu_dte_addr: %pa dte@%pa: %#08x valid: %u pte@%pa: %#08x valid: %u page@%pa flags: %#03x\n",
+ 		&mmu_dte_addr_phys, &dte_addr_phys, dte,
+ 		(dte & IOMMU_FLAGS_PRESENT), &pte_addr_phys, pte,
+ 		(pte & IOMMU_FLAGS_PRESENT), &page_addr_phys, page_flags);
  }
  
- static int default_fault_handler(struct device *dev,
- 				 enum rk_iommu_inttype itype,
- 				 unsigned long pgtable_base,
- 				 unsigned long fault_addr,
- 				 unsigned int status)
+ static irqreturn_t rockchip_iommu_irq(int irq, void *dev_id)
  {
- 	struct iommu_drvdata *data = dev_get_drvdata(dev->archdata.iommu);
+ 	/* SYSMMU is in blocked when interrupt occurred. */
+ 	struct iommu_drvdata *data = dev_id;
+ 	u32 status;
+ 	u32 rawstat;
+ 	dma_addr_t fault_address;
+ 	int i;
+ 	unsigned long flags;
+ 	int ret;
+ 	u32 reg_status;
  
- 	if (!data) {
- 		dev_err(dev->archdata.iommu,"%s,iommu device not assigned yet\n", __func__);
- 		return 0;
+ 	spin_lock_irqsave(&data->data_lock, flags);
+ 
+ 	if (!rockchip_is_iommu_active(data)) {
+ 		spin_unlock_irqrestore(&data->data_lock, flags);
+ 		return IRQ_HANDLED;
  	}
- 	if ((itype >= IOMMU_FAULTS_NUM) || (itype < IOMMU_PAGEFAULT))
- 		itype = IOMMU_FAULT_UNKNOWN;
  
- 	if (itype == IOMMU_BUSERROR)
- 		dev_err(dev->archdata.iommu,"%s occured at 0x%lx(Page table base: 0x%lx)\n",
- 		       iommu_fault_name[itype], fault_addr, pgtable_base);
+ 	for (i = 0; i < data->num_res_mem; i++) {
+ 		status = __raw_readl(data->res_bases[i] +
+ 				     IOMMU_REGISTER_INT_STATUS);
+ 		if (status == 0)
+ 			continue;
  
- 	if (itype == IOMMU_PAGEFAULT)
- 		dev_err(dev->archdata.iommu,"IOMMU:Page fault detected at 0x%lx from bus id %d of type %s on %s\n",
- 		       fault_addr,
- 		       (status >> 6) & 0x1F,
- 		       (status & 32) ? "write" : "read",
- 		       data->dbgname);
+ 		rawstat = __raw_readl(data->res_bases[i] +
+ 				      IOMMU_REGISTER_INT_RAWSTAT);
  
- 	dev_err(dev->archdata.iommu,"Generating Kernel OOPS... because it is unrecoverable.\n");
+ 		reg_status = __raw_readl(data->res_bases[i] +
+ 				      	 IOMMU_REGISTER_STATUS);
  
- 	BUG();
+ 		dev_info(data->iommu, "1.rawstat = 0x%08x,status = 0x%08x,reg_status = 0x%08x\n",
+ 			 rawstat, status, reg_status);
  
- 	return 0;
- }
+ 		if (rawstat & IOMMU_INTERRUPT_PAGE_FAULT) {
+ 			u32 dte;
+ 			int flags;
  
- static void dump_pagetbl(u32 fault_address, u32 addr_dte)
- {
- 	u32 lv1_offset;
- 	u32 lv2_offset;
- 
- 	u32 *lv1_entry_pa;
- 	u32 *lv1_entry_va;
- 	u32 *lv1_entry_value;
- 
- 	u32 *lv2_base;
- 	u32 *lv2_entry_pa;
- 	u32 *lv2_entry_va;
- 	u32 *lv2_entry_value;
- 
- 
- 	lv1_offset = lv1ent_offset(fault_address);
- 	lv2_offset = lv2ent_offset(fault_address);
- 
- 	lv1_entry_pa = (u32 *)addr_dte + lv1_offset;
- 	lv1_entry_va = (u32 *)(__va(addr_dte)) + lv1_offset;
- 	lv1_entry_value = (u32 *)(*lv1_entry_va);
- 
- 	lv2_base = (u32 *)((*lv1_entry_va) & 0xfffffffe);
- 	lv2_entry_pa = (u32 *)lv2_base + lv2_offset;
- 	lv2_entry_va = (u32 *)(__va(lv2_base)) + lv2_offset;
- 	lv2_entry_value = (u32 *)(*lv2_entry_va);
- 
- 	dev_info(NULL,"fault address = 0x%08x,dte addr pa = 0x%08x,va = 0x%08x\n",
- 		fault_address, addr_dte, (u32)__va(addr_dte));
- 	dev_info(NULL,"lv1_offset = 0x%x,lv1_entry_pa = 0x%08x,lv1_entry_va = 0x%08x\n",
- 		lv1_offset, (u32)lv1_entry_pa, (u32)lv1_entry_va);
- 	dev_info(NULL,"lv1_entry_value(*lv1_entry_va) = 0x%08x,lv2_base = 0x%08x\n",
- 		(u32)lv1_entry_value, (u32)lv2_base);
- 	dev_info(NULL,"lv2_offset = 0x%x,lv2_entry_pa = 0x%08x,lv2_entry_va = 0x%08x\n",
- 		lv2_offset, (u32)lv2_entry_pa, (u32)lv2_entry_va);
- 	dev_info(NULL,"lv2_entry value(*lv2_entry_va) = 0x%08x\n",
- 		(u32)lv2_entry_value);
- }
+ 			fault_address = __raw_readl(data->res_bases[i] +
+ 				   	    IOMMU_REGISTER_PAGE_FAULT_ADDR);
  
- static irqreturn_t rockchip_iommu_irq(int irq, void *dev_id)
- {
- 	/* SYSMMU is in blocked when interrupt occurred. */
- 	struct iommu_drvdata *data = dev_id;
- 	struct resource *irqres;
- 	struct platform_device *pdev;
- 	enum rk_iommu_inttype itype = IOMMU_FAULT_UNKNOWN;
- 	u32 status;
- 	u32 rawstat;
- 	u32 int_status;
- 	u32 fault_address;
- 	int i, ret = 0;
+ 			dte = __raw_readl(data->res_bases[i] +
+ 					  IOMMU_REGISTER_DTE_ADDR);
  
- 	read_lock(&data->lock);
+ 			flags = (status & 32) ? 1 : 0;
  
- 	if (!is_iommu_active(data)) {
- 		read_unlock(&data->lock);
- 		return IRQ_HANDLED;
- 	}
- 	
- 	if(cpu_is_rk312x() || cpu_is_rk3036())
- 		rockchip_vcodec_select(data->dbgname);
- 	
- 	pdev = to_platform_device(data->iommu);
+ 			dev_err(data->iommu, "Page fault detected at %pad from bus id %d of type %s on %s\n",
+ 				&fault_address, (status >> 6) & 0x1F,
+ 				(flags == 1) ? "write" : "read", data->dbgname);
  
- 	for (i = 0; i < data->num_res_irq; i++) {
- 		irqres = platform_get_resource(pdev, IORESOURCE_IRQ, i);
- 		if (irqres && ((int)irqres->start == irq)) {
- 			if (data->res_bases[i] == rk312x_vop_mmu_base) {
- 				read_unlock(&data->lock);
- 				return IRQ_HANDLED;
- 			}
- 			break;
+ 			dump_pagetbl(fault_address, dte);
+ 
+ 			if (data->domain)
+ 				report_iommu_fault(data->domain, data->iommu,
+ 						   fault_address, flags);
+ 
+ 			rockchip_iommu_page_fault_done(data->res_bases[i],
+ 					               data->dbgname);
  		}
- 	}
  
- 	if (i == data->num_res_irq) {
- 		itype = IOMMU_FAULT_UNKNOWN;
- 	} else {
- 		int_status = __raw_readl(data->res_bases[i] +
- 					 IOMMU_REGISTER_INT_STATUS);
- 
- 		if (int_status != 0) {
- 			/*mask status*/
- 			__raw_writel(0x00, data->res_bases[i] +
- 				     IOMMU_REGISTER_INT_MASK);
- 
- 			rawstat = __raw_readl(data->res_bases[i] +
- 					      IOMMU_REGISTER_INT_RAWSTAT);
- 
- 			if (rawstat & IOMMU_INTERRUPT_PAGE_FAULT) {
- 				fault_address = __raw_readl(data->res_bases[i] +
- 				IOMMU_REGISTER_PAGE_FAULT_ADDR);
- 				itype = IOMMU_PAGEFAULT;
- 			} else if (rawstat & IOMMU_INTERRUPT_READ_BUS_ERROR) {
- 				itype = IOMMU_BUSERROR;
- 			} else {
- 				goto out;
- 			}
- 			dump_pagetbl(fault_address,
- 				     __raw_readl(data->res_bases[i] +
- 				     IOMMU_REGISTER_DTE_ADDR));
- 		} else {
- 			goto out;
+ 		if (rawstat & IOMMU_INTERRUPT_READ_BUS_ERROR) {
+ 			dev_err(data->iommu, "bus error occured at %pad\n",
+ 				&fault_address);
  		}
- 	}
  
- 	if (data->fault_handler) {
- 		unsigned long base = __raw_readl(data->res_bases[i] +
- 						 IOMMU_REGISTER_DTE_ADDR);
+ 		if (rawstat & ~(IOMMU_INTERRUPT_READ_BUS_ERROR |
+ 		    IOMMU_INTERRUPT_PAGE_FAULT)) {
+ 	    		dev_err(data->iommu, "unexpected int_status: %#08x\n\n",
+ 	    			rawstat);
+ 		}
+ 
+ 		__raw_writel(rawstat, data->res_bases[i] +
+ 			     IOMMU_REGISTER_INT_CLEAR);
+ 
  		status = __raw_readl(data->res_bases[i] +
- 				     IOMMU_REGISTER_STATUS);
- 		ret = data->fault_handler(data->dev, itype, base,
- 					  fault_address, status);
- 	}
+ 				     IOMMU_REGISTER_INT_STATUS);
  
- 	if (!ret && (itype != IOMMU_FAULT_UNKNOWN)) {
- 		if (IOMMU_PAGEFAULT == itype) {
- 			iommu_zap_tlb(data->res_bases[i]);
- 			iommu_page_fault_done(data->res_bases[i],
- 					       data->dbgname);
- 			__raw_writel(IOMMU_INTERRUPT_PAGE_FAULT |
- 				     IOMMU_INTERRUPT_READ_BUS_ERROR,
- 				     data->res_bases[i] +
- 				     IOMMU_REGISTER_INT_MASK);
- 		}
- 	} else {
- 		dev_err(data->iommu,"(%s) %s is not handled.\n",
- 		       data->dbgname, iommu_fault_name[itype]);
- 	}
+ 		rawstat = __raw_readl(data->res_bases[i] +
+ 				      IOMMU_REGISTER_INT_RAWSTAT);
+ 
+ 		reg_status = __raw_readl(data->res_bases[i] +
+ 				      	 IOMMU_REGISTER_STATUS);
  
- out:
- 	read_unlock(&data->lock);
+ 		dev_info(data->iommu, "2.rawstat = 0x%08x,status = 0x%08x,reg_status = 0x%08x\n",
+ 			 rawstat, status, reg_status);
  
+ 		ret = rockchip_iommu_zap_tlb_without_stall(data->res_bases[i]);
+ 		if (ret)
+ 			dev_err(data->iommu, "(%s) %s failed\n", data->dbgname,
+ 				__func__);
+ 	}
+ 
+ 	spin_unlock_irqrestore(&data->data_lock, flags);
  	return IRQ_HANDLED;
  }
  
diff --cc drivers/staging/android/trace/ion.h
index 47af2919cb39,2dcc34cf2a81..67bf9d322d46
--- a/drivers/staging/android/trace/ion.h
+++ b/drivers/staging/android/trace/ion.h
@@@ -143,10 -143,41 +143,41 @@@ DECLARE_EVENT_CLASS(ion_kmap_op
  		  __get_str(client), __entry->buf, __entry->size, __entry->kaddr)
  );
  DEFINE_EVENT(ion_kmap_op, ion_kernel_map,
 -	TP_PROTO(const char* client, unsigned int buffer, unsigned int size, unsigned int kaddr),
 +	TP_PROTO(const char* client, void* buffer, unsigned int size, void* kaddr),
  	TP_ARGS(client, buffer, size, kaddr));
  
+ DECLARE_EVENT_CLASS(ion_mmap_op,
+ 	TP_PROTO(const char* client, unsigned int buf, unsigned int size,
+ 		unsigned long vm_start, unsigned long vm_end),
+ 	TP_ARGS(client, buf, size, vm_start, vm_end),
+ 	TP_STRUCT__entry(
+ 		__string(client, client)
+ 		__field(unsigned int, buf)
+ 		__field(unsigned int, size)
+ 		__field(unsigned long, vm_start)
+ 		__field(unsigned long, vm_end)
+ 	),
+ 	TP_fast_assign(
+ 		__assign_str(client, client);
+ 		__entry->buf = buf;
+ 		__entry->size = size;
+ 		__entry->vm_start = vm_start;
+ 		__entry->vm_end = vm_end;
+ 	),
+ 	TP_printk("client=%s,buffer=%08x:%d,vma[%08lx:%08lx]",
+ 		  __get_str(client), __entry->buf, __entry->size,
+ 		  __entry->vm_start, __entry->vm_end)
+ );
+ 
+ DEFINE_EVENT(ion_mmap_op, ion_buffer_mmap,
+ 	TP_PROTO(const char* client, unsigned int buf, unsigned int size,
+ 		unsigned long vm_start, unsigned long vm_end),
+ 	TP_ARGS(client, buf, size, vm_start, vm_end));
  
+ DEFINE_EVENT(ion_mmap_op, ion_buffer_munmap,
+ 	TP_PROTO(const char* client, unsigned int buf, unsigned int size,
+ 		unsigned long vm_start, unsigned long vm_end),
+ 	TP_ARGS(client, buf, size, vm_start, vm_end));
  
  #endif /* _TRACE_ION_H */