svn commit: r296548 - in head/sys: dev/agp dev/drm2 dev/drm2/i915 modules/drm2/i915kms

Jean-Sébastien Pédron dumbbell at FreeBSD.org
Tue Mar 8 20:33:04 UTC 2016


Author: dumbbell
Date: Tue Mar  8 20:33:02 2016
New Revision: 296548
URL: https://svnweb.freebsd.org/changeset/base/296548

Log:
  drm/i915: Update to match Linux 3.8.13
  
  This update brings initial support for Haswell GPUs.
  
  Tested by:	Many users of FreeBSD, PC-BSD and HardenedBSD
  Relnotes:	yes
  Sponsored by:	The FreeBSD Foundation
  Differential Revision:	https://reviews.freebsd.org/D5554

Added:
  head/sys/dev/drm2/drm_mem_util.h   (contents, props changed)
  head/sys/dev/drm2/i915/dvo.h   (contents, props changed)
  head/sys/dev/drm2/i915/dvo_ch7017.c   (contents, props changed)
  head/sys/dev/drm2/i915/dvo_ch7xxx.c   (contents, props changed)
  head/sys/dev/drm2/i915/dvo_ivch.c   (contents, props changed)
  head/sys/dev/drm2/i915/dvo_ns2501.c   (contents, props changed)
  head/sys/dev/drm2/i915/dvo_sil164.c   (contents, props changed)
  head/sys/dev/drm2/i915/dvo_tfp410.c   (contents, props changed)
  head/sys/dev/drm2/i915/intel_acpi.c   (contents, props changed)
  head/sys/dev/drm2/i915/intel_dvo.c   (contents, props changed)
Modified:
  head/sys/dev/agp/agp_i810.c
  head/sys/dev/agp/agp_i810.h
  head/sys/dev/drm2/drmP.h
  head/sys/dev/drm2/drm_atomic.h
  head/sys/dev/drm2/drm_dp_iic_helper.c
  head/sys/dev/drm2/drm_drv.c
  head/sys/dev/drm2/drm_linux_list.h
  head/sys/dev/drm2/drm_os_freebsd.c
  head/sys/dev/drm2/drm_os_freebsd.h
  head/sys/dev/drm2/drm_pciids.h
  head/sys/dev/drm2/i915/i915_debug.c
  head/sys/dev/drm2/i915/i915_dma.c
  head/sys/dev/drm2/i915/i915_drm.h
  head/sys/dev/drm2/i915/i915_drv.c
  head/sys/dev/drm2/i915/i915_drv.h
  head/sys/dev/drm2/i915/i915_gem.c
  head/sys/dev/drm2/i915/i915_gem_context.c
  head/sys/dev/drm2/i915/i915_gem_evict.c
  head/sys/dev/drm2/i915/i915_gem_execbuffer.c
  head/sys/dev/drm2/i915/i915_gem_gtt.c
  head/sys/dev/drm2/i915/i915_gem_stolen.c
  head/sys/dev/drm2/i915/i915_gem_tiling.c
  head/sys/dev/drm2/i915/i915_irq.c
  head/sys/dev/drm2/i915/i915_reg.h
  head/sys/dev/drm2/i915/i915_suspend.c
  head/sys/dev/drm2/i915/intel_bios.c
  head/sys/dev/drm2/i915/intel_bios.h
  head/sys/dev/drm2/i915/intel_crt.c
  head/sys/dev/drm2/i915/intel_ddi.c
  head/sys/dev/drm2/i915/intel_display.c
  head/sys/dev/drm2/i915/intel_dp.c
  head/sys/dev/drm2/i915/intel_drv.h
  head/sys/dev/drm2/i915/intel_fb.c
  head/sys/dev/drm2/i915/intel_hdmi.c
  head/sys/dev/drm2/i915/intel_iic.c
  head/sys/dev/drm2/i915/intel_lvds.c
  head/sys/dev/drm2/i915/intel_modes.c
  head/sys/dev/drm2/i915/intel_opregion.c
  head/sys/dev/drm2/i915/intel_overlay.c
  head/sys/dev/drm2/i915/intel_panel.c
  head/sys/dev/drm2/i915/intel_pm.c
  head/sys/dev/drm2/i915/intel_ringbuffer.c
  head/sys/dev/drm2/i915/intel_ringbuffer.h
  head/sys/dev/drm2/i915/intel_sdvo.c
  head/sys/dev/drm2/i915/intel_sprite.c
  head/sys/dev/drm2/i915/intel_tv.c
  head/sys/modules/drm2/i915kms/Makefile

Modified: head/sys/dev/agp/agp_i810.c
==============================================================================
--- head/sys/dev/agp/agp_i810.c	Tue Mar  8 20:24:12 2016	(r296547)
+++ head/sys/dev/agp/agp_i810.c	Tue Mar  8 20:33:02 2016	(r296548)
@@ -250,6 +250,10 @@ struct agp_i810_driver {
 	void (*chipset_flush)(device_t);
 };
 
+static struct {
+	struct intel_gtt base;
+} intel_private;
+
 static const struct agp_i810_driver agp_i810_i810_driver = {
 	.chiptype = CHIP_I810,
 	.gen = 1,
@@ -526,6 +530,29 @@ static const struct agp_i810_driver agp_
 	.chipset_flush = agp_i810_chipset_flush,
 };
 
