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 <jbar...@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 *** _______________________________________________ svn-src-all@freebsd.org mailing list https://lists.freebsd.org/mailman/listinfo/svn-src-all To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"