Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit bb94f077 authored by Geert Uytterhoeven's avatar Geert Uytterhoeven Committed by Benjamin Herrenschmidt
Browse files

ps3fb: Inline functions in ps3fb_probe(), to ease cleanup in the error path



Signed-off-by: default avatarGeert Uytterhoeven <Geert.Uytterhoeven@sonycom.com>
Cc: linux-fbdev-devel@lists.sourceforge.net
Signed-off-by: default avatarBenjamin Herrenschmidt <benh@kernel.crashing.org>
parent 02aad32c
Loading
Loading
Loading
Loading
+86 −106
Original line number Diff line number Diff line
@@ -956,73 +956,6 @@ static irqreturn_t ps3fb_vsync_interrupt(int irq, void *ptr)
}


static int ps3fb_vsync_settings(struct gpu_driver_info *dinfo,
				struct device *dev)
{
	int error;

	dev_dbg(dev, "version_driver:%x\n", dinfo->version_driver);
	dev_dbg(dev, "irq outlet:%x\n", dinfo->irq.irq_outlet);
	dev_dbg(dev,
		"version_gpu: %x memory_size: %x ch: %x core_freq: %d "
		"mem_freq:%d\n",
		dinfo->version_gpu, dinfo->memory_size, dinfo->hardware_channel,
		dinfo->nvcore_frequency/1000000, dinfo->memory_frequency/1000000);

	if (dinfo->version_driver != GPU_DRIVER_INFO_VERSION) {
		dev_err(dev, "%s: version_driver err:%x\n", __func__,
			dinfo->version_driver);
		return -EINVAL;
	}

	error = ps3_irq_plug_setup(PS3_BINDING_CPU_ANY, dinfo->irq.irq_outlet,
				   &ps3fb.irq_no);
	if (error) {
		dev_err(dev, "%s: ps3_alloc_irq failed %d\n", __func__, error);
		return error;
	}

	error = request_irq(ps3fb.irq_no, ps3fb_vsync_interrupt, IRQF_DISABLED,
			    DEVICE_NAME, dev);
	if (error) {
		dev_err(dev, "%s: request_irq failed %d\n", __func__, error);
		ps3_irq_plug_destroy(ps3fb.irq_no);
		return error;
	}

	dinfo->irq.mask = (1 << GPU_INTR_STATUS_VSYNC_1) |
			  (1 << GPU_INTR_STATUS_FLIP_1);
	return 0;
}

static int ps3fb_xdr_settings(u64 xdr_lpar, struct device *dev)
{
	int status;

	status = lv1_gpu_context_iomap(ps3fb.context_handle, GPU_IOIF,
				       xdr_lpar, ps3fb_videomemory.size, 0);
	if (status) {
		dev_err(dev, "%s: lv1_gpu_context_iomap failed: %d\n",
			__func__, status);
		return -ENXIO;
	}
	dev_dbg(dev, "video:%p ioif:%lx lpar:%llx size:%lx\n",
		ps3fb_videomemory.address, GPU_IOIF, xdr_lpar,
		ps3fb_videomemory.size);

	status = lv1_gpu_context_attribute(ps3fb.context_handle,
					   L1GPU_CONTEXT_ATTRIBUTE_FB_SETUP,
					   xdr_lpar, GPU_CMD_BUF_SIZE,
					   GPU_IOIF, 0);
	if (status) {
		dev_err(dev,
			"%s: lv1_gpu_context_attribute FB_SETUP failed: %d\n",
			__func__, status);
		return -ENXIO;
	}
	return 0;
}