+static const struct agp_i810_driver agp_i810_valleyview_driver = {
+	.chiptype = CHIP_SB,
+	.gen = 7,
+	.busdma_addr_mask_sz = 40,
+	.res_spec = agp_g4x_res_spec,
+	.check_active = agp_sb_check_active,
+	.set_desc = agp_i810_set_desc,
+	.dump_regs = agp_sb_dump_regs,
+	.get_stolen_size = agp_sb_get_stolen_size,
+	.get_gtt_mappable_entries = agp_i915_get_gtt_mappable_entries,
+	.get_gtt_total_entries = agp_sb_get_gtt_total_entries,
+	.install_gatt = agp_g4x_install_gatt,
+	.deinstall_gatt = agp_i830_deinstall_gatt,
+	.write_gtt = agp_sb_write_gtt,
+	.install_gtt_pte = agp_sb_install_gtt_pte,
+	.read_gtt_pte = agp_g4x_read_gtt_pte,
+	.read_gtt_pte_paddr = agp_sb_read_gtt_pte_paddr,
+	.set_aperture = agp_i915_set_aperture,
+	.chipset_flush_setup = agp_i810_chipset_flush_setup,
+	.chipset_flush_teardown = agp_i810_chipset_flush_teardown,
+	.chipset_flush = agp_i810_chipset_flush,
+};
+
 /* For adding new devices, devid is the id of the graphics controller
  * (pci:0:2:0, for example).  The placeholder (usually at pci:0:2:1) for the
  * second head should never be added.  The bridge_offset is the offset to
@@ -763,40 +790,200 @@ static const struct agp_i810_match {
 	},
 	{
 		.devid = 0x04028086,
-		.name = "Haswell desktop GT1",
+		.name = "Haswell GT1 desktop",
+		.driver = &agp_i810_hsw_driver
+	},
+	{
+		.devid = 0x04068086,
+		.name = "Haswell GT1 mobile",
+		.driver = &agp_i810_hsw_driver
+	},
+	{
+		.devid = 0x040A8086,
+		.name = "Haswell GT1 server",
 		.driver = &agp_i810_hsw_driver
 	},
 	{
 		.devid = 0x04128086,
-		.name = "Haswell desktop GT2",
+		.name = "Haswell GT2 desktop",
 		.driver = &agp_i810_hsw_driver
 	},
 	{
-		.devid = 0x040a8086,
-		.name = "Haswell server GT1",
+		.devid = 0x04168086,
+		.name = "Haswell GT2 mobile",
 		.driver = &agp_i810_hsw_driver
 	},
 	{
-		.devid = 0x041a8086,
-		.name = "Haswell server GT2",
+		.devid = 0x041A8086,
+		.name = "Haswell GT2 server",
 		.driver = &agp_i810_hsw_driver
 	},
 	{
-		.devid = 0x04068086,
-		.name = "Haswell mobile GT1",
+		.devid = 0x04228086,
+		.name = "Haswell GT2 desktop",
 		.driver = &agp_i810_hsw_driver
 	},
 	{
-		.devid = 0x04168086,
-		.name = "Haswell mobile GT2",
+		.devid = 0x04268086,
+		.name = "Haswell GT2 mobile",
+		.driver = &agp_i810_hsw_driver
+	},
+	{
+		.devid = 0x042A8086,
+		.name = "Haswell GT2 server",
+		.driver = &agp_i810_hsw_driver
+	},
+	{
+		.devid = 0x0A028086,
+		.name = "Haswell ULT GT1 desktop",
+		.driver = &agp_i810_hsw_driver
+	},
+	{
+		.devid = 0x0A068086,
+		.name = "Haswell ULT GT1 mobile",
+		.driver = &agp_i810_hsw_driver
+	},
+	{
+		.devid = 0x0A0A8086,
+		.name = "Haswell ULT GT1 server",
+		.driver = &agp_i810_hsw_driver
+	},
+	{
+		.devid = 0x0A128086,
+		.name = "Haswell ULT GT2 desktop",
+		.driver = &agp_i810_hsw_driver
+	},
+	{
+		.devid = 0x0A168086,
+		.name = "Haswell ULT GT2 mobile",
+		.driver = &agp_i810_hsw_driver
+	},
+	{
+		.devid = 0x0A1A8086,
+		.name = "Haswell ULT GT2 server",
+		.driver = &agp_i810_hsw_driver
+	},
+	{
+		.devid = 0x0A228086,
+		.name = "Haswell ULT GT2 desktop",
+		.driver = &agp_i810_hsw_driver
+	},
+	{
+		.devid = 0x0A268086,
+		.name = "Haswell ULT GT2 mobile",
+		.driver = &agp_i810_hsw_driver
+	},
+	{
+		.devid = 0x0A2A8086,
+		.name = "Haswell ULT GT2 server",
+		.driver = &agp_i810_hsw_driver
+	},
+	{
+		.devid = 0x0C028086,
+		.name = "Haswell SDV GT1 desktop",
+		.driver = &agp_i810_hsw_driver
+	},
+	{
+		.devid = 0x0C068086,
+		.name = "Haswell SDV GT1 mobile",
 		.driver = &agp_i810_hsw_driver
 	},
 	{
-		.devid = 0x0c168086,
-		.name = "Haswell SDV",
+		.devid = 0x0C0A8086,
+		.name = "Haswell SDV GT1 server",
 		.driver = &agp_i810_hsw_driver
 	},
 	{
+		.devid = 0x0C128086,
+		.name = "Haswell SDV GT2 desktop",
+		.driver = &agp_i810_hsw_driver
+	},
+	{
+		.devid = 0x0C168086,
+		.name = "Haswell SDV GT2 mobile",
+		.driver = &agp_i810_hsw_driver
+	},
+	{
+		.devid = 0x0C1A8086,
+		.name = "Haswell SDV GT2 server",
+		.driver = &agp_i810_hsw_driver
+	},
+	{
+		.devid = 0x0C228086,
+		.name = "Haswell SDV GT2 desktop",
+		.driver = &agp_i810_hsw_driver
+	},
+	{
+		.devid = 0x0C268086,
+		.name = "Haswell SDV GT2 mobile",
+		.driver = &agp_i810_hsw_driver
+	},
+	{
+		.devid = 0x0C2A8086,
+		.name = "Haswell SDV GT2 server",
+		.driver = &agp_i810_hsw_driver
+	},
+	{
+		.devid = 0x0D028086,
+		.name = "Haswell CRW GT1 desktop",
+		.driver = &agp_i810_hsw_driver
+	},
+	{
+		.devid = 0x0D068086,
+		.name = "Haswell CRW GT1 mobile",
+		.driver = &agp_i810_hsw_driver
+	},
+	{
+		.devid = 0x0D0A8086,
+		.name = "Haswell CRW GT1 server",
+		.driver = &agp_i810_hsw_driver
+	},
+	{
+		.devid = 0x0D128086,
+		.name = "Haswell CRW GT2 desktop",
+		.driver = &agp_i810_hsw_driver
+	},
+	{
+		.devid = 0x0D168086,
+		.name = "Haswell CRW GT2 mobile",
+		.driver = &agp_i810_hsw_driver
+	},
+	{
+		.devid = 0x0D1A8086,
+		.name = "Haswell CRW GT2 server",
+		.driver = &agp_i810_hsw_driver
+	},
+	{
+		.devid = 0x0D228086,
+		.name = "Haswell CRW GT2 desktop",
+		.driver = &agp_i810_hsw_driver
+	},
+	{
+		.devid = 0x0D268086,
+		.name = "Haswell CRW GT2 mobile",
+		.driver = &agp_i810_hsw_driver
+	},
+	{
+		.devid = 0x0D2A8086,
+		.name = "Haswell CRW GT2 server",
+		.driver = &agp_i810_hsw_driver
+	},
+	{
+		.devid = 0x01558086,
+		.name = "Valleyview (desktop)",
+		.driver = &agp_i810_valleyview_driver
+	},
+	{
+		.devid = 0x01578086,
+		.name = "Valleyview (mobile)",
+		.driver = &agp_i810_valleyview_driver
+	},
+	{
+		.devid = 0x0F308086,
+		.name = "Valleyview (mobile)",
+		.driver = &agp_i810_valleyview_driver
+	},
+	{
 		.devid = 0,
 	}
 };
@@ -2285,6 +2472,10 @@ agp_intel_gtt_get(device_t dev)
 	res.gtt_mappable_entries = sc->gtt_mappable_entries;
 	res.do_idle_maps = 0;
 	res.scratch_page_dma = VM_PAGE_TO_PHYS(bogus_page);
+	if (sc->agp.as_aperture != NULL)
+		res.gma_bus_addr = rman_get_start(sc->agp.as_aperture);
+	else
+		res.gma_bus_addr = 0;
 	return (res);
 }
 
@@ -2588,11 +2779,12 @@ intel_gtt_insert_pages(u_int first_entry
 	    pages, flags);
 }
 
-struct intel_gtt
+struct intel_gtt *
 intel_gtt_get(void)
 {
 
-	return (agp_intel_gtt_get(intel_agp));
+	intel_private.base = agp_intel_gtt_get(intel_agp);
+	return (&intel_private.base);
 }
 
 int

Modified: head/sys/dev/agp/agp_i810.h
==============================================================================
--- head/sys/dev/agp/agp_i810.h	Tue Mar  8 20:24:12 2016	(r296547)
+++ head/sys/dev/agp/agp_i810.h	Tue Mar  8 20:33:02 2016	(r296548)
@@ -33,6 +33,7 @@
 #define	AGP_AGP_I810_H
 
 #include <sys/param.h>
+#include <sys/rman.h>
 #include <sys/sglist.h>
 
 #include <vm/vm.h>
@@ -51,24 +52,23 @@
 
 struct intel_gtt {
 	/* Size of memory reserved for graphics by the BIOS */
