/*
 *
 * (C) COPYRIGHT 2013-2015,2017-2018 ARM Limited. All rights reserved.
 *
 * This program is free software and is provided to you under the terms of the
 * GNU General Public License version 2 as published by the Free Software
 * Foundation, and any use by you of this program is subject to the terms
 * of such GNU licence.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, you can access it online at
 * http://www.gnu.org/licenses/gpl-2.0.html.
 *
 * SPDX-License-Identifier: GPL-2.0
 *
 */
#include <linux/dma-mapping.h>
#include <mali_kbase.h>
#include <mali_kbase_10969_workaround.h>

/* Mask of X and Y coordinates for the coordinates words in the descriptors*/
#define X_COORDINATE_MASK 0x00000FFF
#define Y_COORDINATE_MASK 0x0FFF0000
/* Max number of words needed from the fragment shader job descriptor */
#define JOB_HEADER_SIZE_IN_WORDS 10
#define JOB_HEADER_SIZE (JOB_HEADER_SIZE_IN_WORDS*sizeof(u32))

/* Word 0: Status Word */
#define JOB_DESC_STATUS_WORD 0
/* Word 1: Restart Index */
#define JOB_DESC_RESTART_INDEX_WORD 1
/* Word 2: Fault address low word */
#define JOB_DESC_FAULT_ADDR_LOW_WORD 2
/* Word 8: Minimum Tile Coordinates */
#define FRAG_JOB_DESC_MIN_TILE_COORD_WORD 8
/* Word 9: Maximum Tile Coordinates */
#define FRAG_JOB_DESC_MAX_TILE_COORD_WORD 9

