/* Push a new buffer object onto the list */
static void push_object(int type,
	struct kgsl_process_private *process,
	uint64_t gpuaddr, uint64_t dwords)
{
	int index;
	struct kgsl_mem_entry *entry;

	if (process == NULL)
		return;

	/*
	 * Sometimes IBs can be reused in the same dump.  Because we parse from
	 * oldest to newest, if we come across an IB that has already been used,
	 * assume that it has been reused and update the list with the newest
	 * size.
	 */

	for (index = 0; index < objbufptr; index++) {
		if (objbuf[index].gpuaddr == gpuaddr &&
			objbuf[index].entry->priv == process) {

			objbuf[index].size = max_t(uint64_t,
						objbuf[index].size,
						dwords << 2);
			return;
		}
	}

	if (objbufptr == SNAPSHOT_OBJ_BUFSIZE) {
		KGSL_CORE_ERR("snapshot: too many snapshot objects\n");
		return;
	}

	entry = kgsl_sharedmem_find(process, gpuaddr);
	if (entry == NULL) {
		KGSL_CORE_ERR("snapshot: Can't find entry for 0x%016llX\n",
			gpuaddr);
		return;
	}

	if (!kgsl_gpuaddr_in_memdesc(&entry->memdesc, gpuaddr, dwords << 2)) {
		KGSL_CORE_ERR("snapshot: Mem entry 0x%016llX is too small\n",
			gpuaddr);
		kgsl_mem_entry_put(entry);
		return;
	}

	/* Put it on the list of things to parse */
	objbuf[objbufptr].type = type;
	objbuf[objbufptr].gpuaddr = gpuaddr;
	objbuf[objbufptr].size = dwords << 2;
	objbuf[objbufptr++].entry = entry;
}
static void z180_dump_ib(struct kgsl_device *device)
{
	unsigned int rb_size;
	unsigned int *rb_hostptr;
	unsigned int rb_words;
	unsigned int rb_gpuaddr;
	unsigned int ib_gpuptr = 0;
	unsigned int ib_size = 0;
	void *ib_hostptr = NULL;
	int rb_slot_num = -1;
	struct z180_device *z180_dev = Z180_DEVICE(device);
	struct kgsl_mem_entry *entry = NULL;
	phys_addr_t pt_base;
	unsigned int i;
	unsigned int j;
	char linebuf[CHARS_PER_LINE];
	unsigned int current_ib_slot;
	unsigned int len;
	unsigned int rowsize;
	KGSL_LOG_DUMP(device, "Z180 IB dump\n");

	rb_hostptr = (unsigned int *) z180_dev->ringbuffer.cmdbufdesc.hostptr;

	rb_size = Z180_RB_SIZE;
	rb_gpuaddr = z180_dev->ringbuffer.cmdbufdesc.gpuaddr;

	rb_words = rb_size/sizeof(unsigned int);

	KGSL_LOG_DUMP(device, "Ringbuffer size (bytes): %u\n", rb_size);

	KGSL_LOG_DUMP(device, "rb_words: %d\n", rb_words);

	pt_base = kgsl_mmu_get_current_ptbase(&device->mmu);

	
	for (i = 0; i < rb_words; i++) {
		if (rb_hostptr[i] == Z180_STREAM_PACKET_CALL) {

			rb_slot_num++;
			current_ib_slot =
				z180_dev->current_timestamp % Z180_PACKET_COUNT;
			if (rb_slot_num != current_ib_slot)
				continue;

			ib_gpuptr = rb_hostptr[i+1];

			entry = kgsl_get_mem_entry(device, pt_base, ib_gpuptr,
							1);

			if (entry == NULL) {
				KGSL_LOG_DUMP(device,
				"IB mem entry not found for ringbuffer slot#: %d\n",
				rb_slot_num);
				continue;
			}

			ib_hostptr = kgsl_memdesc_map(&entry->memdesc);

			if (ib_hostptr == NULL) {
				KGSL_LOG_DUMP(device,
				"Could not map IB to kernel memory, Ringbuffer Slot: %d\n",
				rb_slot_num);
				kgsl_mem_entry_put(entry);
				continue;
			}

			ib_size = entry->memdesc.size;
			KGSL_LOG_DUMP(device,
				"IB size: %dbytes, IB size in words: %d\n",
				ib_size,
				ib_size/sizeof(unsigned int));

			for (j = 0; j < ib_size; j += WORDS_PER_LINE) {
				len = ib_size - j*sizeof(unsigned int);
				rowsize = WORDS_PER_LINE*sizeof(unsigned int);
				hex_dump_to_buffer(ib_hostptr+j, len, rowsize,
						sizeof(unsigned int), linebuf,
						sizeof(linebuf), false);
				KGSL_LOG_DUMP(device, "IB%d: %04X: %s\n",
						rb_slot_num,
						(rb_gpuaddr +
						j*sizeof(unsigned int)),
						linebuf);
			}
			KGSL_LOG_DUMP(device, "IB Dump Finished\n");
			kgsl_mem_entry_put(entry);
		}
	}
}