static struct fb_ops ps3fb_ops = {
	.fb_open	= ps3fb_open,
	.fb_release	= ps3fb_release,
@@ -1048,38 +981,6 @@ static struct fb_fix_screeninfo ps3fb_fix __initdata = {
	.accel =	FB_ACCEL_NONE,
};

static int ps3fb_set_sync(struct device *dev)
{
	int status;

#ifdef HEAD_A
	status = lv1_gpu_context_attribute(0x0,
					   L1GPU_CONTEXT_ATTRIBUTE_DISPLAY_SYNC,
					   0, L1GPU_DISPLAY_SYNC_VSYNC, 0, 0);
	if (status) {
		dev_err(dev,
			"%s: lv1_gpu_context_attribute DISPLAY_SYNC failed: "
			"%d\n",
			__func__, status);
		return -1;
	}
#endif
#ifdef HEAD_B
	status = lv1_gpu_context_attribute(0x0,
					   L1GPU_CONTEXT_ATTRIBUTE_DISPLAY_SYNC,
					   1, L1GPU_DISPLAY_SYNC_VSYNC, 0, 0);

	if (status) {
		dev_err(dev,
			"%s: lv1_gpu_context_attribute DISPLAY_SYNC failed: "
			"%d\n",
			__func__, status);
		return -1;
	}
#endif
	return 0;
}

static int __devinit ps3fb_probe(struct ps3_system_bus_device *dev)
{
	struct fb_info *info;
@@ -1091,6 +992,7 @@ static int __devinit ps3fb_probe(struct ps3_system_bus_device *dev)
	u64 lpar_reports = 0;
	u64 lpar_reports_size = 0;
	u64 xdr_lpar;
	struct gpu_driver_info *dinfo;
	void *fb_start;
	int status;
	struct task_struct *task;
@@ -1116,7 +1018,31 @@ static int __devinit ps3fb_probe(struct ps3_system_bus_device *dev)
	atomic_set(&ps3fb.ext_flip, 0);	/* for flip with vsync */
	init_waitqueue_head(&ps3fb.wait_vsync);

	ps3fb_set_sync(&dev->core);
#ifdef HEAD_A
	status = lv1_gpu_context_attribute(0x0,
					   L1GPU_CONTEXT_ATTRIBUTE_DISPLAY_SYNC,
					   0, L1GPU_DISPLAY_SYNC_VSYNC, 0, 0);
	if (status) {
		dev_err(&dev->core,
			"%s: lv1_gpu_context_attribute DISPLAY_SYNC failed: "
			"%d\n",
			__func__, status);
		goto err;
	}
#endif
#ifdef HEAD_B
	status = lv1_gpu_context_attribute(0x0,
					   L1GPU_CONTEXT_ATTRIBUTE_DISPLAY_SYNC,
					   1, L1GPU_DISPLAY_SYNC_VSYNC, 0, 0);

	if (status) {
		dev_err(&dev->core,
			"%s: lv1_gpu_context_attribute DISPLAY_SYNC failed: "
			"%d\n",
			__func__, status);
		goto err;
	}
#endif

	max_ps3fb_size = _ALIGN_UP(GPU_IOIF, 256*1024*1024) - GPU_IOIF;
	if (ps3fb_videomemory.size > max_ps3fb_size) {
@@ -1147,23 +1073,76 @@ static int __devinit ps3fb_probe(struct ps3_system_bus_device *dev)
	}

	/* vsync interrupt */
	ps3fb.dinfo = (void __force *)ioremap(lpar_driver_info, 128 * 1024);
	if (!ps3fb.dinfo) {
	dinfo = (void __force *)ioremap(lpar_driver_info, 128 * 1024);
	if (!dinfo) {
		dev_err(&dev->core, "%s: ioremap failed\n", __func__);
		goto err_gpu_context_free;
	}

	retval = ps3fb_vsync_settings(ps3fb.dinfo, &dev->core);
	if (retval)
	ps3fb.dinfo = dinfo;
	dev_dbg(&dev->core, "version_driver:%x\n", dinfo->version_driver);
	dev_dbg(&dev->core, "irq outlet:%x\n", dinfo->irq.irq_outlet);
	dev_dbg(&dev->core, "version_gpu: %x memory_size: %x ch: %x "
		"core_freq: %d mem_freq:%d\n", dinfo->version_gpu,
		dinfo->memory_size, dinfo->hardware_channel,
		dinfo->nvcore_frequency/1000000,
		dinfo->memory_frequency/1000000);

	if (dinfo->version_driver != GPU_DRIVER_INFO_VERSION) {
		dev_err(&dev->core, "%s: version_driver err:%x\n", __func__,
			dinfo->version_driver);
		retval = -EINVAL;
		goto err_iounmap_dinfo;
	}

	retval = ps3_irq_plug_setup(PS3_BINDING_CPU_ANY, dinfo->irq.irq_outlet,
				    &ps3fb.irq_no);
	if (retval) {
		dev_err(&dev->core, "%s: ps3_alloc_irq failed %d\n", __func__,
			retval);
		goto err_iounmap_dinfo;
	}

	retval = request_irq(ps3fb.irq_no, ps3fb_vsync_interrupt,
			     IRQF_DISABLED, DEVICE_NAME, &dev->core);
	if (retval) {
		dev_err(&dev->core, "%s: request_irq failed %d\n", __func__,
			retval);
		goto err_destroy_plug;
	}

	dinfo->irq.mask = (1 << GPU_INTR_STATUS_VSYNC_1) |
			  (1 << GPU_INTR_STATUS_FLIP_1);

	/* Clear memory to prevent kernel info leakage into userspace */
	memset(ps3fb_videomemory.address, 0, ps3fb_videomemory.size);

	xdr_lpar = ps3_mm_phys_to_lpar(__pa(ps3fb_videomemory.address));
	retval = ps3fb_xdr_settings(xdr_lpar, &dev->core);
	if (retval)

	status = lv1_gpu_context_iomap(ps3fb.context_handle, GPU_IOIF,
				       xdr_lpar, ps3fb_videomemory.size, 0);
	if (status) {
		dev_err(&dev->core, "%s: lv1_gpu_context_iomap failed: %d\n",
			__func__, status);
		retval =  -ENXIO;
		goto err_free_irq;
	}

	dev_dbg(&dev->core, "video:%p ioif:%lx lpar:%llx size:%lx\n",
		ps3fb_videomemory.address, GPU_IOIF, xdr_lpar,
		ps3fb_videomemory.size);

	status = lv1_gpu_context_attribute(ps3fb.context_handle,
					   L1GPU_CONTEXT_ATTRIBUTE_FB_SETUP,
					   xdr_lpar, GPU_CMD_BUF_SIZE,
					   GPU_IOIF, 0);
	if (status) {
		dev_err(&dev->core,
			"%s: lv1_gpu_context_attribute FB_SETUP failed: %d\n",
			__func__, status);
		retval = -ENXIO;
		goto err_free_irq;
	}

	info = framebuffer_alloc(sizeof(struct ps3fb_par), &dev->core);
	if (!info)
@@ -1234,6 +1213,7 @@ static int __devinit ps3fb_probe(struct ps3_system_bus_device *dev)
	framebuffer_release(info);
err_free_irq:
	free_irq(ps3fb.irq_no, &dev->core);
err_destroy_plug:
	ps3_irq_plug_destroy(ps3fb.irq_no);
err_iounmap_dinfo:
	iounmap((u8 __force __iomem *)ps3fb.dinfo);