int kbasep_10969_workaround_clamp_coordinates(struct kbase_jd_atom *katom)
{
	struct device *dev = katom->kctx->kbdev->dev;
	u32   clamped = 0;
	struct kbase_va_region *region;
	struct tagged_addr *page_array;
	u64 page_index;
	u32 offset = katom->jc & (~PAGE_MASK);
	u32 *page_1 = NULL;
	u32 *page_2 = NULL;
	u32   job_header[JOB_HEADER_SIZE_IN_WORDS];
	void *dst = job_header;
	u32 minX, minY, maxX, maxY;
	u32 restartX, restartY;
	struct page *p;
	u32 copy_size;

	dev_warn(dev, "Called TILE_RANGE_FAULT workaround clamping function.\n");
	if (!(katom->core_req & BASE_JD_REQ_FS))
		return 0;

	kbase_gpu_vm_lock(katom->kctx);
	region = kbase_region_tracker_find_region_enclosing_address(katom->kctx,
			katom->jc);
	if (!region || (region->flags & KBASE_REG_FREE))
		goto out_unlock;

	page_array = kbase_get_cpu_phy_pages(region);
	if (!page_array)
		goto out_unlock;

	page_index = (katom->jc >> PAGE_SHIFT) - region->start_pfn;

	p = phys_to_page(as_phys_addr_t(page_array[page_index]));

	/* we need the first 10 words of the fragment shader job descriptor.
	 * We need to check that the offset + 10 words is less that the page
	 * size otherwise we need to load the next page.
	 * page_size_overflow will be equal to 0 in case the whole descriptor
	 * is within the page > 0 otherwise.
	 */
	copy_size = MIN(PAGE_SIZE - offset, JOB_HEADER_SIZE);

	page_1 = kmap_atomic(p);

	/* page_1 is a u32 pointer, offset is expressed in bytes */
	page_1 += offset>>2;

	kbase_sync_single_for_cpu(katom->kctx->kbdev,
			kbase_dma_addr(p) + offset,
			copy_size, DMA_BIDIRECTIONAL);

	memcpy(dst, page_1, copy_size);

	/* The data needed overflows page the dimension,
	 * need to map the subsequent page */
	if (copy_size < JOB_HEADER_SIZE) {
		p = phys_to_page(as_phys_addr_t(page_array[page_index + 1]));
		page_2 = kmap_atomic(p);

		kbase_sync_single_for_cpu(katom->kctx->kbdev,
				kbase_dma_addr(p),
				JOB_HEADER_SIZE - copy_size, DMA_BIDIRECTIONAL);

		memcpy(dst + copy_size, page_2, JOB_HEADER_SIZE - copy_size);
	}

	/* We managed to correctly map one or two pages (in case of overflow) */
	/* Get Bounding Box data and restart index from fault address low word */
	minX = job_header[FRAG_JOB_DESC_MIN_TILE_COORD_WORD] & X_COORDINATE_MASK;
	minY = job_header[FRAG_JOB_DESC_MIN_TILE_COORD_WORD] & Y_COORDINATE_MASK;
	maxX = job_header[FRAG_JOB_DESC_MAX_TILE_COORD_WORD] & X_COORDINATE_MASK;
	maxY = job_header[FRAG_JOB_DESC_MAX_TILE_COORD_WORD] & Y_COORDINATE_MASK;
	restartX = job_header[JOB_DESC_FAULT_ADDR_LOW_WORD] & X_COORDINATE_MASK;
	restartY = job_header[JOB_DESC_FAULT_ADDR_LOW_WORD] & Y_COORDINATE_MASK;

	dev_warn(dev, "Before Clamping:\n"
			"Jobstatus: %08x\n"
			"restartIdx: %08x\n"
			"Fault_addr_low: %08x\n"
			"minCoordsX: %08x minCoordsY: %08x\n"
			"maxCoordsX: %08x maxCoordsY: %08x\n",
			job_header[JOB_DESC_STATUS_WORD],
			job_header[JOB_DESC_RESTART_INDEX_WORD],
			job_header[JOB_DESC_FAULT_ADDR_LOW_WORD],
			minX, minY,
			maxX, maxY);

	/* Set the restart index to the one which generated the fault*/
	job_header[JOB_DESC_RESTART_INDEX_WORD] =
			job_header[JOB_DESC_FAULT_ADDR_LOW_WORD];

	if (restartX < minX) {
		job_header[JOB_DESC_RESTART_INDEX_WORD] = (minX) | restartY;
		dev_warn(dev,
			"Clamping restart X index to minimum. %08x clamped to %08x\n",
			restartX, minX);
		clamped =  1;
	}
	if (restartY < minY) {
		job_header[JOB_DESC_RESTART_INDEX_WORD] = (minY) | restartX;
		dev_warn(dev,
			"Clamping restart Y index to minimum. %08x clamped to %08x\n",
			restartY, minY);
		clamped =  1;
	}
	if (restartX > maxX) {
		job_header[JOB_DESC_RESTART_INDEX_WORD] = (maxX) | restartY;
		dev_warn(dev,
			"Clamping restart X index to maximum. %08x clamped to %08x\n",
			restartX, maxX);
		clamped =  1;
	}
	if (restartY > maxY) {
		job_header[JOB_DESC_RESTART_INDEX_WORD] = (maxY) | restartX;
		dev_warn(dev,
			"Clamping restart Y index to maximum. %08x clamped to %08x\n",
			restartY, maxY);
		clamped =  1;
	}

	if (clamped) {
		/* Reset the fault address low word
		 * and set the job status to STOPPED */
		job_header[JOB_DESC_FAULT_ADDR_LOW_WORD] = 0x0;
		job_header[JOB_DESC_STATUS_WORD] = BASE_JD_EVENT_STOPPED;
		dev_warn(dev, "After Clamping:\n"
				"Jobstatus: %08x\n"
				"restartIdx: %08x\n"
				"Fault_addr_low: %08x\n"
				"minCoordsX: %08x minCoordsY: %08x\n"
				"maxCoordsX: %08x maxCoordsY: %08x\n",
				job_header[JOB_DESC_STATUS_WORD],
				job_header[JOB_DESC_RESTART_INDEX_WORD],
				job_header[JOB_DESC_FAULT_ADDR_LOW_WORD],
				minX, minY,
				maxX, maxY);

		/* Flush CPU cache to update memory for future GPU reads*/
		memcpy(page_1, dst, copy_size);
		p = phys_to_page(as_phys_addr_t(page_array[page_index]));

		kbase_sync_single_for_device(katom->kctx->kbdev,
				kbase_dma_addr(p) + offset,
				copy_size, DMA_TO_DEVICE);

		if (copy_size < JOB_HEADER_SIZE) {
			memcpy(page_2, dst + copy_size,
					JOB_HEADER_SIZE - copy_size);
			p = phys_to_page(as_phys_addr_t(page_array[page_index +
								   1]));

			kbase_sync_single_for_device(katom->kctx->kbdev,
					kbase_dma_addr(p),
					JOB_HEADER_SIZE - copy_size,
					DMA_TO_DEVICE);
		}
	}
	if (copy_size < JOB_HEADER_SIZE)
		kunmap_atomic(page_2);

	kunmap_atomic(page_1);

out_unlock:
	kbase_gpu_vm_unlock(katom->kctx);
	return clamped;
}