-	u_int stolen_size;
+	unsigned int stolen_size;
 	/* Total number of gtt entries. */
-	u_int gtt_total_entries;
-	/*
-	 * Part of the gtt that is mappable by the cpu, for those
-	 * chips where this is not the full gtt.
-	 */
-	u_int gtt_mappable_entries;
-
-	/*
-	 * Always false.
-	 */
-	u_int do_idle_maps;
-	
-	/*
-	 * Share the scratch page dma with ppgtts.
-	 */
+	unsigned int gtt_total_entries;
+	/* Part of the gtt that is mappable by the cpu, for those chips where
+	 * this is not the full gtt. */
+	unsigned int gtt_mappable_entries;
+	/* Whether i915 needs to use the dmar apis or not. */
+	unsigned int needs_dmar : 1;
+	/* Whether we idle the gpu before mapping/unmapping */
+	unsigned int do_idle_maps : 1;
+	/* Share the scratch page dma with ppgtts. */
 	vm_paddr_t scratch_page_dma;
+	vm_page_t scratch_page;
+	/* for ppgtt PDE access */
+	uint32_t *gtt;
+	/* needed for ioremap in drm/i915 */
+	bus_addr_t gma_bus_addr;
 };
 
 struct intel_gtt agp_intel_gtt_get(device_t dev);
