int kgsl_ringbuffer_init(struct kgsl_device *device) { int status; uint32_t flags; struct kgsl_ringbuffer *rb = &device->ringbuffer; KGSL_CMD_VDBG("enter (device=%p)\n", device); rb->device = device; rb->sizedwords = (2 << kgsl_cfg_rb_sizelog2quadwords); rb->blksizequadwords = kgsl_cfg_rb_blksizequadwords; /* allocate memory for ringbuffer, needs to be double octword aligned * align on page from contiguous physical memory */ flags = (KGSL_MEMFLAGS_ALIGNPAGE | KGSL_MEMFLAGS_CONPHYS | KGSL_MEMFLAGS_STRICTREQUEST); status = kgsl_sharedmem_alloc(flags, (rb->sizedwords << 2), &rb->buffer_desc); if (status != 0) { kgsl_ringbuffer_close(rb); KGSL_CMD_VDBG("return %d\n", status); return status; } /* allocate memory for polling and timestamps */ /* This really can be at 4 byte alignment boundry but for using MMU * we need to make it at page boundary */ flags = (KGSL_MEMFLAGS_ALIGNPAGE | KGSL_MEMFLAGS_CONPHYS); status = kgsl_sharedmem_alloc(flags, sizeof(struct kgsl_rbmemptrs), &rb->memptrs_desc); if (status != 0) { kgsl_ringbuffer_close(rb); KGSL_CMD_VDBG("return %d\n", status); return status; } /* last allocation of init process is made here so map all * allocations to MMU */ status = kgsl_yamato_setup_pt(device, device->mmu.defaultpagetable); if (status != 0) { kgsl_ringbuffer_close(rb); KGSL_CMD_VDBG("return %d\n", status); return status; } /* overlay structure on memptrs memory */ rb->memptrs = (struct kgsl_rbmemptrs *) rb->memptrs_desc.hostptr; rb->flags |= KGSL_FLAGS_INITIALIZED; KGSL_CMD_VDBG("return %d\n", 0); return 0; }
int kgsl_g12_cmdstream_init(struct kgsl_device *device) { struct kgsl_g12_device *g12_device = (struct kgsl_g12_device *) device; memset(&g12_device->ringbuffer, 0, sizeof(struct kgsl_g12_ringbuffer)); g12_device->ringbuffer.prevctx = KGSL_G12_INVALID_CONTEXT; return kgsl_sharedmem_alloc(0, KGSL_G12_RB_SIZE, &g12_device->ringbuffer.cmdbufdesc); }
int kgsl_g12_drawctxt_create(struct kgsl_device_private *dev_priv, uint32_t unused, unsigned int *drawctxt_id) { int cmd; int result; unsigned int ctx_id; struct kgsl_device *device = dev_priv->device; if (g_z1xx.numcontext == 0) { if (kgsl_sharedmem_alloc(0, KGSL_G12_RB_SIZE, &g_z1xx.cmdbufdesc) != 0) return -ENOMEM; cmd = (int)(((VGV3_NEXTCMD_JUMP) & VGV3_NEXTCMD_NEXTCMD_FMASK) << VGV3_NEXTCMD_NEXTCMD_FSHIFT); result = kgsl_g12_cmdwindow_write(device, KGSL_CMDWINDOW_2D, ADDR_VGV3_MODE, 4); if (result != 0) return result; result = kgsl_g12_cmdwindow_write(device, KGSL_CMDWINDOW_2D, ADDR_VGV3_NEXTADDR, g_z1xx.cmdbufdesc.physaddr); if (result != 0) return result; result = kgsl_g12_cmdwindow_write(device, KGSL_CMDWINDOW_2D, ADDR_VGV3_NEXTCMD, cmd | 5); if (result != 0) return result; result = kgsl_g12_cmdwindow_write(device, KGSL_CMDWINDOW_2D, ADDR_VGV3_CONTROL, 0); if (result != 0) return result; } ctx_id = ffz(dev_priv->ctxt_id_mask); g_z1xx.numcontext++; if (g_z1xx.numcontext > KGSL_G12_CONTEXT_MAX) { *drawctxt_id = 0; return KGSL_FAILURE; } *drawctxt_id = ctx_id; return KGSL_SUCCESS; }
int kgsl_ringbuffer_init(struct kgsl_device *device) { int status; uint32_t flags; struct kgsl_ringbuffer *rb = &device->ringbuffer; KGSL_CMD_VDBG("enter (device=%p)\n", device); rb->device = device; rb->sizedwords = (2 << kgsl_cfg_rb_sizelog2quadwords); rb->blksizequadwords = kgsl_cfg_rb_blksizequadwords; flags = (KGSL_MEMFLAGS_ALIGNPAGE | KGSL_MEMFLAGS_CONPHYS | KGSL_MEMFLAGS_STRICTREQUEST); status = kgsl_sharedmem_alloc(flags, (rb->sizedwords << 2), &rb->buffer_desc); if (status != 0) { kgsl_ringbuffer_close(rb); KGSL_CMD_VDBG("return %d\n", status); return status; } flags = (KGSL_MEMFLAGS_ALIGNPAGE | KGSL_MEMFLAGS_CONPHYS); status = kgsl_sharedmem_alloc(flags, sizeof(struct kgsl_rbmemptrs), &rb->memptrs_desc); if (status != 0) { kgsl_ringbuffer_close(rb); KGSL_CMD_VDBG("return %d\n", status); return status; } status = kgsl_yamato_setup_pt(device, device->mmu.defaultpagetable); if (status != 0) { kgsl_ringbuffer_close(rb); KGSL_CMD_VDBG("return %d\n", status); return status; } rb->memptrs = (struct kgsl_rbmemptrs *) rb->memptrs_desc.hostptr; rb->flags |= KGSL_FLAGS_INITIALIZED; status = kgsl_ringbuffer_start(rb); if (status != 0) { kgsl_ringbuffer_close(rb); KGSL_CMD_VDBG("return %d\n", status); return status; } KGSL_CMD_VDBG("return %d\n", 0); return 0; }
static long gsl_kmod_ioctl(struct file *fd, unsigned int cmd, unsigned long arg) { int kgslStatus = GSL_FAILURE; switch (cmd) { case IOCTL_KGSL_DEVICE_START: { kgsl_device_start_t param; if (copy_from_user(¶m, (void __user *)arg, sizeof(kgsl_device_start_t))) { printk(KERN_ERR "%s: copy_from_user error\n", __func__); kgslStatus = GSL_FAILURE; break; } kgslStatus = kgsl_device_start(param.device_id, param.flags); break; } case IOCTL_KGSL_DEVICE_STOP: { kgsl_device_stop_t param; if (copy_from_user(¶m, (void __user *)arg, sizeof(kgsl_device_stop_t))) { printk(KERN_ERR "%s: copy_from_user error\n", __func__); kgslStatus = GSL_FAILURE; break; } kgslStatus = kgsl_device_stop(param.device_id); break; } case IOCTL_KGSL_DEVICE_IDLE: { kgsl_device_idle_t param; if (copy_from_user(¶m, (void __user *)arg, sizeof(kgsl_device_idle_t))) { printk(KERN_ERR "%s: copy_from_user error\n", __func__); kgslStatus = GSL_FAILURE; break; } kgslStatus = kgsl_device_idle(param.device_id, param.timeout); break; } case IOCTL_KGSL_DEVICE_ISIDLE: { kgsl_device_isidle_t param; if (copy_from_user(¶m, (void __user *)arg, sizeof(kgsl_device_isidle_t))) { printk(KERN_ERR "%s: copy_from_user error\n", __func__); kgslStatus = GSL_FAILURE; break; } kgslStatus = kgsl_device_isidle(param.device_id); break; } case IOCTL_KGSL_DEVICE_GETPROPERTY: { kgsl_device_getproperty_t param; void *tmp; if (copy_from_user(¶m, (void __user *)arg, sizeof(kgsl_device_getproperty_t))) { printk(KERN_ERR "%s: copy_from_user error\n", __func__); kgslStatus = GSL_FAILURE; break; } tmp = kmalloc(param.sizebytes, GFP_KERNEL); if (!tmp) { printk(KERN_ERR "%s:kmalloc error\n", __func__); kgslStatus = GSL_FAILURE; break; } kgslStatus = kgsl_device_getproperty(param.device_id, param.type, tmp, param.sizebytes); if (kgslStatus == GSL_SUCCESS) { if (copy_to_user(param.value, tmp, param.sizebytes)) { printk(KERN_ERR "%s: copy_to_user error\n", __func__); kgslStatus = GSL_FAILURE; kfree(tmp); break; } } else { printk(KERN_ERR "%s: kgsl_device_getproperty error\n", __func__); } kfree(tmp); break; } case IOCTL_KGSL_DEVICE_SETPROPERTY: { kgsl_device_setproperty_t param; if (copy_from_user(¶m, (void __user *)arg, sizeof(kgsl_device_setproperty_t))) { printk(KERN_ERR "%s: copy_from_user error\n", __func__); kgslStatus = GSL_FAILURE; break; } kgslStatus = kgsl_device_setproperty(param.device_id, param.type, param.value, param.sizebytes); if (kgslStatus != GSL_SUCCESS) { printk(KERN_ERR "%s: kgsl_device_setproperty error\n", __func__); } break; } case IOCTL_KGSL_DEVICE_REGREAD: { kgsl_device_regread_t param; unsigned int tmp; if (copy_from_user(¶m, (void __user *)arg, sizeof(kgsl_device_regread_t))) { printk(KERN_ERR "%s: copy_from_user error\n", __func__); kgslStatus = GSL_FAILURE; break; } kgslStatus = kgsl_device_regread(param.device_id, param.offsetwords, &tmp); if (kgslStatus == GSL_SUCCESS) { if (copy_to_user(param.value, &tmp, sizeof(unsigned int))) { printk(KERN_ERR "%s: copy_to_user error\n", __func__); kgslStatus = GSL_FAILURE; break; } } break; } case IOCTL_KGSL_DEVICE_REGWRITE: { kgsl_device_regwrite_t param; if (copy_from_user(¶m, (void __user *)arg, sizeof(kgsl_device_regwrite_t))) { printk(KERN_ERR "%s: copy_from_user error\n", __func__); kgslStatus = GSL_FAILURE; break; } kgslStatus = kgsl_device_regwrite(param.device_id, param.offsetwords, param.value); break; } case IOCTL_KGSL_DEVICE_WAITIRQ: { kgsl_device_waitirq_t param; unsigned int count; printk(KERN_ERR "IOCTL_KGSL_DEVICE_WAITIRQ obsoleted!\n"); // kgslStatus = -ENOTTY; break; if (copy_from_user(¶m, (void __user *)arg, sizeof(kgsl_device_waitirq_t))) { printk(KERN_ERR "%s: copy_from_user error\n", __func__); kgslStatus = GSL_FAILURE; break; } kgslStatus = kgsl_device_waitirq(param.device_id, param.intr_id, &count, param.timeout); if (kgslStatus == GSL_SUCCESS) { if (copy_to_user(param.count, &count, sizeof(unsigned int))) { printk(KERN_ERR "%s: copy_to_user error\n", __func__); kgslStatus = GSL_FAILURE; break; } } break; } case IOCTL_KGSL_CMDSTREAM_ISSUEIBCMDS: { kgsl_cmdstream_issueibcmds_t param; gsl_timestamp_t tmp; if (copy_from_user(¶m, (void __user *)arg, sizeof(kgsl_cmdstream_issueibcmds_t))) { printk(KERN_ERR "%s: copy_from_user error\n", __func__); kgslStatus = GSL_FAILURE; break; } kgslStatus = kgsl_cmdstream_issueibcmds(param.device_id, param.drawctxt_index, param.ibaddr, param.sizedwords, &tmp, param.flags); if (kgslStatus == GSL_SUCCESS) { if (copy_to_user(param.timestamp, &tmp, sizeof(gsl_timestamp_t))) { printk(KERN_ERR "%s: copy_to_user error\n", __func__); kgslStatus = GSL_FAILURE; break; } } break; } case IOCTL_KGSL_CMDSTREAM_READTIMESTAMP: { kgsl_cmdstream_readtimestamp_t param; gsl_timestamp_t tmp; if (copy_from_user(¶m, (void __user *)arg, sizeof(kgsl_cmdstream_readtimestamp_t))) { printk(KERN_ERR "%s: copy_from_user error\n", __func__); kgslStatus = GSL_FAILURE; break; } tmp = kgsl_cmdstream_readtimestamp(param.device_id, param.type); if (copy_to_user(param.timestamp, &tmp, sizeof(gsl_timestamp_t))) { printk(KERN_ERR "%s: copy_to_user error\n", __func__); kgslStatus = GSL_FAILURE; break; } kgslStatus = GSL_SUCCESS; break; } case IOCTL_KGSL_CMDSTREAM_FREEMEMONTIMESTAMP: { int err; kgsl_cmdstream_freememontimestamp_t param; if (copy_from_user(¶m, (void __user *)arg, sizeof(kgsl_cmdstream_freememontimestamp_t))) { printk(KERN_ERR "%s: copy_from_user error\n", __func__); kgslStatus = GSL_FAILURE; break; } err = del_memblock_from_allocated_list(fd, param.memdesc); if(err) { /* tried to remove a block of memory that is not allocated! * NOTE that -EINVAL is Linux kernel's error codes! * the drivers error codes COULD mix up with kernel's. */ kgslStatus = -EINVAL; } else { kgslStatus = kgsl_cmdstream_freememontimestamp(param.device_id, param.memdesc, param.timestamp, param.type); } break; } case IOCTL_KGSL_CMDSTREAM_WAITTIMESTAMP: { kgsl_cmdstream_waittimestamp_t param; if (copy_from_user(¶m, (void __user *)arg, sizeof(kgsl_cmdstream_waittimestamp_t))) { printk(KERN_ERR "%s: copy_from_user error\n", __func__); kgslStatus = GSL_FAILURE; break; } kgslStatus = kgsl_cmdstream_waittimestamp(param.device_id, param.timestamp, param.timeout); break; } case IOCTL_KGSL_CMDWINDOW_WRITE: { kgsl_cmdwindow_write_t param; if (copy_from_user(¶m, (void __user *)arg, sizeof(kgsl_cmdwindow_write_t))) { printk(KERN_ERR "%s: copy_from_user error\n", __func__); kgslStatus = GSL_FAILURE; break; } kgslStatus = kgsl_cmdwindow_write(param.device_id, param.target, param.addr, param.data); break; } case IOCTL_KGSL_CONTEXT_CREATE: { kgsl_context_create_t param; unsigned int tmp; int tmpStatus; if (copy_from_user(¶m, (void __user *)arg, sizeof(kgsl_context_create_t))) { printk(KERN_ERR "%s: copy_from_user error\n", __func__); kgslStatus = GSL_FAILURE; break; } kgslStatus = kgsl_context_create(param.device_id, param.type, &tmp, param.flags); if (kgslStatus == GSL_SUCCESS) { if (copy_to_user(param.drawctxt_id, &tmp, sizeof(unsigned int))) { tmpStatus = kgsl_context_destroy(param.device_id, tmp); /* is asserting ok? Basicly we should return the error from copy_to_user * but will the user space interpret it correctly? Will the user space * always check against GSL_SUCCESS or GSL_FAILURE as they are not the only * return values. */ KOS_ASSERT(tmpStatus == GSL_SUCCESS); printk(KERN_ERR "%s: copy_to_user error\n", __func__); kgslStatus = GSL_FAILURE; break; } else { add_device_context_to_array(fd, param.device_id, tmp); } } break; } case IOCTL_KGSL_CONTEXT_DESTROY: { kgsl_context_destroy_t param; if (copy_from_user(¶m, (void __user *)arg, sizeof(kgsl_context_destroy_t))) { printk(KERN_ERR "%s: copy_from_user error\n", __func__); kgslStatus = GSL_FAILURE; break; } kgslStatus = kgsl_context_destroy(param.device_id, param.drawctxt_id); del_device_context_from_array(fd, param.device_id, param.drawctxt_id); break; } case IOCTL_KGSL_DRAWCTXT_BIND_GMEM_SHADOW: { kgsl_drawctxt_bind_gmem_shadow_t param; if (copy_from_user(¶m, (void __user *)arg, sizeof(kgsl_drawctxt_bind_gmem_shadow_t))) { printk(KERN_ERR "%s: copy_from_user error\n", __func__); kgslStatus = GSL_FAILURE; break; } kgslStatus = kgsl_drawctxt_bind_gmem_shadow(param.device_id, param.drawctxt_id, param.gmem_rect, param.shadow_x, param.shadow_y, param.shadow_buffer, param.buffer_id); break; } case IOCTL_KGSL_SHAREDMEM_ALLOC: { kgsl_sharedmem_alloc_t param; gsl_memdesc_t tmp; int tmpStatus; if (copy_from_user(¶m, (void __user *)arg, sizeof(kgsl_sharedmem_alloc_t))) { printk(KERN_ERR "%s: copy_from_user error\n", __func__); kgslStatus = GSL_FAILURE; break; } kgslStatus = kgsl_sharedmem_alloc(param.device_id, param.flags, param.sizebytes, &tmp); if (kgslStatus == GSL_SUCCESS) { if (copy_to_user(param.memdesc, &tmp, sizeof(gsl_memdesc_t))) { tmpStatus = kgsl_sharedmem_free(&tmp); KOS_ASSERT(tmpStatus == GSL_SUCCESS); printk(KERN_ERR "%s: copy_to_user error\n", __func__); kgslStatus = GSL_FAILURE; break; } else { add_memblock_to_allocated_list(fd, &tmp); } } break; } case IOCTL_KGSL_SHAREDMEM_FREE: { kgsl_sharedmem_free_t param; gsl_memdesc_t tmp; int err; if (copy_from_user(¶m, (void __user *)arg, sizeof(kgsl_sharedmem_free_t))) { printk(KERN_ERR "%s: copy_from_user error\n", __func__); kgslStatus = GSL_FAILURE; break; } if (copy_from_user(&tmp, (void __user *)param.memdesc, sizeof(gsl_memdesc_t))) { printk(KERN_ERR "%s: copy_from_user error\n", __func__); kgslStatus = GSL_FAILURE; break; } err = del_memblock_from_allocated_list(fd, &tmp); if(err) { printk(KERN_ERR "%s: tried to free memdesc that was not allocated!\n", __func__); kgslStatus = err; break; } kgslStatus = kgsl_sharedmem_free(&tmp); if (kgslStatus == GSL_SUCCESS) { if (copy_to_user(param.memdesc, &tmp, sizeof(gsl_memdesc_t))) { printk(KERN_ERR "%s: copy_to_user error\n", __func__); kgslStatus = GSL_FAILURE; break; } } break; } case IOCTL_KGSL_SHAREDMEM_READ: { kgsl_sharedmem_read_t param; gsl_memdesc_t memdesc; if (copy_from_user(¶m, (void __user *)arg, sizeof(kgsl_sharedmem_read_t))) { printk(KERN_ERR "%s: copy_from_user error\n", __func__); kgslStatus = GSL_FAILURE; break; } if (copy_from_user(&memdesc, (void __user *)param.memdesc, sizeof(gsl_memdesc_t))) { printk(KERN_ERR "%s: copy_from_user error\n", __func__); kgslStatus = GSL_FAILURE; break; } kgslStatus = kgsl_sharedmem_read(&memdesc, param.dst, param.offsetbytes, param.sizebytes, true); if (kgslStatus != GSL_SUCCESS) { printk(KERN_ERR "%s: kgsl_sharedmem_read failed\n", __func__); } break; } case IOCTL_KGSL_SHAREDMEM_WRITE: { kgsl_sharedmem_write_t param; gsl_memdesc_t memdesc; if (copy_from_user(¶m, (void __user *)arg, sizeof(kgsl_sharedmem_write_t))) { printk(KERN_ERR "%s: copy_from_user error\n", __func__); kgslStatus = GSL_FAILURE; break; } if (copy_from_user(&memdesc, (void __user *)param.memdesc, sizeof(gsl_memdesc_t))) { printk(KERN_ERR "%s: copy_from_user error\n", __func__); kgslStatus = GSL_FAILURE; break; } kgslStatus = kgsl_sharedmem_write(&memdesc, param.offsetbytes, param.src, param.sizebytes, true); if (kgslStatus != GSL_SUCCESS) { printk(KERN_ERR "%s: kgsl_sharedmem_write failed\n", __func__); } break; } case IOCTL_KGSL_SHAREDMEM_SET: { kgsl_sharedmem_set_t param; gsl_memdesc_t memdesc; if (copy_from_user(¶m, (void __user *)arg, sizeof(kgsl_sharedmem_set_t))) { printk(KERN_ERR "%s: copy_from_user error\n", __func__); kgslStatus = GSL_FAILURE; break; } if (copy_from_user(&memdesc, (void __user *)param.memdesc, sizeof(gsl_memdesc_t))) { printk(KERN_ERR "%s: copy_from_user error\n", __func__); kgslStatus = GSL_FAILURE; break; } kgslStatus = kgsl_sharedmem_set(&memdesc, param.offsetbytes, param.value, param.sizebytes); break; } case IOCTL_KGSL_SHAREDMEM_LARGESTFREEBLOCK: { kgsl_sharedmem_largestfreeblock_t param; unsigned int largestfreeblock; if (copy_from_user(¶m, (void __user *)arg, sizeof(kgsl_sharedmem_largestfreeblock_t))) { printk(KERN_ERR "%s: copy_from_user error\n", __func__); kgslStatus = GSL_FAILURE; break; } largestfreeblock = kgsl_sharedmem_largestfreeblock(param.device_id, param.flags); if (copy_to_user(param.largestfreeblock, &largestfreeblock, sizeof(unsigned int))) { printk(KERN_ERR "%s: copy_to_user error\n", __func__); kgslStatus = GSL_FAILURE; break; } kgslStatus = GSL_SUCCESS; break; } case IOCTL_KGSL_SHAREDMEM_CACHEOPERATION: { kgsl_sharedmem_cacheoperation_t param; gsl_memdesc_t memdesc; if (copy_from_user(¶m, (void __user *)arg, sizeof(kgsl_sharedmem_cacheoperation_t))) { printk(KERN_ERR "%s: copy_from_user error\n", __func__); kgslStatus = GSL_FAILURE; break; } if (copy_from_user(&memdesc, (void __user *)param.memdesc, sizeof(gsl_memdesc_t))) { printk(KERN_ERR "%s: copy_from_user error\n", __func__); kgslStatus = GSL_FAILURE; break; } kgslStatus = kgsl_sharedmem_cacheoperation(&memdesc, param.offsetbytes, param.sizebytes, param.operation); break; } case IOCTL_KGSL_SHAREDMEM_FROMHOSTPOINTER: { kgsl_sharedmem_fromhostpointer_t param; gsl_memdesc_t memdesc; if (copy_from_user(¶m, (void __user *)arg, sizeof(kgsl_sharedmem_fromhostpointer_t))) { printk(KERN_ERR "%s: copy_from_user error\n", __func__); kgslStatus = GSL_FAILURE; break; } if (copy_from_user(&memdesc, (void __user *)param.memdesc, sizeof(gsl_memdesc_t))) { printk(KERN_ERR "%s: copy_from_user error\n", __func__); kgslStatus = GSL_FAILURE; break; } kgslStatus = kgsl_sharedmem_fromhostpointer(param.device_id, &memdesc, param.hostptr); break; } case IOCTL_KGSL_ADD_TIMESTAMP: { kgsl_add_timestamp_t param; gsl_timestamp_t tmp; if (copy_from_user(¶m, (void __user *)arg, sizeof(kgsl_add_timestamp_t))) { printk(KERN_ERR "%s: copy_from_user error\n", __func__); kgslStatus = GSL_FAILURE; break; } tmp = kgsl_add_timestamp(param.device_id, &tmp); if (copy_to_user(param.timestamp, &tmp, sizeof(gsl_timestamp_t))) { printk(KERN_ERR "%s: copy_to_user error\n", __func__); kgslStatus = GSL_FAILURE; break; } kgslStatus = GSL_SUCCESS; break; } case IOCTL_KGSL_DEVICE_CLOCK: { kgsl_device_clock_t param; if (copy_from_user(¶m, (void __user *)arg, sizeof(kgsl_device_clock_t))) { printk(KERN_ERR "%s: copy_from_user error\n", __func__); kgslStatus = GSL_FAILURE; break; } kgslStatus = kgsl_device_clock(param.device, param.enable); break; } default: kgslStatus = -ENOTTY; break; } return kgslStatus; }
int kgsl_mmu_init(struct kgsl_device *device) { /* * intialize device mmu * * call this with the global lock held */ int status; uint32_t flags; struct kgsl_mmu *mmu = &device->mmu; #ifdef _DEBUG struct kgsl_mmu_debug regs; #endif /* _DEBUG */ KGSL_MEM_VDBG("enter (device=%p)\n", device); if (mmu->flags & KGSL_FLAGS_INITIALIZED0) { KGSL_MEM_INFO("MMU already initialized.\n"); return 0; } mmu->device = device; #ifndef CONFIG_MSM_KGSL_MMU mmu->config = 0x00000000; #endif /* setup MMU and sub-client behavior */ kgsl_yamato_regwrite(device, REG_MH_MMU_CONFIG, mmu->config); /* enable axi interrupts */ KGSL_MEM_DBG("enabling mmu interrupts mask=0x%08lx\n", GSL_MMU_INT_MASK); kgsl_yamato_regwrite(device, REG_MH_INTERRUPT_MASK, GSL_MMU_INT_MASK); mmu->flags |= KGSL_FLAGS_INITIALIZED0; /* MMU not enabled */ if ((mmu->config & 0x1) == 0) { KGSL_MEM_VDBG("return %d\n", 0); return 0; } /* idle device */ kgsl_yamato_idle(device, KGSL_TIMEOUT_DEFAULT); /* make sure aligned to pagesize */ BUG_ON(mmu->mpu_base & (KGSL_PAGESIZE - 1)); BUG_ON((mmu->mpu_base + mmu->mpu_range) & (KGSL_PAGESIZE - 1)); /* define physical memory range accessible by the core */ kgsl_yamato_regwrite(device, REG_MH_MMU_MPU_BASE, mmu->mpu_base); kgsl_yamato_regwrite(device, REG_MH_MMU_MPU_END, mmu->mpu_base + mmu->mpu_range); /* enable axi interrupts */ KGSL_MEM_DBG("enabling mmu interrupts mask=0x%08lx\n", GSL_MMU_INT_MASK | MH_INTERRUPT_MASK__MMU_PAGE_FAULT); kgsl_yamato_regwrite(device, REG_MH_INTERRUPT_MASK, GSL_MMU_INT_MASK | MH_INTERRUPT_MASK__MMU_PAGE_FAULT); mmu->flags |= KGSL_FLAGS_INITIALIZED; /* sub-client MMU lookups require address translation */ if ((mmu->config & ~0x1) > 0) { /*make sure virtual address range is a multiple of 64Kb */ BUG_ON(mmu->va_range & ((1 << 16) - 1)); /* allocate memory used for completing r/w operations that * cannot be mapped by the MMU */ flags = (KGSL_MEMFLAGS_ALIGN4K | KGSL_MEMFLAGS_CONPHYS | KGSL_MEMFLAGS_STRICTREQUEST); status = kgsl_sharedmem_alloc(flags, 64, &mmu->dummyspace); if (status != 0) { KGSL_MEM_ERR ("Unable to allocate dummy space memory.\n"); kgsl_mmu_close(device); return status; } kgsl_sharedmem_set(&mmu->dummyspace, 0, 0, mmu->dummyspace.size); /* TRAN_ERROR needs a 32 byte (32 byte aligned) chunk of memory * to complete transactions in case of an MMU fault. Note that * we'll leave the bottom 32 bytes of the dummyspace for other * purposes (e.g. use it when dummy read cycles are needed * for other blocks */ kgsl_yamato_regwrite(device, REG_MH_MMU_TRAN_ERROR, mmu->dummyspace.physaddr + 32); mmu->defaultpagetable = kgsl_mmu_createpagetableobject(mmu); if (!mmu->defaultpagetable) { KGSL_MEM_ERR("Failed to create global page table\n"); kgsl_mmu_close(device); return -ENOMEM; } mmu->hwpagetable = mmu->defaultpagetable; kgsl_yamato_regwrite(device, REG_MH_MMU_PT_BASE, mmu->hwpagetable->base.gpuaddr); kgsl_yamato_regwrite(device, REG_MH_MMU_VA_RANGE, (mmu->hwpagetable->va_base | (mmu->hwpagetable->va_range >> 16))); status = kgsl_yamato_setstate(device, KGSL_MMUFLAGS_TLBFLUSH); if (status) { kgsl_mmu_close(device); return status; } mmu->flags |= KGSL_FLAGS_STARTED; }
struct kgsl_pagetable *kgsl_mmu_createpagetableobject(struct kgsl_mmu *mmu) { int status = 0; struct kgsl_pagetable *pagetable = NULL; uint32_t flags; KGSL_MEM_VDBG("enter (mmu=%p)\n", mmu); pagetable = kzalloc(sizeof(struct kgsl_pagetable), GFP_KERNEL); if (pagetable == NULL) { KGSL_MEM_ERR("Unable to allocate pagetable object.\n"); return NULL; } pagetable->mmu = mmu; pagetable->va_base = mmu->va_base; pagetable->va_range = mmu->va_range; pagetable->last_superpte = 0; pagetable->max_entries = (mmu->va_range >> KGSL_PAGESIZE_SHIFT) + GSL_PT_EXTRA_ENTRIES; pagetable->pool = gen_pool_create(KGSL_PAGESIZE_SHIFT, -1); if (pagetable->pool == NULL) { KGSL_MEM_ERR("Unable to allocate virtualaddr pool.\n"); goto err_gen_pool_create; } if (gen_pool_add(pagetable->pool, pagetable->va_base, pagetable->va_range, -1)) { KGSL_MEM_ERR("gen_pool_create failed for pagetable %p\n", pagetable); goto err_gen_pool_add; } /* allocate page table memory */ flags = (KGSL_MEMFLAGS_ALIGN4K | KGSL_MEMFLAGS_CONPHYS | KGSL_MEMFLAGS_STRICTREQUEST); status = kgsl_sharedmem_alloc(flags, pagetable->max_entries * GSL_PTE_SIZE, &pagetable->base); if (status) { KGSL_MEM_ERR("cannot alloc page tables\n"); goto err_kgsl_sharedmem_alloc; } /* reset page table entries * -- all pte's are marked as not dirty initially */ kgsl_sharedmem_set(&pagetable->base, 0, 0, pagetable->base.size); pagetable->base.gpuaddr = pagetable->base.physaddr; KGSL_MEM_VDBG("return %p\n", pagetable); return pagetable; err_kgsl_sharedmem_alloc: err_gen_pool_add: gen_pool_destroy(pagetable->pool); err_gen_pool_create: kfree(pagetable); return NULL; }
int kgsl_g12_drawctxt_create(struct kgsl_device *device, uint32_t ctxt_id_mask, unsigned int *drawctxt_id) { int i; int cmd; int result; unsigned int ctx_id; if (g_z1xx.numcontext == 0) { for (i = 0; i < GSL_HAL_NUMCMDBUFFERS; i++) { int flags = 0; if (kgsl_sharedmem_alloc(flags, GSL_HAL_CMDBUFFERSIZE, &g_z1xx.cmdbufdesc[i]) != 0) return -ENOMEM; g_z1xx.cmdbuf[i] = kzalloc(GSL_HAL_CMDBUFFERSIZE, GFP_KERNEL); g_z1xx.curr = i; g_z1xx.offs = 0; addmarker(&g_z1xx); kgsl_sharedmem_write(&g_z1xx.cmdbufdesc[i], 0, g_z1xx.cmdbuf[i], (512 + 13) * sizeof(unsigned int)); } g_z1xx.curr = 0; cmd = (int)(((VGV3_NEXTCMD_JUMP) & VGV3_NEXTCMD_NEXTCMD_FMASK) << VGV3_NEXTCMD_NEXTCMD_FSHIFT); /* set cmd stream buffer to hw */ result = kgsl_g12_cmdwindow_write(device, KGSL_CMDWINDOW_2D, ADDR_VGV3_MODE, 4); if (result != 0) return result; result = kgsl_g12_cmdwindow_write(device, KGSL_CMDWINDOW_2D, ADDR_VGV3_NEXTADDR, g_z1xx.cmdbufdesc[0].physaddr); if (result != 0) return result; result = kgsl_g12_cmdwindow_write(device, KGSL_CMDWINDOW_2D, ADDR_VGV3_NEXTCMD, cmd | 5); if (result != 0) return result; cmd = (int)(((1) & VGV3_CONTROL_MARKADD_FMASK) << VGV3_CONTROL_MARKADD_FSHIFT); result = kgsl_g12_cmdwindow_write(device, KGSL_CMDWINDOW_2D, ADDR_VGV3_CONTROL, cmd); if (result != 0) return result; result = kgsl_g12_cmdwindow_write(device, KGSL_CMDWINDOW_2D, ADDR_VGV3_CONTROL, 0); if (result != 0) return result; } ctx_id = ffz(ctxt_id_mask); g_z1xx.numcontext++; if (g_z1xx.numcontext > KGSL_G12_CONTEXT_MAX) { *drawctxt_id = 0; return KGSL_FAILURE; } *drawctxt_id = ctx_id; return KGSL_SUCCESS; }