diff options
Diffstat (limited to 'drivers/gpu')
34 files changed, 3075 insertions, 475 deletions
diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig index 4cd35d8fd79..f5d46e7199d 100644 --- a/drivers/gpu/drm/Kconfig +++ b/drivers/gpu/drm/Kconfig @@ -67,12 +67,18 @@ config DRM_I830 will load the correct one. config DRM_I915 + tristate "i915 driver" select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT select FB select FRAMEBUFFER_CONSOLE if !EMBEDDED - tristate "i915 driver" + # i915 depends on ACPI_VIDEO when ACPI is enabled + # but for select to work, need to select ACPI_VIDEO's dependencies, ick + select VIDEO_OUTPUT_CONTROL if ACPI + select BACKLIGHT_CLASS_DEVICE if ACPI + select INPUT if ACPI + select ACPI_VIDEO if ACPI help Choose this option if you have a system that has Intel 830M, 845G, 852GM, 855GM 865G or 915G integrated graphics. If M is selected, the @@ -84,12 +90,6 @@ config DRM_I915 config DRM_I915_KMS bool "Enable modesetting on intel by default" depends on DRM_I915 - # i915 KMS depends on ACPI_VIDEO when ACPI is enabled - # but for select to work, need to select ACPI_VIDEO's dependencies, ick - select VIDEO_OUTPUT_CONTROL if ACPI - select BACKLIGHT_CLASS_DEVICE if ACPI - select INPUT if ACPI - select ACPI_VIDEO if ACPI help Choose this option if you want kernel modesetting enabled by default, and you have a new enough userspace to support this. Running old diff --git a/drivers/gpu/drm/drm_bufs.c b/drivers/gpu/drm/drm_bufs.c index 6d80d17f1e9..80a257554b3 100644 --- a/drivers/gpu/drm/drm_bufs.c +++ b/drivers/gpu/drm/drm_bufs.c @@ -170,6 +170,14 @@ static int drm_addmap_core(struct drm_device * dev, resource_size_t offset, } DRM_DEBUG("offset = 0x%08llx, size = 0x%08lx, type = %d\n", (unsigned long long)map->offset, map->size, map->type); + + /* page-align _DRM_SHM maps. They are allocated here so there is no security + * hole created by that and it works around various broken drivers that use + * a non-aligned quantity to map the SAREA. --BenH + */ + if (map->type == _DRM_SHM) + map->size = PAGE_ALIGN(map->size); + if ((map->offset & (~(resource_size_t)PAGE_MASK)) || (map->size & (~PAGE_MASK))) { drm_free(map, sizeof(*map), DRM_MEM_MAPS); return -EINVAL; @@ -363,7 +371,8 @@ static int drm_addmap_core(struct drm_device * dev, resource_size_t offset, list->user_token = list->hash.key << PAGE_SHIFT; mutex_unlock(&dev->struct_mutex); - list->master = dev->primary->master; + if (!(map->flags & _DRM_DRIVER)) + list->master = dev->primary->master; *maplist = list; return 0; } diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c index 94a76887173..8fab7890a36 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c @@ -2294,7 +2294,12 @@ int drm_mode_connector_property_set_ioctl(struct drm_device *dev, } } - if (connector->funcs->set_property) + /* Do DPMS ourselves */ + if (property == connector->dev->mode_config.dpms_property) { + if (connector->funcs->dpms) + (*connector->funcs->dpms)(connector, (int) out_resp->value); + ret = 0; + } else if (connector->funcs->set_property) ret = connector->funcs->set_property(connector, property, out_resp->value); /* store the property value if succesful */ diff --git a/drivers/gpu/drm/drm_crtc_helper.c b/drivers/gpu/drm/drm_crtc_helper.c index 45890447fee..a6f73f1e99d 100644 --- a/drivers/gpu/drm/drm_crtc_helper.c +++ b/drivers/gpu/drm/drm_crtc_helper.c @@ -199,6 +199,29 @@ static void drm_helper_add_std_modes(struct drm_device *dev, } /** + * drm_helper_encoder_in_use - check if a given encoder is in use + * @encoder: encoder to check + * + * LOCKING: + * Caller must hold mode config lock. + * + * Walk @encoders's DRM device's mode_config and see if it's in use. + * + * RETURNS: + * True if @encoder is part of the mode_config, false otherwise. + */ +bool drm_helper_encoder_in_use(struct drm_encoder *encoder) +{ + struct drm_connector *connector; + struct drm_device *dev = encoder->dev; + list_for_each_entry(connector, &dev->mode_config.connector_list, head) + if (connector->encoder == encoder) + return true; + return false; +} +EXPORT_SYMBOL(drm_helper_encoder_in_use); + +/** * drm_helper_crtc_in_use - check if a given CRTC is in a mode_config * @crtc: CRTC to check * @@ -216,7 +239,7 @@ bool drm_helper_crtc_in_use(struct drm_crtc *crtc) struct drm_device *dev = crtc->dev; /* FIXME: Locking around list access? */ list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) - if (encoder->crtc == crtc) + if (encoder->crtc == crtc && drm_helper_encoder_in_use(encoder)) return true; return false; } @@ -240,7 +263,7 @@ void drm_helper_disable_unused_functions(struct drm_device *dev) list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { encoder_funcs = encoder->helper_private; - if (!encoder->crtc) + if (!drm_helper_encoder_in_use(encoder)) (*encoder_funcs->dpms)(encoder, DRM_MODE_DPMS_OFF); } @@ -935,6 +958,88 @@ bool drm_helper_initial_config(struct drm_device *dev) } EXPORT_SYMBOL(drm_helper_initial_config); +static int drm_helper_choose_encoder_dpms(struct drm_encoder *encoder) +{ + int dpms = DRM_MODE_DPMS_OFF; + struct drm_connector *connector; + struct drm_device *dev = encoder->dev; + + list_for_each_entry(connector, &dev->mode_config.connector_list, head) + if (connector->encoder == encoder) + if (connector->dpms < dpms) + dpms = connector->dpms; + return dpms; +} + +static int drm_helper_choose_crtc_dpms(struct drm_crtc *crtc) +{ + int dpms = DRM_MODE_DPMS_OFF; + struct drm_connector *connector; + struct drm_device *dev = crtc->dev; + + list_for_each_entry(connector, &dev->mode_config.connector_list, head) + if (connector->encoder && connector->encoder->crtc == crtc) + if (connector->dpms < dpms) + dpms = connector->dpms; + return dpms; +} + +/** + * drm_helper_connector_dpms + * @connector affected connector + * @mode DPMS mode + * + * Calls the low-level connector DPMS function, then + * calls appropriate encoder and crtc DPMS functions as well + */ +void drm_helper_connector_dpms(struct drm_connector *connector, int mode) +{ + struct drm_encoder *encoder = connector->encoder; + struct drm_crtc *crtc = encoder ? encoder->crtc : NULL; + int old_dpms; + + if (mode == connector->dpms) + return; + + old_dpms = connector->dpms; + connector->dpms = mode; + + /* from off to on, do crtc then encoder */ + if (mode < old_dpms) { + if (crtc) { + struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private; + if (crtc_funcs->dpms) + (*crtc_funcs->dpms) (crtc, + drm_helper_choose_crtc_dpms(crtc)); + } + if (encoder) { + struct drm_encoder_helper_funcs *encoder_funcs = encoder->helper_private; + if (encoder_funcs->dpms) + (*encoder_funcs->dpms) (encoder, + drm_helper_choose_encoder_dpms(encoder)); + } + } + + /* from on to off, do encoder then crtc */ + if (mode > old_dpms) { + if (encoder) { + struct drm_encoder_helper_funcs *encoder_funcs = encoder->helper_private; + if (encoder_funcs->dpms) + (*encoder_funcs->dpms) (encoder, + drm_helper_choose_encoder_dpms(encoder)); + } + if (crtc) { + struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private; + if (crtc_funcs->dpms) + (*crtc_funcs->dpms) (crtc, + drm_helper_choose_crtc_dpms(crtc)); + } + } + + return; +} +EXPORT_SYMBOL(drm_helper_connector_dpms); + /** * drm_hotplug_stage_two * @dev DRM device diff --git a/drivers/gpu/drm/drm_drv.c b/drivers/gpu/drm/drm_drv.c index f01def16a66..019b7c57823 100644 --- a/drivers/gpu/drm/drm_drv.c +++ b/drivers/gpu/drm/drm_drv.c @@ -481,7 +481,7 @@ int drm_ioctl(struct inode *inode, struct file *filp, } retcode = func(dev, kdata, file_priv); - if ((retcode == 0) && (cmd & IOC_OUT)) { + if (cmd & IOC_OUT) { if (copy_to_user((void __user *)arg, kdata, _IOC_SIZE(cmd)) != 0) retcode = -EFAULT; diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c index ca9c6165671..801a0d0e081 100644 --- a/drivers/gpu/drm/drm_edid.c +++ b/drivers/gpu/drm/drm_edid.c @@ -289,6 +289,11 @@ static struct drm_display_mode *drm_mode_detailed(struct drm_device *dev, struct drm_display_mode *mode; struct detailed_pixel_timing *pt = &timing->data.pixel_data; + /* ignore tiny modes */ + if (((pt->hactive_hi << 8) | pt->hactive_lo) < 64 || + ((pt->vactive_hi << 8) | pt->hactive_lo) < 64) + return NULL; + if (pt->stereo) { printk(KERN_WARNING "stereo mode not supported\n"); return NULL; @@ -584,85 +589,13 @@ int drm_do_probe_ddc_edid(struct i2c_adapter *adapter, } EXPORT_SYMBOL(drm_do_probe_ddc_edid); -/** - * Get EDID information. - * - * \param adapter : i2c device adaptor. - * \param buf : EDID data buffer to be filled - * \param len : EDID data buffer length - * \return 0 on success or -1 on failure. - * - * Initialize DDC, then fetch EDID information - * by calling drm_do_probe_ddc_edid function. - */ -static int drm_ddc_read(struct i2c_adapter *adapter, - unsigned char *buf, int len) -{ - struct i2c_algo_bit_data *algo_data = adapter->algo_data; - int i, j; - int ret = -1; - - algo_data->setscl(algo_data->data, 1); - - for (i = 0; i < 1; i++) { - /* For some old monitors we need the - * following process to initialize/stop DDC - */ - algo_data->setsda(algo_data->data, 1); - msleep(13); - - algo_data->setscl(algo_data->data, 1); - for (j = 0; j < 5; j++) { - msleep(10); - if (algo_data->getscl(algo_data->data)) - break; - } - if (j == 5) - continue; - - algo_data->setsda(algo_data->data, 0); - msleep(15); - algo_data->setscl(algo_data->data, 0); - msleep(15); - algo_data->setsda(algo_data->data, 1); - msleep(15); - - /* Do the real work */ - ret = drm_do_probe_ddc_edid(adapter, buf, len); - algo_data->setsda(algo_data->data, 0); - algo_data->setscl(algo_data->data, 0); - msleep(15); - - algo_data->setscl(algo_data->data, 1); - for (j = 0; j < 10; j++) { - msleep(10); - if (algo_data->getscl(algo_data->data)) - break; - } - - algo_data->setsda(algo_data->data, 1); - msleep(15); - algo_data->setscl(algo_data->data, 0); - algo_data->setsda(algo_data->data, 0); - if (ret == 0) - break; - } - /* Release the DDC lines when done or the Apple Cinema HD display - * will switch off - */ - algo_data->setsda(algo_data->data, 1); - algo_data->setscl(algo_data->data, 1); - - return ret; -} - static int drm_ddc_read_edid(struct drm_connector *connector, struct i2c_adapter *adapter, char *buf, int len) { int ret; - ret = drm_ddc_read(adapter, buf, len); + ret = drm_do_probe_ddc_edid(adapter, buf, len); if (ret != 0) { dev_info(&connector->dev->pdev->dev, "%s: no EDID data\n", drm_get_connector_name(connector)); diff --git a/drivers/gpu/drm/drm_gem.c b/drivers/gpu/drm/drm_gem.c index 4984aa89cf3..ec43005100d 100644 --- a/drivers/gpu/drm/drm_gem.c +++ b/drivers/gpu/drm/drm_gem.c @@ -133,7 +133,7 @@ drm_gem_object_alloc(struct drm_device *dev, size_t size) BUG_ON((size & (PAGE_SIZE - 1)) != 0); - obj = kcalloc(1, sizeof(*obj), GFP_KERNEL); + obj = kzalloc(sizeof(*obj), GFP_KERNEL); obj->dev = dev; obj->filp = shmem_file_setup("drm mm object", size, VM_NORESERVE); diff --git a/drivers/gpu/drm/drm_hashtab.c b/drivers/gpu/drm/drm_hashtab.c index af539f7d87d..ac35145c3e2 100644 --- a/drivers/gpu/drm/drm_hashtab.c +++ b/drivers/gpu/drm/drm_hashtab.c @@ -62,6 +62,7 @@ int drm_ht_create(struct drm_open_hash *ht, unsigned int order) } return 0; } +EXPORT_SYMBOL(drm_ht_create); void drm_ht_verbose_list(struct drm_open_hash *ht, unsigned long key) { @@ -156,6 +157,7 @@ int drm_ht_just_insert_please(struct drm_open_hash *ht, struct drm_hash_item *it } return 0; } +EXPORT_SYMBOL(drm_ht_just_insert_please); int drm_ht_find_item(struct drm_open_hash *ht, unsigned long key, struct drm_hash_item **item) @@ -169,6 +171,7 @@ int drm_ht_find_item(struct drm_open_hash *ht, unsigned long key, *item = hlist_entry(list, struct drm_hash_item, head); return 0; } +EXPORT_SYMBOL(drm_ht_find_item); int drm_ht_remove_key(struct drm_open_hash *ht, unsigned long key) { @@ -202,3 +205,4 @@ void drm_ht_remove(struct drm_open_hash *ht) ht->table = NULL; } } +EXPORT_SYMBOL(drm_ht_remove); diff --git a/drivers/gpu/drm/drm_irq.c b/drivers/gpu/drm/drm_irq.c index 93e677a481f..fc8e5acd9d9 100644 --- a/drivers/gpu/drm/drm_irq.c +++ b/drivers/gpu/drm/drm_irq.c @@ -196,6 +196,7 @@ int drm_irq_install(struct drm_device *dev) { int ret = 0; unsigned long sh_flags = 0; + char *irqname; if (!drm_core_check_feature(dev, DRIVER_HAVE_IRQ)) return -EINVAL; @@ -227,8 +228,13 @@ int drm_irq_install(struct drm_device *dev) if (drm_core_check_feature(dev, DRIVER_IRQ_SHARED)) sh_flags = IRQF_SHARED; + if (dev->devname) + irqname = dev->devname; + else + irqname = dev->driver->name; + ret = request_irq(drm_dev_to_irq(dev), dev->driver->irq_handler, - sh_flags, dev->devname, dev); + sh_flags, irqname, dev); if (ret < 0) { mutex_lock(&dev->struct_mutex); diff --git a/drivers/gpu/drm/drm_mm.c b/drivers/gpu/drm/drm_mm.c index 367c590ffbb..7819fd930a5 100644 --- a/drivers/gpu/drm/drm_mm.c +++ b/drivers/gpu/drm/drm_mm.c @@ -42,8 +42,11 @@ */ #include "drmP.h" +#include "drm_mm.h" #include <linux/slab.h> +#define MM_UNUSED_TARGET 4 + unsigned long drm_mm_tail_space(struct drm_mm *mm) { struct list_head *tail_node; @@ -74,16 +77,62 @@ int drm_mm_remove_space_from_tail(struct drm_mm *mm, unsigned long size) return 0; } +static struct drm_mm_node *drm_mm_kmalloc(struct drm_mm *mm, int atomic) +{ + struct drm_mm_node *child; + + if (atomic) + child = kmalloc(sizeof(*child), GFP_ATOMIC); + else + child = kmalloc(sizeof(*child), GFP_KERNEL); + + if (unlikely(child == NULL)) { + spin_lock(&mm->unused_lock); + if (list_empty(&mm->unused_nodes)) + child = NULL; + else { + child = + list_entry(mm->unused_nodes.next, + struct drm_mm_node, fl_entry); + list_del(&child->fl_entry); + --mm->num_unused; + } + spin_unlock(&mm->unused_lock); + } + return child; +} + +int drm_mm_pre_get(struct drm_mm *mm) +{ + struct drm_mm_node *node; + + spin_lock(&mm->unused_lock); + while (mm->num_unused < MM_UNUSED_TARGET) { + spin_unlock(&mm->unused_lock); + node = kmalloc(sizeof(*node), GFP_KERNEL); + spin_lock(&mm->unused_lock); + + if (unlikely(node == NULL)) { + int ret = (mm->num_unused < 2) ? -ENOMEM : 0; + spin_unlock(&mm->unused_lock); + return ret; + } + ++mm->num_unused; + list_add_tail(&node->fl_entry, &mm->unused_nodes); + } + spin_unlock(&mm->unused_lock); + return 0; +} +EXPORT_SYMBOL(drm_mm_pre_get); static int drm_mm_create_tail_node(struct drm_mm *mm, - unsigned long start, - unsigned long size) + unsigned long start, + unsigned long size, int atomic) { struct drm_mm_node *child; - child = (struct drm_mm_node *) - drm_alloc(sizeof(*child), DRM_MEM_MM); - if (!child) + child = drm_mm_kmalloc(mm, atomic); + if (unlikely(child == NULL)) return -ENOMEM; child->free = 1; @@ -97,8 +146,7 @@ static int drm_mm_create_tail_node(struct drm_mm *mm, return 0; } - -int drm_mm_add_space_to_tail(struct drm_mm *mm, unsigned long size) +int drm_mm_add_space_to_tail(struct drm_mm *mm, unsigned long size, int atomic) { struct list_head *tail_node; struct drm_mm_node *entry; @@ -106,20 +154,21 @@ int drm_mm_add_space_to_tail(struct drm_mm *mm, unsigned long size) tail_node = mm->ml_entry.prev; entry = list_entry(tail_node, struct drm_mm_node, ml_entry); if (!entry->free) { - return drm_mm_create_tail_node(mm, entry->start + entry->size, size); + return drm_mm_create_tail_node(mm, entry->start + entry->size, + size, atomic); } entry->size += size; return 0; } static struct drm_mm_node *drm_mm_split_at_start(struct drm_mm_node *parent, - unsigned long size) + unsigned long size, + int atomic) { struct drm_mm_node *child; - child = (struct drm_mm_node *) - drm_alloc(sizeof(*child), DRM_MEM_MM); - if (!child) + child = drm_mm_kmalloc(parent->mm, atomic); + if (unlikely(child == NULL)) return NULL; INIT_LIST_HEAD(&child->fl_entry); @@ -151,8 +200,9 @@ struct drm_mm_node *drm_mm_get_block(struct drm_mm_node * parent, tmp = parent->start % alignment; if (tmp) { - align_splitoff = drm_mm_split_at_start(parent, alignment - tmp); - if (!align_splitoff) + align_splitoff = + drm_mm_split_at_start(parent, alignment - tmp, 0); + if (unlikely(align_splitoff == NULL)) return NULL; } @@ -161,7 +211,7 @@ struct drm_mm_node *drm_mm_get_block(struct drm_mm_node * parent, parent->free = 0; return parent; } else { - child = drm_mm_split_at_start(parent, size); + child = drm_mm_split_at_start(parent, size, 0); } if (align_splitoff) @@ -169,14 +219,49 @@ struct drm_mm_node *drm_mm_get_block(struct drm_mm_node * parent, return child; } + EXPORT_SYMBOL(drm_mm_get_block); +struct drm_mm_node *drm_mm_get_block_atomic(struct drm_mm_node *parent, + unsigned long size, + unsigned alignment) +{ + + struct drm_mm_node *align_splitoff = NULL; + struct drm_mm_node *child; + unsigned tmp = 0; + + if (alignment) + tmp = parent->start % alignment; + + if (tmp) { + align_splitoff = + drm_mm_split_at_start(parent, alignment - tmp, 1); + if (unlikely(align_splitoff == NULL)) + return NULL; + } + + if (parent->size == size) { + list_del_init(&parent->fl_entry); + parent->free = 0; + return parent; + } else { + child = drm_mm_split_at_start(parent, size, 1); + } + + if (align_splitoff) + drm_mm_put_block(align_splitoff); + + return child; +} +EXPORT_SYMBOL(drm_mm_get_block_atomic); + /* * Put a block. Merge with the previous and / or next block if they are free. * Otherwise add to the free stack. */ -void drm_mm_put_block(struct drm_mm_node * cur) +void drm_mm_put_block(struct drm_mm_node *cur) { struct drm_mm *mm = cur->mm; @@ -188,21 +273,27 @@ void drm_mm_put_block(struct drm_mm_node * cur) int merged = 0; if (cur_head->prev != root_head) { - prev_node = list_entry(cur_head->prev, struct drm_mm_node, ml_entry); + prev_node = + list_entry(cur_head->prev, struct drm_mm_node, ml_entry); if (prev_node->free) { prev_node->size += cur->size; merged = 1; } } if (cur_head->next != root_head) { - next_node = list_entry(cur_head->next, struct drm_mm_node, ml_entry); + next_node = + list_entry(cur_head->next, struct drm_mm_node, ml_entry); if (next_node->free) { if (merged) { prev_node->size += next_node->size; list_del(&next_node->ml_entry); list_del(&next_node->fl_entry); - drm_free(next_node, sizeof(*next_node), - DRM_MEM_MM); + if (mm->num_unused < MM_UNUSED_TARGET) { + list_add(&next_node->fl_entry, + &mm->unused_nodes); + ++mm->num_unused; + } else + kfree(next_node); } else { next_node->size += cur->size; next_node->start = cur->start; @@ -215,14 +306,19 @@ void drm_mm_put_block(struct drm_mm_node * cur) list_add(&cur->fl_entry, &mm->fl_entry); } else { list_del(&cur->ml_entry); - drm_free(cur, sizeof(*cur), DRM_MEM_MM); + if (mm->num_unused < MM_UNUSED_TARGET) { + list_add(&cur->fl_entry, &mm->unused_nodes); + ++mm->num_unused; + } else + kfree(cur); } } + EXPORT_SYMBOL(drm_mm_put_block); -struct drm_mm_node *drm_mm_search_free(const struct drm_mm * mm, - unsigned long size, - unsigned alignment, int best_match) +struct drm_mm_node *drm_mm_search_free(const struct drm_mm *mm, + unsigned long size, + unsigned alignment, int best_match) { struct list_head *list; const struct list_head *free_stack = &mm->fl_entry; @@ -247,7 +343,6 @@ struct drm_mm_node *drm_mm_search_free(const struct drm_mm * mm, wasted += alignment - tmp; } - if (entry->size >= size + wasted) { if (!best_match) return entry; @@ -260,6 +355,7 @@ struct drm_mm_node *drm_mm_search_free(const struct drm_mm * mm, return best; } +EXPORT_SYMBOL(drm_mm_search_free); int drm_mm_clean(struct drm_mm * mm) { @@ -267,14 +363,17 @@ int drm_mm_clean(struct drm_mm * mm) return (head->next->next == head); } -EXPORT_SYMBOL(drm_mm_search_free); +EXPORT_SYMBOL(drm_mm_clean); int drm_mm_init(struct drm_mm * mm, unsigned long start, unsigned long size) { INIT_LIST_HEAD(&mm->ml_entry); INIT_LIST_HEAD(&mm->fl_entry); + INIT_LIST_HEAD(&mm->unused_nodes); + mm->num_unused = 0; + spin_lock_init(&mm->unused_lock); - return drm_mm_create_tail_node(mm, start, size); + return drm_mm_create_tail_node(mm, start, size, 0); } EXPORT_SYMBOL(drm_mm_init); @@ -282,6 +381,7 @@ void drm_mm_takedown(struct drm_mm * mm) { struct list_head *bnode = mm->fl_entry.next; struct drm_mm_node *entry; + struct drm_mm_node *next; entry = list_entry(bnode, struct drm_mm_node, fl_entry); @@ -293,7 +393,16 @@ void drm_mm_takedown(struct drm_mm * mm) list_del(&entry->fl_entry); list_del(&entry->ml_entry); + kfree(entry); + + spin_lock(&mm->unused_lock); + list_for_each_entry_safe(entry, next, &mm->unused_nodes, fl_entry) { + list_del(&entry->fl_entry); + kfree(entry); + --mm->num_unused; + } + spin_unlock(&mm->unused_lock); - drm_free(entry, sizeof(*entry), DRM_MEM_MM); + BUG_ON(mm->num_unused != 0); } EXPORT_SYMBOL(drm_mm_takedown); diff --git a/drivers/gpu/drm/drm_modes.c b/drivers/gpu/drm/drm_modes.c index c9b80fdd463..54f492a488a 100644 --- a/drivers/gpu/drm/drm_modes.c +++ b/drivers/gpu/drm/drm_modes.c @@ -38,6 +38,7 @@ #include "drm.h" #include "drm_crtc.h" +#define DRM_MODESET_DEBUG "drm_mode" /** * drm_mode_debug_printmodeline - debug print a mode * @dev: DRM device @@ -50,12 +51,13 @@ */ void drm_mode_debug_printmodeline(struct drm_display_mode *mode) { - DRM_DEBUG("Modeline %d:\"%s\" %d %d %d %d %d %d %d %d %d %d 0x%x 0x%x\n", - mode->base.id, mode->name, mode->vrefresh, mode->clock, - mode->hdisplay, mode->hsync_start, - mode->hsync_end, mode->htotal, - mode->vdisplay, mode->vsync_start, - mode->vsync_end, mode->vtotal, mode->type, mode->flags); + DRM_DEBUG_MODE(DRM_MODESET_DEBUG, + "Modeline %d:\"%s\" %d %d %d %d %d %d %d %d %d %d 0x%x 0x%x\n", + mode->base.id, mode->name, mode->vrefresh, mode->clock, + mode->hdisplay, mode->hsync_start, + mode->hsync_end, mode->htotal, + mode->vdisplay, mode->vsync_start, + mode->vsync_end, mode->vtotal, mode->type, mode->flags); } EXPORT_SYMBOL(drm_mode_debug_printmodeline); @@ -401,7 +403,9 @@ void drm_mode_prune_invalid(struct drm_device *dev, list_del(&mode->head); if (verbose) { drm_mode_debug_printmodeline(mode); - DRM_DEBUG("Not using %s mode %d\n", mode->name, mode->status); + DRM_DEBUG_MODE(DRM_MODESET_DEBUG, + "Not using %s mode %d\n", + mode->name, mode->status); } drm_mode_destroy(dev, mode); } diff --git a/drivers/gpu/drm/drm_stub.c b/drivers/gpu/drm/drm_stub.c index b9631e3a1ea..89050684fe0 100644 --- a/drivers/gpu/drm/drm_stub.c +++ b/drivers/gpu/drm/drm_stub.c @@ -51,7 +51,22 @@ struct idr drm_minors_idr; struct class *drm_class; struct proc_dir_entry *drm_proc_root; struct dentry *drm_debugfs_root; - +void drm_ut_debug_printk(unsigned int request_level, + const char *prefix, + const char *function_name, + const char *format, ...) +{ + va_list args; + + if (drm_debug & request_level) { + if (function_name) + printk(KERN_DEBUG "[%s:%s], ", prefix, function_name); + va_start(args, format); + vprintk(format, args); + va_end(args); + } +} +EXPORT_SYMBOL(drm_ut_debug_printk); static int drm_minor_get_id(struct drm_device *dev, int type) { int new_id; diff --git a/drivers/gpu/drm/drm_sysfs.c b/drivers/gpu/drm/drm_sysfs.c index 8f9372921f8..9987ab88083 100644 --- a/drivers/gpu/drm/drm_sysfs.c +++ b/drivers/gpu/drm/drm_sysfs.c @@ -147,7 +147,7 @@ static ssize_t status_show(struct device *device, enum drm_connector_status status; status = connector->funcs->detect(connector); - return snprintf(buf, PAGE_SIZE, "%s", + return snprintf(buf, PAGE_SIZE, "%s\n", drm_get_connector_status_name(status)); } @@ -166,7 +166,7 @@ static ssize_t dpms_show(struct device *device, if (ret) return 0; - return snprintf(buf, PAGE_SIZE, "%s", + return snprintf(buf, PAGE_SIZE, "%s\n", drm_get_dpms_name((int)dpms_status)); } @@ -176,7 +176,7 @@ static ssize_t enabled_show(struct device *device, { struct drm_connector *connector = to_drm_connector(device); - return snprintf(buf, PAGE_SIZE, connector->encoder ? "enabled" : + return snprintf(buf, PAGE_SIZE |