@@ -83,7 +83,7 @@ void agp_intel_gtt_insert_sg_entries(dev
 void agp_intel_gtt_insert_pages(device_t dev, u_int first_entry,
     u_int num_entries, vm_page_t *pages, u_int flags);
 
-struct intel_gtt intel_gtt_get(void);
+struct intel_gtt *intel_gtt_get(void);
 int intel_gtt_chipset_flush(void);
 void intel_gtt_unmap_memory(struct sglist *sg_list);
 void intel_gtt_clear_range(u_int first_entry, u_int num_entries);

Modified: head/sys/dev/drm2/drmP.h
==============================================================================
--- head/sys/dev/drm2/drmP.h	Tue Mar  8 20:24:12 2016	(r296547)
+++ head/sys/dev/drm2/drmP.h	Tue Mar  8 20:33:02 2016	(r296548)
@@ -238,7 +238,6 @@ struct drm_device;
 			__func__ , ##__VA_ARGS__);			\
 } while (0)
 
-
 /*@}*/
 
 /***********************************************************************/
@@ -700,6 +699,8 @@ struct drm_driver {
 	void (*postclose) (struct drm_device *, struct drm_file *);
 	void (*lastclose) (struct drm_device *);
 	int (*unload) (struct drm_device *);
+	int (*suspend) (struct drm_device *, pm_message_t state);
+	int (*resume) (struct drm_device *);
 	int (*dma_ioctl) (struct drm_device *dev, void *data, struct drm_file *file_priv);
 	int (*dma_quiescent) (struct drm_device *);
 	int (*context_dtor) (struct drm_device *dev, int context);
@@ -1118,7 +1119,7 @@ struct drm_device {
 	char busid_str[128];
 	int modesetting;
 
-	drm_pci_id_list_t *id_entry;	/* PCI ID, name, and chipset private */
+	const drm_pci_id_list_t *id_entry;	/* PCI ID, name, and chipset private */
 };
 
 #define DRM_SWITCH_POWER_ON 0
@@ -1581,6 +1582,8 @@ static __inline__ void drm_core_dropmap(
 {
 }
 
+#include <dev/drm2/drm_mem_util.h>
+
 extern int drm_fill_in_dev(struct drm_device *dev,
 			   struct drm_driver *driver);
 extern void drm_cancel_fill_in_dev(struct drm_device *dev);
@@ -1758,9 +1761,11 @@ struct dmi_system_id {
 bool dmi_check_system(const struct dmi_system_id *);
 
 /* Device setup support (drm_drv.c) */
-int	drm_probe_helper(device_t kdev, drm_pci_id_list_t *idlist);
-int	drm_attach_helper(device_t kdev, drm_pci_id_list_t *idlist,
+int	drm_probe_helper(device_t kdev, const drm_pci_id_list_t *idlist);
+int	drm_attach_helper(device_t kdev, const drm_pci_id_list_t *idlist,
 	    struct drm_driver *driver);
+int	drm_generic_suspend(device_t kdev);
+int	drm_generic_resume(device_t kdev);
 int	drm_generic_detach(device_t kdev);
 
 void drm_event_wakeup(struct drm_pending_event *e);

Modified: head/sys/dev/drm2/drm_atomic.h
==============================================================================
--- head/sys/dev/drm2/drm_atomic.h	Tue Mar  8 20:24:12 2016	(r296547)
+++ head/sys/dev/drm2/drm_atomic.h	Tue Mar  8 20:33:02 2016	(r296548)
@@ -39,8 +39,8 @@ typedef uint64_t	atomic64_t;
 #define	NB_BITS_PER_LONG		(sizeof(long) * NBBY)
 #define	BITS_TO_LONGS(x)		howmany(x, NB_BITS_PER_LONG)
 
-#define	atomic_read(p)			(*(volatile u_int *)(p))
-#define	atomic_set(p, v)		do { *(u_int *)(p) = (v); } while (0)
+#define	atomic_read(p)			atomic_load_acq_int(p)
+#define	atomic_set(p, v)		atomic_store_rel_int(p, v)
 
 #define	atomic64_read(p)		atomic_load_acq_64(p)
 #define	atomic64_set(p, v)		atomic_store_rel_64(p, v)
@@ -78,6 +78,9 @@ typedef uint64_t	atomic64_t;
 #define	cmpxchg(ptr, old, new) \
     (atomic_cmpset_int((volatile u_int *)(ptr),(old),(new)) ? (old) : (0))
 
+#define	atomic_inc_not_zero(p)		atomic_inc(p)
+#define	atomic_clear_mask(b, p)		atomic_clear_int((p), (b))
+
 static __inline u_long
 find_first_zero_bit(const u_long *p, u_long max)
 {

Modified: head/sys/dev/drm2/drm_dp_iic_helper.c
==============================================================================
--- head/sys/dev/drm2/drm_dp_iic_helper.c	Tue Mar  8 20:24:12 2016	(r296547)
+++ head/sys/dev/drm2/drm_dp_iic_helper.c	Tue Mar  8 20:33:02 2016	(r296548)
@@ -149,7 +149,7 @@ iic_dp_aux_xfer(device_t idev, struct ii
 		buf = msgs[m].buf;
 		reading = (msgs[m].flags & IIC_M_RD) != 0;
 		ret = iic_dp_aux_address(idev, msgs[m].slave >> 1, reading);
-		if (ret != 0)
+		if (ret < 0)
 			break;
 		if (reading) {
 			for (b = 0; b < len; b++) {
@@ -160,7 +160,7 @@ iic_dp_aux_xfer(device_t idev, struct ii
 		} else {
 			for (b = 0; b < len; b++) {
 				ret = iic_dp_aux_put_byte(idev, buf[b]);
-				if (ret != 0)
+				if (ret < 0)
 					break;
 			}
 		}

Modified: head/sys/dev/drm2/drm_drv.c
==============================================================================
--- head/sys/dev/drm2/drm_drv.c	Tue Mar  8 20:24:12 2016	(r296547)
+++ head/sys/dev/drm2/drm_drv.c	Tue Mar  8 20:33:02 2016	(r296548)
@@ -470,6 +470,14 @@ int drm_ioctl(struct cdev *kdev, u_long 
 
       err_i1:
 	atomic_dec(&dev->ioctl_count);
+	if (retcode == -ERESTARTSYS) {
+		/*
+		 * FIXME: Find where in i915 ERESTARTSYS should be
+		 * converted to EINTR.
+		 */
+		DRM_DEBUG("ret = %d -> %d\n", retcode, -EINTR);
+		retcode = -EINTR;
+	}
 	if (retcode)
 		DRM_DEBUG("ret = %d\n", retcode);
 	if (retcode != 0 &&

Modified: head/sys/dev/drm2/drm_linux_list.h
==============================================================================
--- head/sys/dev/drm2/drm_linux_list.h	Tue Mar  8 20:24:12 2016	(r296547)
+++ head/sys/dev/drm2/drm_linux_list.h	Tue Mar  8 20:33:02 2016	(r296548)
@@ -40,7 +40,6 @@ struct list_head {
 };
 
 #define list_entry(ptr, type, member) container_of(ptr,type,member)
-#define hlist_entry(ptr, type, member) container_of(ptr,type,member)
 
 static __inline__ void
 INIT_LIST_HEAD(struct list_head *head) {
@@ -179,4 +178,123 @@ list_splice(const struct list_head *list
 void drm_list_sort(void *priv, struct list_head *head, int (*cmp)(void *priv,
     struct list_head *a, struct list_head *b));
 
+/* hlist, copied from sys/dev/ofed/linux/list.h */
+
+struct hlist_head {
+	struct hlist_node *first;
+};
+
+struct hlist_node {
+	struct hlist_node *next, **pprev;
+};
+
+#define	HLIST_HEAD_INIT { }
+#define	HLIST_HEAD(name) struct hlist_head name = HLIST_HEAD_INIT
+#define	INIT_HLIST_HEAD(head) (head)->first = NULL
+#define	INIT_HLIST_NODE(node)						\
+do {									\
+	(node)->next = NULL;						\
+	(node)->pprev = NULL;						\
+} while (0)
+
+static inline int
+hlist_unhashed(const struct hlist_node *h)
+{
+
+	return !h->pprev;
+}
+
+static inline int
+hlist_empty(const struct hlist_head *h)
+{
+
+	return !h->first;
+}
+
+static inline void
+hlist_del(struct hlist_node *n)
+{
+
+        if (n->next)
+                n->next->pprev = n->pprev;
+        *n->pprev = n->next;
+}
+
+static inline void
+hlist_del_init(struct hlist_node *n)
+{
+
+	if (hlist_unhashed(n))
+		return;
+	hlist_del(n);
+	INIT_HLIST_NODE(n);
+}
+
+static inline void
+hlist_add_head(struct hlist_node *n, struct hlist_head *h)
+{
+
+	n->next = h->first;
+	if (h->first)
+		h->first->pprev = &n->next;
+	h->first = n;
+	n->pprev = &h->first;
+}
+
+static inline void
+hlist_add_before(struct hlist_node *n, struct hlist_node *next)
+{
+
+	n->pprev = next->pprev;
+	n->next = next;
+	next->pprev = &n->next;
+	*(n->pprev) = n;
+}
+
+static inline void
+hlist_add_after(struct hlist_node *n, struct hlist_node *next)
+{
+
+	next->next = n->next;
+	n->next = next;
+	next->pprev = &n->next;
+	if (next->next)
+		next->next->pprev = &next->next;
+}
+
+static inline void
+hlist_move_list(struct hlist_head *old, struct hlist_head *new)
+{
+
+	new->first = old->first;
+	if (new->first)
+		new->first->pprev = &new->first;
+	old->first = NULL;
+}
+
+#define	hlist_entry(ptr, type, field)	container_of(ptr, type, field)
+
+#define	hlist_for_each(p, head)						\
+	for (p = (head)->first; p; p = p->next)
+
+#define	hlist_for_each_safe(p, n, head)					\
+	for (p = (head)->first; p && ({ n = p->next; 1; }); p = n)
+
+#define	hlist_for_each_entry(tp, p, head, field)			\
+	for (p = (head)->first;						\
+	    p ? (tp = hlist_entry(p, typeof(*tp), field)): NULL; p = p->next)
+
+#define hlist_for_each_entry_continue(tp, p, field)			\
+	for (p = (p)->next;						\
+	    p ? (tp = hlist_entry(p, typeof(*tp), field)): NULL; p = p->next)
+
+#define	hlist_for_each_entry_from(tp, p, field)				\
+	for (; p ? (tp = hlist_entry(p, typeof(*tp), field)): NULL; p = p->next)
+
+#define hlist_for_each_entry_safe(tpos, pos, n, head, member) 		 \
+	for (pos = (head)->first;					 \
+	     (pos) != 0 && ({ n = (pos)->next; \
+		 tpos = hlist_entry((pos), typeof(*(tpos)), member); 1;}); \
+	     pos = (n))
+
 #endif /* _DRM_LINUX_LIST_H_ */

Added: head/sys/dev/drm2/drm_mem_util.h
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/sys/dev/drm2/drm_mem_util.h	Tue Mar  8 20:33:02 2016	(r296548)
@@ -0,0 +1,59 @@
+/*
+ * Copyright © 2008 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ * Authors:
+ *     Jesse Barnes <jbarnes at virtuousgeek.org>
+ *
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#ifndef _DRM_MEM_UTIL_H_
+#define _DRM_MEM_UTIL_H_
+
+#include <sys/types.h>
+#include <sys/malloc.h>
+
+static __inline__ void *drm_calloc_large(size_t nmemb, size_t size)
+{
+	if (size != 0 && nmemb > SIZE_MAX / size)
+		return NULL;
+
+	return malloc(nmemb * size, DRM_MEM_DRIVER, M_NOWAIT | M_ZERO);
+}
+
+/* Modeled after cairo's malloc_ab, it's like calloc but without the zeroing. */
+static __inline__ void *drm_malloc_ab(size_t nmemb, size_t size)
+{
+	if (size != 0 && nmemb > SIZE_MAX / size)
+		return NULL;
+
+	return malloc(nmemb * size, DRM_MEM_DRIVER, M_NOWAIT);
+}
+
+static __inline void drm_free_large(void *ptr)
+{
+	free(ptr, DRM_MEM_DRIVER);
+}
+
+#endif

Modified: head/sys/dev/drm2/drm_os_freebsd.c
==============================================================================
--- head/sys/dev/drm2/drm_os_freebsd.c	Tue Mar  8 20:24:12 2016	(r296547)
+++ head/sys/dev/drm2/drm_os_freebsd.c	Tue Mar  8 20:33:02 2016	(r296548)
@@ -67,8 +67,27 @@ ns_to_timeval(const int64_t nsec)
         return (tv);
 }
 
-static drm_pci_id_list_t *
-drm_find_description(int vendor, int device, drm_pci_id_list_t *idlist)
+/* Copied from OFED. */
+unsigned long drm_linux_timer_hz_mask;
+
+static void
+drm_linux_timer_init(void *arg)
+{
+
+        /*
+         * Compute an internal HZ value which can divide 2**32 to
+         * avoid timer rounding problems when the tick value wraps
+         * around 2**32:
+         */
+        drm_linux_timer_hz_mask = 1;
+        while (drm_linux_timer_hz_mask < (unsigned long)hz)
+                drm_linux_timer_hz_mask *= 2;
+        drm_linux_timer_hz_mask--;
+}
+SYSINIT(drm_linux_timer, SI_SUB_DRIVERS, SI_ORDER_FIRST, drm_linux_timer_init, NULL);
+
+static const drm_pci_id_list_t *
+drm_find_description(int vendor, int device, const drm_pci_id_list_t *idlist)
 {
 	int i = 0;
 
@@ -87,9 +106,9 @@ drm_find_description(int vendor, int dev
  * method.
  */
 int
-drm_probe_helper(device_t kdev, drm_pci_id_list_t *idlist)
+drm_probe_helper(device_t kdev, const drm_pci_id_list_t *idlist)
 {
-	drm_pci_id_list_t *id_entry;
+	const drm_pci_id_list_t *id_entry;
 	int vendor, device;
 
 	vendor = pci_get_vendor(kdev);
@@ -118,7 +137,7 @@ drm_probe_helper(device_t kdev, drm_pci_
  * method.
  */
 int
-drm_attach_helper(device_t kdev, drm_pci_id_list_t *idlist,
+drm_attach_helper(device_t kdev, const drm_pci_id_list_t *idlist,
     struct drm_driver *driver)
 {
 	struct drm_device *dev;
@@ -137,6 +156,55 @@ drm_attach_helper(device_t kdev, drm_pci
 }
 
 int
+drm_generic_suspend(device_t kdev)
+{
+	struct drm_device *dev;
+	int error;
+
+	DRM_DEBUG_KMS("Starting suspend\n");
+
+	dev = device_get_softc(kdev);
+	if (dev->driver->suspend) {
+		pm_message_t state;
+
+		state.event = PM_EVENT_SUSPEND;
+		error = -dev->driver->suspend(dev, state);
+		if (error)
+			goto out;
+	}
+
+	error = bus_generic_suspend(kdev);
+
+out:
+	DRM_DEBUG_KMS("Finished suspend: %d\n", error);
+
+	return error;
+}
+
+int
+drm_generic_resume(device_t kdev)
+{
+	struct drm_device *dev;
+	int error;
+
+	DRM_DEBUG_KMS("Starting resume\n");
+
+	dev = device_get_softc(kdev);
+	if (dev->driver->resume) {
+		error = -dev->driver->resume(dev);
+		if (error)
+			goto out;
+	}
+
+	error = bus_generic_resume(kdev);
+
+out:
+	DRM_DEBUG_KMS("Finished resume: %d\n", error);
+
+	return error;
+}
+
+int
 drm_generic_detach(device_t kdev)
 {
 	struct drm_device *dev;
@@ -331,6 +399,42 @@ drm_clflush_virt_range(char *addr, unsig
 #endif
 }
 
+void
+hex_dump_to_buffer(const void *buf, size_t len, int rowsize, int groupsize,
+    char *linebuf, size_t linebuflen, bool ascii __unused)
+{
+	int i, j, c;
+
+	i = j = 0;
+
+	while (i < len && j <= linebuflen) {
+		c = ((const char *)buf)[i];
+
+		if (i != 0) {
+			if (i % rowsize == 0) {
+				/* Newline required. */
+				sprintf(linebuf + j, "\n");
+				++j;
+			} else if (i % groupsize == 0) {
+				/* Space required. */
+				sprintf(linebuf + j, " ");
+				++j;
+			}
+		}
+
+		if (j > linebuflen - 1)
+			break;
+
+		sprintf(linebuf + j, "%02X", c);
+		j += 2;
+
+		++i;
+	}
+
+	if (j <= linebuflen)
+		sprintf(linebuf + j, "\n");
+}
+
 #if DRM_LINUX
 
 #include <sys/sysproto.h>

Modified: head/sys/dev/drm2/drm_os_freebsd.h
==============================================================================
--- head/sys/dev/drm2/drm_os_freebsd.h	Tue Mar  8 20:24:12 2016	(r296547)
+++ head/sys/dev/drm2/drm_os_freebsd.h	Tue Mar  8 20:33:02 2016	(r296548)
@@ -10,6 +10,7 @@ __FBSDID("$FreeBSD$");
 #define	_DRM_OS_FREEBSD_H_
 
 #include <sys/fbio.h>
+#include <sys/smp.h>
 
 #if _BYTE_ORDER == _BIG_ENDIAN
 #define	__BIG_ENDIAN 4321
@@ -24,10 +25,22 @@ __FBSDID("$FreeBSD$");
 #endif
 
 #ifndef __user
-#define __user
+#define	__user
 #endif
 #ifndef __iomem
-#define __iomem
+#define	__iomem
+#endif
+#ifndef __always_unused
+#define	__always_unused
+#endif
+#ifndef __must_check
+#define	__must_check
+#endif
+#ifndef __force
+#define	__force
+#endif
+#ifndef uninitialized_var
+#define	uninitialized_var(x) x
 #endif
 
 #define	cpu_to_le16(x)	htole16(x)
@@ -69,9 +82,23 @@ typedef void			irqreturn_t;
 #define	__exit
 #define	__read_mostly
 
-#define	WARN_ON(cond)		KASSERT(!(cond), ("WARN ON: " #cond))
+#define	BUILD_BUG_ON(x)		CTASSERT(!(x))
+#define	BUILD_BUG_ON_NOT_POWER_OF_2(x)
+
+#ifndef WARN
+#define WARN(condition, format, ...) ({				\
+	int __ret_warn_on = !!(condition);			\
+	if (unlikely(__ret_warn_on))				\
+	DRM_ERROR(format, ##__VA_ARGS__);			\
+	unlikely(__ret_warn_on);				\
+})
+#endif
+#define	WARN_ONCE(condition, format, ...)			\
+	WARN(condition, format, ##__VA_ARGS__)
+#define	WARN_ON(cond)		WARN(cond, "WARN ON: " #cond)
 #define	WARN_ON_SMP(cond)	WARN_ON(cond)
-#define	BUG_ON(cond)		KASSERT(!(cond), ("BUG ON: " #cond))
+#define	BUG()			panic("BUG")
+#define	BUG_ON(cond)		KASSERT(!(cond), ("BUG ON: " #cond " -> 0x%jx", (uintmax_t)(cond)))
 #define	unlikely(x)            __builtin_expect(!!(x), 0)
 #define	likely(x)              __builtin_expect(!!(x), 1)
 #define	container_of(ptr, type, member) ({			\
@@ -93,6 +120,15 @@ typedef void			irqreturn_t;
 #define	DRM_UDELAY(udelay)	DELAY(udelay)
 #define	drm_msleep(x, msg)	pause((msg), ((int64_t)(x)) * hz / 1000)
 #define	DRM_MSLEEP(msecs)	drm_msleep((msecs), "drm_msleep")
+#define	get_seconds()		time_second
+
+#define ioread8(addr)		*(volatile uint8_t *)((char *)addr)
+#define ioread16(addr)		*(volatile uint16_t *)((char *)addr)
+#define ioread32(addr)		*(volatile uint32_t *)((char *)addr)
+
+#define iowrite8(data, addr)	*(volatile uint8_t *)((char *)addr) = data;
+#define iowrite16(data, addr)	*(volatile uint16_t *)((char *)addr) = data;
+#define iowrite32(data, addr)	*(volatile uint32_t *)((char *)addr) = data;
 
 #define	DRM_READ8(map, offset)						\
 	*(volatile u_int8_t *)(((vm_offset_t)(map)->handle) +		\
@@ -127,12 +163,18 @@ typedef void			irqreturn_t;
 #define	DRM_WRITEMEMORYBARRIER()	wmb()
 #define	DRM_MEMORYBARRIER()		mb()
 #define	smp_rmb()			rmb()
+#define	smp_wmb()			wmb()
 #define	smp_mb__before_atomic_inc()	mb()
 #define	smp_mb__after_atomic_inc()	mb()
+#define	barrier()			__compiler_membar()
 
 #define	do_div(a, b)		((a) /= (b))
 #define	div64_u64(a, b)		((a) / (b))
 #define	lower_32_bits(n)	((u32)(n))
+#define	upper_32_bits(n)	((u32)(((n) >> 16) >> 16))
+
+#define	__set_bit(n, s)		set_bit((n), (s))
+#define	__clear_bit(n, s)	clear_bit((n), (s))
 
 #define min_t(type, x, y) ({			\
 	type __min1 = (x);			\
@@ -148,6 +190,10 @@ typedef void			irqreturn_t;
 #define	memcpy_fromio(a, b, c)	memcpy((a), (b), (c))
 #define	memcpy_toio(a, b, c)	memcpy((a), (b), (c))
 
+#define	VERIFY_READ	VM_PROT_READ
+#define	VERIFY_WRITE	VM_PROT_WRITE
+#define	access_ok(prot, p, l)	useracc((p), (l), (prot))
+
 /* XXXKIB what is the right code for the FreeBSD ? */
 /* kib@ used ENXIO here -- dumbbell@ */
 #define	EREMOTEIO	EIO
@@ -170,8 +216,10 @@ typedef void			irqreturn_t;
 #define	PCI_VENDOR_ID_SONY		0x104d
 #define	PCI_VENDOR_ID_VIA		0x1106
 
-#define DIV_ROUND_UP(n,d) (((n) + (d) - 1) / (d))
-#define	hweight32(i)	bitcount32(i)
+#define DIV_ROUND_UP(n,d) 	(((n) + (d) - 1) / (d))
+#define	DIV_ROUND_CLOSEST(n,d)	(((n) + (d) / 2) / (d))
+#define	div_u64(n, d)		((n) / (d))
+#define	hweight32(i)		bitcount32(i)
 
 static inline unsigned long
 roundup_pow_of_two(unsigned long x)
@@ -195,6 +243,8 @@ ror32(uint32_t word, unsigned int shift)
 }
 
 #define	IS_ALIGNED(x, y)	(((x) & ((y) - 1)) == 0)
+#define	round_down(x, y)	rounddown2((x), (y))
+#define	round_up(x, y)		roundup2((x), (y))
 #define	get_unaligned(ptr)                                              \
 	({ __typeof__(*(ptr)) __tmp;                                    \
 	  memcpy(&__tmp, (ptr), sizeof(*(ptr))); __tmp; })
@@ -251,7 +301,9 @@ abs64(int64_t x)
 int64_t		timeval_to_ns(const struct timeval *tv);
 struct timeval	ns_to_timeval(const int64_t nsec);
 
-#define PAGE_ALIGN(addr) round_page(addr)
+#define	PAGE_ALIGN(addr) round_page(addr)
+#define	page_to_phys(x) VM_PAGE_TO_PHYS(x)
+#define	offset_in_page(x) ((x) & PAGE_MASK)
 
 #define	drm_get_device_from_kdev(_kdev)	(((struct drm_minor *)(_kdev)->si_drv1)->dev)
 
@@ -295,20 +347,193 @@ __get_user(size_t size, const void *ptr,
 }
 #define	get_user(x, ptr) __get_user(sizeof(*ptr), (ptr), &(x))
 
+static inline int
+__copy_to_user_inatomic(void __user *to, const void *from, unsigned n)
+{
+
+	return (copyout_nofault(from, to, n) != 0 ? n : 0);
+}
+#define	__copy_to_user_inatomic_nocache(to, from, n) \
+    __copy_to_user_inatomic((to), (from), (n))
+
+static inline unsigned long
+__copy_from_user_inatomic(void *to, const void __user *from,
+    unsigned long n)
+{
+
+	/*
+	 * XXXKIB.  Equivalent Linux function is implemented using
+	 * MOVNTI for aligned moves.  For unaligned head and tail,
+	 * normal move is performed.  As such, it is not incorrect, if
+	 * only somewhat slower, to use normal copyin.  All uses
+	 * except shmem_pwrite_fast() have the destination mapped WC.
+	 */
+	return ((copyin_nofault(__DECONST(void *, from), to, n) != 0 ? n : 0));
+}
+#define	__copy_from_user_inatomic_nocache(to, from, n) \
+    __copy_from_user_inatomic((to), (from), (n))
+
+static inline int
+fault_in_multipages_readable(const char __user *uaddr, int size)
+{
+	char c;
+	int ret = 0;
+	const char __user *end = uaddr + size - 1;
+
+	if (unlikely(size == 0))
+		return ret;
+
+	while (uaddr <= end) {
+		ret = -copyin(uaddr, &c, 1);
+		if (ret != 0)
+			return -EFAULT;
+		uaddr += PAGE_SIZE;
+	}
+
+	/* Check whether the range spilled into the next page. */
+	if (((unsigned long)uaddr & ~PAGE_MASK) ==
+			((unsigned long)end & ~PAGE_MASK)) {
+		ret = -copyin(end, &c, 1);
+	}
+
+	return ret;
+}
+
+static inline int
+fault_in_multipages_writeable(char __user *uaddr, int size)
+{
+	int ret = 0;

*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***


More information about the svn-src-all mailing list