diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2010-02-11 17:03:28 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2010-02-11 17:03:28 -0500 |
commit | 67dcabd06126084295b5825d3d7f584450dd8553 (patch) | |
tree | ac4a3be737071f7b891b8a66e764d5706cf681ca | |
parent | 09e65ed298e1d12b82752675ff5b9135860429ff (diff) | |
parent | 77c1ff3982c6b36961725dd19e872a1c07df7f3b (diff) |
Merge branch 'drm-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/airlied/drm-2.6
* 'drm-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/airlied/drm-2.6: (30 commits)
vgaarb: fix incorrect dereference of userspace pointer.
drm/radeon/kms: retry auxch on 0x20 timeout value.
drm/radeon: Skip dma copy test in benchmark if card doesn't have dma engine.
drm/vmwgfx: Fix a circular locking dependency bug.
drm/vmwgfx: Drop scanout flag compat and add execbuf ioctl parameter members. Bumps major.
drm/vmwgfx: Report propper framebuffer_{max|min}_{width|height}
drm/vmwgfx: Update the user-space interface.
drm/radeon/kms: fix screen clearing before fbcon.
nouveau: fix state detection with switchable graphics
drm/nouveau: move dereferences after null checks
drm/nv50: make the pgraph irq handler loop like the pre-nv50 version
drm/nv50: delete ramfc object after disabling fifo, not before
drm/nv50: avoid unloading pgraph context when ctxprog is running
drm/nv50: align size of buffer object to the right boundaries.
drm/nv50: disregard dac outputs in nv50_sor_dpms()
drm/nv50: prevent multiple init tables being parsed at the same time
drm/nouveau: make dp auxch xfer len check for reads only
drm/nv40: make INIT_COMPUTE_MEM a NOP, just like nv50
drm/nouveau: Add proper vgaarb support.
drm/nouveau: Fix fbcon on mixed pre-NV50 + NV50 multicard.
...
43 files changed, 402 insertions, 230 deletions
diff --git a/drivers/gpu/drm/nouveau/nouveau_acpi.c b/drivers/gpu/drm/nouveau/nouveau_acpi.c index 1cf488247a16..48227e744753 100644 --- a/drivers/gpu/drm/nouveau/nouveau_acpi.c +++ b/drivers/gpu/drm/nouveau/nouveau_acpi.c | |||
@@ -90,21 +90,21 @@ int nouveau_hybrid_setup(struct drm_device *dev) | |||
90 | { | 90 | { |
91 | int result; | 91 | int result; |
92 | 92 | ||
93 | if (nouveau_dsm(dev, NOUVEAU_DSM_ACTIVE, NOUVEAU_DSM_ACTIVE_QUERY, | 93 | if (nouveau_dsm(dev, NOUVEAU_DSM_POWER, NOUVEAU_DSM_POWER_STATE, |
94 | &result)) | 94 | &result)) |
95 | return -ENODEV; | 95 | return -ENODEV; |
96 | 96 | ||
97 | NV_INFO(dev, "_DSM hardware status gave 0x%x\n", result); | 97 | NV_INFO(dev, "_DSM hardware status gave 0x%x\n", result); |
98 | 98 | ||
99 | if (result & 0x1) { /* Stamina mode - disable the external GPU */ | 99 | if (result) { /* Ensure that the external GPU is enabled */ |
100 | nouveau_dsm(dev, NOUVEAU_DSM_LED, NOUVEAU_DSM_LED_SPEED, NULL); | ||
101 | nouveau_dsm(dev, NOUVEAU_DSM_POWER, NOUVEAU_DSM_POWER_SPEED, | ||
102 | NULL); | ||
103 | } else { /* Stamina mode - disable the external GPU */ | ||
100 | nouveau_dsm(dev, NOUVEAU_DSM_LED, NOUVEAU_DSM_LED_STAMINA, | 104 | nouveau_dsm(dev, NOUVEAU_DSM_LED, NOUVEAU_DSM_LED_STAMINA, |
101 | NULL); | 105 | NULL); |
102 | nouveau_dsm(dev, NOUVEAU_DSM_POWER, NOUVEAU_DSM_POWER_STAMINA, | 106 | nouveau_dsm(dev, NOUVEAU_DSM_POWER, NOUVEAU_DSM_POWER_STAMINA, |
103 | NULL); | 107 | NULL); |
104 | } else { /* Ensure that the external GPU is enabled */ | ||
105 | nouveau_dsm(dev, NOUVEAU_DSM_LED, NOUVEAU_DSM_LED_SPEED, NULL); | ||
106 | nouveau_dsm(dev, NOUVEAU_DSM_POWER, NOUVEAU_DSM_POWER_SPEED, | ||
107 | NULL); | ||
108 | } | 108 | } |
109 | 109 | ||
110 | return 0; | 110 | return 0; |
diff --git a/drivers/gpu/drm/nouveau/nouveau_bios.c b/drivers/gpu/drm/nouveau/nouveau_bios.c index d7f8d8b4a4b8..2cd0fad17dac 100644 --- a/drivers/gpu/drm/nouveau/nouveau_bios.c +++ b/drivers/gpu/drm/nouveau/nouveau_bios.c | |||
@@ -1865,7 +1865,7 @@ init_compute_mem(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) | |||
1865 | 1865 | ||
1866 | struct drm_nouveau_private *dev_priv = bios->dev->dev_private; | 1866 | struct drm_nouveau_private *dev_priv = bios->dev->dev_private; |
1867 | 1867 | ||
1868 | if (dev_priv->card_type >= NV_50) | 1868 | if (dev_priv->card_type >= NV_40) |
1869 | return 1; | 1869 | return 1; |
1870 | 1870 | ||
1871 | /* | 1871 | /* |
@@ -3765,7 +3765,6 @@ nouveau_bios_run_display_table(struct drm_device *dev, struct dcb_entry *dcbent, | |||
3765 | */ | 3765 | */ |
3766 | 3766 | ||
3767 | struct drm_nouveau_private *dev_priv = dev->dev_private; | 3767 | struct drm_nouveau_private *dev_priv = dev->dev_private; |
3768 | struct init_exec iexec = {true, false}; | ||
3769 | struct nvbios *bios = &dev_priv->VBIOS; | 3768 | struct nvbios *bios = &dev_priv->VBIOS; |
3770 | uint8_t *table = &bios->data[bios->display.script_table_ptr]; | 3769 | uint8_t *table = &bios->data[bios->display.script_table_ptr]; |
3771 | uint8_t *otable = NULL; | 3770 | uint8_t *otable = NULL; |
@@ -3845,8 +3844,6 @@ nouveau_bios_run_display_table(struct drm_device *dev, struct dcb_entry *dcbent, | |||
3845 | } | 3844 | } |
3846 | } | 3845 | } |
3847 | 3846 | ||
3848 | bios->display.output = dcbent; | ||
3849 | |||
3850 | if (pxclk == 0) { | 3847 | if (pxclk == 0) { |
3851 | script = ROM16(otable[6]); | 3848 | script = ROM16(otable[6]); |
3852 | if (!script) { | 3849 | if (!script) { |
@@ -3855,7 +3852,7 @@ nouveau_bios_run_display_table(struct drm_device *dev, struct dcb_entry *dcbent, | |||
3855 | } | 3852 | } |
3856 | 3853 | ||
3857 | NV_TRACE(dev, "0x%04X: parsing output script 0\n", script); | 3854 | NV_TRACE(dev, "0x%04X: parsing output script 0\n", script); |
3858 | parse_init_table(bios, script, &iexec); | 3855 | nouveau_bios_run_init_table(dev, script, dcbent); |
3859 | } else | 3856 | } else |
3860 | if (pxclk == -1) { | 3857 | if (pxclk == -1) { |
3861 | script = ROM16(otable[8]); | 3858 | script = ROM16(otable[8]); |
@@ -3865,7 +3862,7 @@ nouveau_bios_run_display_table(struct drm_device *dev, struct dcb_entry *dcbent, | |||
3865 | } | 3862 | } |
3866 | 3863 | ||
3867 | NV_TRACE(dev, "0x%04X: parsing output script 1\n", script); | 3864 | NV_TRACE(dev, "0x%04X: parsing output script 1\n", script); |
3868 | parse_init_table(bios, script, &iexec); | 3865 | nouveau_bios_run_init_table(dev, script, dcbent); |
3869 | } else | 3866 | } else |
3870 | if (pxclk == -2) { | 3867 | if (pxclk == -2) { |
3871 | if (table[4] >= 12) | 3868 | if (table[4] >= 12) |
@@ -3878,7 +3875,7 @@ nouveau_bios_run_display_table(struct drm_device *dev, struct dcb_entry *dcbent, | |||
3878 | } | 3875 | } |
3879 | 3876 | ||
3880 | NV_TRACE(dev, "0x%04X: parsing output script 2\n", script); | 3877 | NV_TRACE(dev, "0x%04X: parsing output script 2\n", script); |
3881 | parse_init_table(bios, script, &iexec); | 3878 | nouveau_bios_run_init_table(dev, script, dcbent); |
3882 | } else | 3879 | } else |
3883 | if (pxclk > 0) { | 3880 | if (pxclk > 0) { |
3884 | script = ROM16(otable[table[4] + i*6 + 2]); | 3881 | script = ROM16(otable[table[4] + i*6 + 2]); |
@@ -3890,7 +3887,7 @@ nouveau_bios_run_display_table(struct drm_device *dev, struct dcb_entry *dcbent, | |||
3890 | } | 3887 | } |
3891 | 3888 | ||
3892 | NV_TRACE(dev, "0x%04X: parsing clock script 0\n", script); | 3889 | NV_TRACE(dev, "0x%04X: parsing clock script 0\n", script); |
3893 | parse_init_table(bios, script, &iexec); | 3890 | nouveau_bios_run_init_table(dev, script, dcbent); |
3894 | } else | 3891 | } else |
3895 | if (pxclk < 0) { | 3892 | if (pxclk < 0) { |
3896 | script = ROM16(otable[table[4] + i*6 + 4]); | 3893 | script = ROM16(otable[table[4] + i*6 + 4]); |
@@ -3902,7 +3899,7 @@ nouveau_bios_run_display_table(struct drm_device *dev, struct dcb_entry *dcbent, | |||
3902 | } | 3899 | } |
3903 | 3900 | ||
3904 | NV_TRACE(dev, "0x%04X: parsing clock script 1\n", script); | 3901 | NV_TRACE(dev, "0x%04X: parsing clock script 1\n", script); |
3905 | parse_init_table(bios, script, &iexec); | 3902 | nouveau_bios_run_init_table(dev, script, dcbent); |
3906 | } | 3903 | } |
3907 | 3904 | ||
3908 | return 0; | 3905 | return 0; |
@@ -5864,10 +5861,13 @@ nouveau_bios_run_init_table(struct drm_device *dev, uint16_t table, | |||
5864 | struct drm_nouveau_private *dev_priv = dev->dev_private; | 5861 | struct drm_nouveau_private *dev_priv = dev->dev_private; |
5865 | struct nvbios *bios = &dev_priv->VBIOS; | 5862 | struct nvbios *bios = &dev_priv->VBIOS; |
5866 | struct init_exec iexec = { true, false }; | 5863 | struct init_exec iexec = { true, false }; |
5864 | unsigned long flags; | ||
5867 | 5865 | ||
5866 | spin_lock_irqsave(&bios->lock, flags); | ||
5868 | bios->display.output = dcbent; | 5867 | bios->display.output = dcbent; |
5869 | parse_init_table(bios, table, &iexec); | 5868 | parse_init_table(bios, table, &iexec); |
5870 | bios->display.output = NULL; | 5869 | bios->display.output = NULL; |
5870 | spin_unlock_irqrestore(&bios->lock, flags); | ||
5871 | } | 5871 | } |
5872 | 5872 | ||
5873 | static bool NVInitVBIOS(struct drm_device *dev) | 5873 | static bool NVInitVBIOS(struct drm_device *dev) |
@@ -5876,6 +5876,7 @@ static bool NVInitVBIOS(struct drm_device *dev) | |||
5876 | struct nvbios *bios = &dev_priv->VBIOS; | 5876 | struct nvbios *bios = &dev_priv->VBIOS; |
5877 | 5877 | ||
5878 | memset(bios, 0, sizeof(struct nvbios)); | 5878 | memset(bios, 0, sizeof(struct nvbios)); |
5879 | spin_lock_init(&bios->lock); | ||
5879 | bios->dev = dev; | 5880 | bios->dev = dev; |
5880 | 5881 | ||
5881 | if (!NVShadowVBIOS(dev, bios->data)) | 5882 | if (!NVShadowVBIOS(dev, bios->data)) |
diff --git a/drivers/gpu/drm/nouveau/nouveau_bios.h b/drivers/gpu/drm/nouveau/nouveau_bios.h index 058e98c76d89..68446fd4146b 100644 --- a/drivers/gpu/drm/nouveau/nouveau_bios.h +++ b/drivers/gpu/drm/nouveau/nouveau_bios.h | |||
@@ -205,6 +205,8 @@ struct nvbios { | |||
205 | struct drm_device *dev; | 205 | struct drm_device *dev; |
206 | struct nouveau_bios_info pub; | 206 | struct nouveau_bios_info pub; |
207 | 207 | ||
208 | spinlock_t lock; | ||
209 | |||
208 | uint8_t data[NV_PROM_SIZE]; | 210 | uint8_t data[NV_PROM_SIZE]; |
209 | unsigned int length; | 211 | unsigned int length; |
210 | bool execute; | 212 | bool execute; |
diff --git a/drivers/gpu/drm/nouveau/nouveau_bo.c b/drivers/gpu/drm/nouveau/nouveau_bo.c index db0ed4c13f98..028719fddf76 100644 --- a/drivers/gpu/drm/nouveau/nouveau_bo.c +++ b/drivers/gpu/drm/nouveau/nouveau_bo.c | |||
@@ -65,8 +65,10 @@ nouveau_bo_fixup_align(struct drm_device *dev, | |||
65 | 65 | ||
66 | /* | 66 | /* |
67 | * Some of the tile_flags have a periodic structure of N*4096 bytes, | 67 | * Some of the tile_flags have a periodic structure of N*4096 bytes, |
68 | * align to to that as well as the page size. Overallocate memory to | 68 | * align to to that as well as the page size. Align the size to the |
69 | * avoid corruption of other buffer objects. | 69 | * appropriate boundaries. This does imply that sizes are rounded up |
70 | * 3-7 pages, so be aware of this and do not waste memory by allocating | ||
71 | * many small buffers. | ||
70 | */ | 72 | */ |
71 | if (dev_priv->card_type == NV_50) { | 73 | if (dev_priv->card_type == NV_50) { |
72 | uint32_t block_size = nouveau_mem_fb_amount(dev) >> 15; | 74 | uint32_t block_size = nouveau_mem_fb_amount(dev) >> 15; |
@@ -77,22 +79,20 @@ nouveau_bo_fixup_align(struct drm_device *dev, | |||
77 | case 0x2800: | 79 | case 0x2800: |
78 | case 0x4800: | 80 | case 0x4800: |
79 | case 0x7a00: | 81 | case 0x7a00: |
80 | *size = roundup(*size, block_size); | ||
81 | if (is_power_of_2(block_size)) { | 82 | if (is_power_of_2(block_size)) { |
82 | *size += 3 * block_size; | ||
83 | for (i = 1; i < 10; i++) { | 83 | for (i = 1; i < 10; i++) { |
84 | *align = 12 * i * block_size; | 84 | *align = 12 * i * block_size; |
85 | if (!(*align % 65536)) | 85 | if (!(*align % 65536)) |
86 | break; | 86 | break; |
87 | } | 87 | } |
88 | } else { | 88 | } else { |
89 | *size += 6 * block_size; | ||
90 | for (i = 1; i < 10; i++) { | 89 | for (i = 1; i < 10; i++) { |
91 | *align = 8 * i * block_size; | 90 | *align = 8 * i * block_size; |
92 | if (!(*align % 65536)) | 91 | if (!(*align % 65536)) |
93 | break; | 92 | break; |
94 | } | 93 | } |
95 | } | 94 | } |
95 | *size = roundup(*size, *align); | ||
96 | break; | 96 | break; |
97 | default: | 97 | default: |
98 | break; | 98 | break; |
diff --git a/drivers/gpu/drm/nouveau/nouveau_channel.c b/drivers/gpu/drm/nouveau/nouveau_channel.c index 343d718a9667..2281f99da7fc 100644 --- a/drivers/gpu/drm/nouveau/nouveau_channel.c +++ b/drivers/gpu/drm/nouveau/nouveau_channel.c | |||
@@ -278,12 +278,11 @@ nouveau_channel_free(struct nouveau_channel *chan) | |||
278 | /* Ensure the channel is no longer active on the GPU */ | 278 | /* Ensure the channel is no longer active on the GPU */ |
279 | pfifo->reassign(dev, false); | 279 | pfifo->reassign(dev, false); |
280 | 280 | ||
281 | if (pgraph->channel(dev) == chan) { | 281 | pgraph->fifo_access(dev, false); |
282 | pgraph->fifo_access(dev, false); | 282 | if (pgraph->channel(dev) == chan) |
283 | pgraph->unload_context(dev); | 283 | pgraph->unload_context(dev); |
284 | pgraph->fifo_access(dev, true); | ||
285 | } | ||
286 | pgraph->destroy_context(chan); | 284 | pgraph->destroy_context(chan); |
285 | pgraph->fifo_access(dev, true); | ||
287 | 286 | ||
288 | if (pfifo->channel_id(dev) == chan->id) { | 287 | if (pfifo->channel_id(dev) == chan->id) { |
289 | pfifo->disable(dev); | 288 | pfifo->disable(dev); |
diff --git a/drivers/gpu/drm/nouveau/nouveau_connector.c b/drivers/gpu/drm/nouveau/nouveau_connector.c index 7e6d673f3a23..d2f63353ea97 100644 --- a/drivers/gpu/drm/nouveau/nouveau_connector.c +++ b/drivers/gpu/drm/nouveau/nouveau_connector.c | |||
@@ -88,13 +88,14 @@ nouveau_connector_destroy(struct drm_connector *drm_connector) | |||
88 | { | 88 | { |
89 | struct nouveau_connector *nv_connector = | 89 | struct nouveau_connector *nv_connector = |
90 | nouveau_connector(drm_connector); | 90 | nouveau_connector(drm_connector); |
91 | struct drm_device *dev = nv_connector->base.dev; | 91 | struct drm_device *dev; |
92 | |||
93 | NV_DEBUG_KMS(dev, "\n"); | ||
94 | 92 | ||
95 | if (!nv_connector) | 93 | if (!nv_connector) |
96 | return; | 94 | return; |
97 | 95 | ||
96 | dev = nv_connector->base.dev; | ||
97 | NV_DEBUG_KMS(dev, "\n"); | ||
98 | |||
98 | kfree(nv_connector->edid); | 99 | kfree(nv_connector->edid); |
99 | drm_sysfs_connector_remove(drm_connector); | 100 | drm_sysfs_connector_remove(drm_connector); |
100 | drm_connector_cleanup(drm_connector); | 101 | drm_connector_cleanup(drm_connector); |
diff --git a/drivers/gpu/drm/nouveau/nouveau_dp.c b/drivers/gpu/drm/nouveau/nouveau_dp.c index dd4937224220..f954ad93e81f 100644 --- a/drivers/gpu/drm/nouveau/nouveau_dp.c +++ b/drivers/gpu/drm/nouveau/nouveau_dp.c | |||
@@ -502,12 +502,12 @@ nouveau_dp_auxch(struct nouveau_i2c_chan *auxch, int cmd, int addr, | |||
502 | break; | 502 | break; |
503 | } | 503 | } |
504 | 504 | ||
505 | if ((stat & NV50_AUXCH_STAT_COUNT) != data_nr) { | ||
506 | ret = -EREMOTEIO; | ||
507 | goto out; | ||
508 | } | ||
509 | |||
510 | if (cmd & 1) { | 505 | if (cmd & 1) { |
506 | if ((stat & NV50_AUXCH_STAT_COUNT) != data_nr) { | ||
507 | ret = -EREMOTEIO; | ||
508 | goto out; | ||
509 | } | ||
510 | |||
511 | for (i = 0; i < 4; i++) { | 511 | for (i = 0; i < 4; i++) { |
512 | data32[i] = nv_rd32(dev, NV50_AUXCH_DATA_IN(index, i)); | 512 | data32[i] = nv_rd32(dev, NV50_AUXCH_DATA_IN(index, i)); |
513 | NV_DEBUG_KMS(dev, "rd %d: 0x%08x\n", i, data32[i]); | 513 | NV_DEBUG_KMS(dev, "rd %d: 0x%08x\n", i, data32[i]); |
diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.c b/drivers/gpu/drm/nouveau/nouveau_drv.c index 343ab7f17ccc..da3b93b84502 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drv.c +++ b/drivers/gpu/drm/nouveau/nouveau_drv.c | |||
@@ -56,7 +56,7 @@ int nouveau_vram_pushbuf; | |||
56 | module_param_named(vram_pushbuf, nouveau_vram_pushbuf, int, 0400); | 56 | module_param_named(vram_pushbuf, nouveau_vram_pushbuf, int, 0400); |
57 | 57 | ||
58 | MODULE_PARM_DESC(vram_notify, "Force DMA notifiers to be in VRAM"); | 58 | MODULE_PARM_DESC(vram_notify, "Force DMA notifiers to be in VRAM"); |
59 | int nouveau_vram_notify; | 59 | int nouveau_vram_notify = 1; |
60 | module_param_named(vram_notify, nouveau_vram_notify, int, 0400); | 60 | module_param_named(vram_notify, nouveau_vram_notify, int, 0400); |
61 | 61 | ||
62 | MODULE_PARM_DESC(duallink, "Allow dual-link TMDS (>=GeForce 8)"); | 62 | MODULE_PARM_DESC(duallink, "Allow dual-link TMDS (>=GeForce 8)"); |
@@ -75,6 +75,14 @@ MODULE_PARM_DESC(ignorelid, "Ignore ACPI lid status"); | |||
75 | int nouveau_ignorelid = 0; | 75 | int nouveau_ignorelid = 0; |
76 | module_param_named(ignorelid, nouveau_ignorelid, int, 0400); | 76 | module_param_named(ignorelid, nouveau_ignorelid, int, 0400); |
77 | 77 | ||
78 | MODULE_PARM_DESC(noagp, "Disable all acceleration"); | ||
79 | int nouveau_noaccel = 0; | ||
80 | module_param_named(noaccel, nouveau_noaccel, int, 0400); | ||
81 | |||
82 | MODULE_PARM_DESC(noagp, "Disable fbcon acceleration"); | ||
83 | int nouveau_nofbaccel = 0; | ||
84 | module_param_named(nofbaccel, nouveau_nofbaccel, int, 0400); | ||
85 | |||
78 | MODULE_PARM_DESC(tv_norm, "Default TV norm.\n" | 86 | MODULE_PARM_DESC(tv_norm, "Default TV norm.\n" |
79 | "\t\tSupported: PAL, PAL-M, PAL-N, PAL-Nc, NTSC-M, NTSC-J,\n" | 87 | "\t\tSupported: PAL, PAL-M, PAL-N, PAL-Nc, NTSC-M, NTSC-J,\n" |
80 | "\t\t\thd480i, hd480p, hd576i, hd576p, hd720p, hd1080i.\n" | 88 | "\t\t\thd480i, hd480p, hd576i, hd576p, hd720p, hd1080i.\n" |
diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.h b/drivers/gpu/drm/nouveau/nouveau_drv.h index 6b9690418bc7..5445cefdd03e 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drv.h +++ b/drivers/gpu/drm/nouveau/nouveau_drv.h | |||
@@ -678,6 +678,8 @@ extern int nouveau_reg_debug; | |||
678 | extern char *nouveau_vbios; | 678 | extern char *nouveau_vbios; |
679 | extern int nouveau_ctxfw; | 679 | extern int nouveau_ctxfw; |
680 | extern int nouveau_ignorelid; | 680 | extern int nouveau_ignorelid; |
681 | extern int nouveau_nofbaccel; | ||
682 | extern int nouveau_noaccel; | ||
681 | 683 | ||
682 | /* nouveau_state.c */ | 684 | /* nouveau_state.c */ |
683 | extern void nouveau_preclose(struct drm_device *dev, struct drm_file *); | 685 | extern void nouveau_preclose(struct drm_device *dev, struct drm_file *); |
diff --git a/drivers/gpu/drm/nouveau/nouveau_fbcon.c b/drivers/gpu/drm/nouveau/nouveau_fbcon.c index 0b05c869e0e7..ea879a2efef3 100644 --- a/drivers/gpu/drm/nouveau/nouveau_fbcon.c +++ b/drivers/gpu/drm/nouveau/nouveau_fbcon.c | |||
@@ -107,6 +107,34 @@ static struct fb_ops nouveau_fbcon_ops = { | |||
107 | .fb_setcmap = drm_fb_helper_setcmap, | 107 | .fb_setcmap = drm_fb_helper_setcmap, |
108 | }; | 108 | }; |
109 | 109 | ||
110 | static struct fb_ops nv04_fbcon_ops = { | ||
111 | .owner = THIS_MODULE, | ||
112 | .fb_check_var = drm_fb_helper_check_var, | ||
113 | .fb_set_par = drm_fb_helper_set_par, | ||
114 | .fb_setcolreg = drm_fb_helper_setcolreg, | ||
115 | .fb_fillrect = nv04_fbcon_fillrect, | ||
116 | .fb_copyarea = nv04_fbcon_copyarea, | ||
117 | .fb_imageblit = nv04_fbcon_imageblit, | ||
118 | .fb_sync = nouveau_fbcon_sync, | ||
119 | .fb_pan_display = drm_fb_helper_pan_display, | ||
120 | .fb_blank = drm_fb_helper_blank, | ||
121 | .fb_setcmap = drm_fb_helper_setcmap, | ||
122 | }; | ||
123 | |||
124 | static struct fb_ops nv50_fbcon_ops = { | ||
125 | .owner = THIS_MODULE, | ||
126 | .fb_check_var = drm_fb_helper_check_var, | ||
127 | .fb_set_par = drm_fb_helper_set_par, | ||
128 | .fb_setcolreg = drm_fb_helper_setcolreg, | ||
129 | .fb_fillrect = nv50_fbcon_fillrect, | ||
130 | .fb_copyarea = nv50_fbcon_copyarea, | ||
131 | .fb_imageblit = nv50_fbcon_imageblit, | ||
132 | .fb_sync = nouveau_fbcon_sync, | ||
133 | .fb_pan_display = drm_fb_helper_pan_display, | ||
134 | .fb_blank = drm_fb_helper_blank, | ||
135 | .fb_setcmap = drm_fb_helper_setcmap, | ||
136 | }; | ||
137 | |||
110 | static void nouveau_fbcon_gamma_set(struct drm_crtc *crtc, u16 red, u16 green, | 138 | static void nouveau_fbcon_gamma_set(struct drm_crtc *crtc, u16 red, u16 green, |
111 | u16 blue, int regno) | 139 | u16 blue, int regno) |
112 | { | 140 | { |
@@ -267,8 +295,12 @@ nouveau_fbcon_create(struct drm_device *dev, uint32_t fb_width, | |||
267 | dev_priv->fbdev_info = info; | 295 | dev_priv->fbdev_info = info; |
268 | 296 | ||
269 | strcpy(info->fix.id, "nouveaufb"); | 297 | strcpy(info->fix.id, "nouveaufb"); |
270 | info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_COPYAREA | | 298 | if (nouveau_nofbaccel) |
271 | FBINFO_HWACCEL_FILLRECT | FBINFO_HWACCEL_IMAGEBLIT; | 299 | info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_DISABLED; |
300 | else | ||
301 | info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_COPYAREA | | ||
302 | FBINFO_HWACCEL_FILLRECT | | ||
303 | FBINFO_HWACCEL_IMAGEBLIT; | ||
272 | info->fbops = &nouveau_fbcon_ops; | 304 | info->fbops = &nouveau_fbcon_ops; |
273 | info->fix.smem_start = dev->mode_config.fb_base + nvbo->bo.offset - | 305 | info->fix.smem_start = dev->mode_config.fb_base + nvbo->bo.offset - |
274 | dev_priv->vm_vram_base; | 306 | dev_priv->vm_vram_base; |
@@ -316,13 +348,15 @@ nouveau_fbcon_create(struct drm_device *dev, uint32_t fb_width, | |||
316 | par->nouveau_fb = nouveau_fb; | 348 | par->nouveau_fb = nouveau_fb; |
317 | par->dev = dev; | 349 | par->dev = dev; |
318 | 350 | ||
319 | if (dev_priv->channel) { | 351 | if (dev_priv->channel && !nouveau_nofbaccel) { |
320 | switch (dev_priv->card_type) { | 352 | switch (dev_priv->card_type) { |
321 | case NV_50: | 353 | case NV_50: |
322 | nv50_fbcon_accel_init(info); | 354 | nv50_fbcon_accel_init(info); |
355 | info->fbops = &nv50_fbcon_ops; | ||
323 | break; | 356 | break; |
324 | default: | 357 | default: |
325 | nv04_fbcon_accel_init(info); | 358 | nv04_fbcon_accel_init(info); |
359 | info->fbops = &nv04_fbcon_ops; | ||
326 | break; | 360 | break; |
327 | }; | 361 | }; |
328 | } | 362 | } |
diff --git a/drivers/gpu/drm/nouveau/nouveau_fbcon.h b/drivers/gpu/drm/nouveau/nouveau_fbcon.h index 462e0b87b4bd..f9c34e1a8c11 100644 --- a/drivers/gpu/drm/nouveau/nouveau_fbcon.h +++ b/drivers/gpu/drm/nouveau/nouveau_fbcon.h | |||
@@ -40,7 +40,13 @@ int nouveau_fbcon_remove(struct drm_device *dev, struct drm_framebuffer *fb); | |||
40 | void nouveau_fbcon_restore(void); | 40 | void nouveau_fbcon_restore(void); |
41 | void nouveau_fbcon_zfill(struct drm_device *dev); | 41 | void nouveau_fbcon_zfill(struct drm_device *dev); |
42 | 42 | ||
43 | void nv04_fbcon_copyarea(struct fb_info *info, const struct fb_copyarea *region); | ||
44 | void nv04_fbcon_fillrect(struct fb_info *info, const struct fb_fillrect *rect); | ||
45 | void nv04_fbcon_imageblit(struct fb_info *info, const struct fb_image *image); | ||
43 | int nv04_fbcon_accel_init(struct fb_info *info); | 46 | int nv04_fbcon_accel_init(struct fb_info *info); |
47 | void nv50_fbcon_fillrect(struct fb_info *info, const struct fb_fillrect *rect); | ||
48 | void nv50_fbcon_copyarea(struct fb_info *info, const struct fb_copyarea *region); | ||
49 | void nv50_fbcon_imageblit(struct fb_info *info, const struct fb_image *image); | ||
44 | int nv50_fbcon_accel_init(struct fb_info *info); | 50 | int nv50_fbcon_accel_init(struct fb_info *info); |
45 | 51 | ||
46 | void nouveau_fbcon_gpu_lockup(struct fb_info *info); | 52 | void nouveau_fbcon_gpu_lockup(struct fb_info *info); |
diff --git a/drivers/gpu/drm/nouveau/nouveau_gem.c b/drivers/gpu/drm/nouveau/nouveau_gem.c index 6ac804b0c9f9..70cc30803e3b 100644 --- a/drivers/gpu/drm/nouveau/nouveau_gem.c +++ b/drivers/gpu/drm/nouveau/nouveau_gem.c | |||
@@ -925,7 +925,9 @@ nouveau_gem_ioctl_cpu_prep(struct drm_device *dev, void *data, | |||
925 | } | 925 | } |
926 | 926 | ||
927 | if (req->flags & NOUVEAU_GEM_CPU_PREP_NOBLOCK) { | 927 | if (req->flags & NOUVEAU_GEM_CPU_PREP_NOBLOCK) { |
928 | spin_lock(&nvbo->bo.lock); | ||
928 | ret = ttm_bo_wait(&nvbo->bo, false, false, no_wait); | 929 | ret = ttm_bo_wait(&nvbo->bo, false, false, no_wait); |
930 | spin_unlock(&nvbo->bo.lock); | ||
929 | } else { | 931 | } else { |
930 | ret = ttm_bo_synccpu_write_grab(&nvbo->bo, no_wait); | 932 | ret = ttm_bo_synccpu_write_grab(&nvbo->bo, no_wait); |
931 | if (ret == 0) | 933 | if (ret == 0) |
diff --git a/drivers/gpu/drm/nouveau/nouveau_grctx.c b/drivers/gpu/drm/nouveau/nouveau_grctx.c index 419f4c2b3b89..c7ebec696747 100644 --- a/drivers/gpu/drm/nouveau/nouveau_grctx.c +++ b/drivers/gpu/drm/nouveau/nouveau_grctx.c | |||
@@ -97,8 +97,8 @@ nouveau_grctx_prog_load(struct drm_device *dev) | |||
97 | } | 97 | } |
98 | 98 | ||
99 | pgraph->ctxvals = kmalloc(fw->size, GFP_KERNEL); | 99 | pgraph->ctxvals = kmalloc(fw->size, GFP_KERNEL); |
100 | if (!pgraph->ctxprog) { | 100 | if (!pgraph->ctxvals) { |
101 | NV_ERROR(dev, "OOM copying ctxprog\n"); | 101 | NV_ERROR(dev, "OOM copying ctxvals\n"); |
102 | release_firmware(fw); | 102 | release_firmware(fw); |
103 | nouveau_grctx_fini(dev); | 103 | nouveau_grctx_fini(dev); |
104 | return -ENOMEM; | 104 | return -ENOMEM; |
diff --git a/drivers/gpu/drm/nouveau/nouveau_irq.c b/drivers/gpu/drm/nouveau/nouveau_irq.c index 3b9bad66162a..447f9f69d6b1 100644 --- a/drivers/gpu/drm/nouveau/nouveau_irq.c +++ b/drivers/gpu/drm/nouveau/nouveau_irq.c | |||
@@ -211,6 +211,20 @@ nouveau_fifo_irq_handler(struct drm_device *dev) | |||
211 | get + 4); | 211 | get + 4); |
212 | } | 212 | } |
213 | 213 | ||
214 | if (status & NV_PFIFO_INTR_SEMAPHORE) { | ||
215 | uint32_t sem; | ||
216 | |||
217 | status &= ~NV_PFIFO_INTR_SEMAPHORE; | ||
218 | nv_wr32(dev, NV03_PFIFO_INTR_0, | ||
219 | NV_PFIFO_INTR_SEMAPHORE); | ||
220 | |||
221 | sem = nv_rd32(dev, NV10_PFIFO_CACHE1_SEMAPHORE); | ||
222 | nv_wr32(dev, NV10_PFIFO_CACHE1_SEMAPHORE, sem | 0x1); | ||
223 | |||
224 | nv_wr32(dev, NV03_PFIFO_CACHE1_GET, get + 4); | ||
225 | nv_wr32(dev, NV04_PFIFO_CACHE1_PULL0, 1); | ||
226 | } | ||
227 | |||
214 | if (status) { | 228 | if (status) { |
215 | NV_INFO(dev, "PFIFO_INTR 0x%08x - Ch %d\n", | 229 | NV_INFO(dev, "PFIFO_INTR 0x%08x - Ch %d\n", |
216 | status, chid); | 230 | status, chid); |
@@ -566,86 +580,99 @@ nouveau_pgraph_irq_handler(struct drm_device *dev) | |||
566 | static void | 580 | static void |
567 | nv50_pgraph_irq_handler(struct drm_device *dev) | 581 | nv50_pgraph_irq_handler(struct drm_device *dev) |
568 | { | 582 | { |
569 | uint32_t status, nsource; | 583 | uint32_t status; |
570 | 584 | ||
571 | status = nv_rd32(dev, NV03_PGRAPH_INTR); | 585 | while ((status = nv_rd32(dev, NV03_PGRAPH_INTR))) { |
572 | nsource = nv_rd32(dev, NV03_PGRAPH_NSOURCE); | 586 | uint32_t nsource = nv_rd32(dev, NV03_PGRAPH_NSOURCE); |
573 | 587 | ||
574 | if (status & 0x00000001) { | 588 | if (status & 0x00000001) { |
575 | nouveau_pgraph_intr_notify(dev, nsource); | 589 | nouveau_pgraph_intr_notify(dev, nsource); |
576 | status &= ~0x00000001; | 590 | status &= ~0x00000001; |
577 | nv_wr32(dev, NV03_PGRAPH_INTR, 0x00000001); | 591 | nv_wr32(dev, NV03_PGRAPH_INTR, 0x00000001); |
578 | } | 592 | } |
579 | 593 | ||
580 | if (status & 0x00000010) { | 594 | if (status & 0x00000010) { |
581 | nouveau_pgraph_intr_error(dev, nsource | | 595 | nouveau_pgraph_intr_error(dev, nsource | |
582 | NV03_PGRAPH_NSOURCE_ILLEGAL_MTHD); | 596 | NV03_PGRAPH_NSOURCE_ILLEGAL_MTHD); |
583 | 597 | ||
584 | status &= ~0x00000010; | 598 | status &= ~0x00000010; |
585 | nv_wr32(dev, NV03_PGRAPH_INTR, 0x00000010); | 599 | nv_wr32(dev, NV03_PGRAPH_INTR, 0x00000010); |
586 | } | 600 | } |
587 | 601 | ||
588 | if (status & 0x00001000) { | 602 | if (status & 0x00001000) { |
589 | nv_wr32(dev, 0x400500, 0x00000000); | 603 | nv_wr32(dev, 0x400500, 0x00000000); |
590 | nv_wr32(dev, NV03_PGRAPH_INTR, NV_PGRAPH_INTR_CONTEXT_SWITCH); | 604 | nv_wr32(dev, NV03_PGRAPH_INTR, |
591 | nv_wr32(dev, NV40_PGRAPH_INTR_EN, nv_rd32(dev, | 605 | NV_PGRAPH_INTR_CONTEXT_SWITCH); |
592 | NV40_PGRAPH_INTR_EN) & ~NV_PGRAPH_INTR_CONTEXT_SWITCH); | 606 | nv_wr32(dev, NV40_PGRAPH_INTR_EN, nv_rd32(dev, |
593 | nv_wr32(dev, 0x400500, 0x00010001); | 607 | NV40_PGRAPH_INTR_EN) & |
608 | ~NV_PGRAPH_INTR_CONTEXT_SWITCH); | ||
609 | nv_wr32(dev, 0x400500, 0x00010001); | ||
594 | 610 | ||
595 | nv50_graph_context_switch(dev); | 611 | nv50_graph_context_switch(dev); |
596 | 612 | ||
597 | status &= ~NV_PGRAPH_INTR_CONTEXT_SWITCH; | 613 | status &= ~NV_PGRAPH_INTR_CONTEXT_SWITCH; |
598 | } | 614 | } |
599 | 615 | ||
600 | if (status & 0x00100000) { | 616 | if (status & 0x00100000) { |
601 | nouveau_pgraph_intr_error(dev, nsource | | 617 | nouveau_pgraph_intr_error(dev, nsource | |
602 | NV03_PGRAPH_NSOURCE_DATA_ERROR); | 618 | NV03_PGRAPH_NSOURCE_DATA_ERROR); |
603 | 619 | ||
604 | status &= ~0x00100000; | 620 | status &= ~0x00100000; |
605 | nv_wr32(dev, NV03_PGRAPH_INTR, 0x00100000); | 621 | nv_wr32(dev, NV03_PGRAPH_INTR, 0x00100000); |
606 | } | 622 | } |
607 | 623 | ||
608 | if (status & 0x00200000) { | 624 | if (status & 0x00200000) { |
609 | int r; | 625 | int r; |
610 | 626 | ||
611 | nouveau_pgraph_intr_error(dev, nsource | | 627 | nouveau_pgraph_intr_error(dev, nsource | |
612 | NV03_PGRAPH_NSOURCE_PROTECTION_ERROR); | 628 | NV03_PGRAPH_NSOURCE_PROTECTION_ERROR); |
613 | 629 | ||
614 | NV_ERROR(dev, "magic set 1:\n"); | 630 | NV_ERROR(dev, "magic set 1:\n"); |
615 | for (r = 0x408900; r <= 0x408910; r += 4) | 631 | for (r = 0x408900; r <= 0x408910; r += 4) |
616 | NV_ERROR(dev, "\t0x%08x: 0x%08x\n", r, nv_rd32(dev, r)); | 632 | NV_ERROR(dev, "\t0x%08x: 0x%08x\n", r, |
617 | nv_wr32(dev, 0x408900, nv_rd32(dev, 0x408904) | 0xc0000000); | 633 | nv_rd32(dev, r)); |
618 | for (r = 0x408e08; r <= 0x408e24; r += 4) | 634 | nv_wr32(dev, 0x408900, |
619 | NV_ERROR(dev, "\t0x%08x: 0x%08x\n", r, nv_rd32(dev, r)); | 635 | nv_rd32(dev, 0x408904) | 0xc0000000); |
620 | nv_wr32(dev, 0x408e08, nv_rd32(dev, 0x408e08) | 0xc0000000); | 636 | for (r = 0x408e08; r <= 0x408e24; r += 4) |
621 | 637 | NV_ERROR(dev, "\t0x%08x: 0x%08x\n", r, | |
622 | NV_ERROR(dev, "magic set 2:\n"); | 638 | nv_rd32(dev, r)); |
623 | for (r = 0x409900; r <= 0x409910; r += 4) | 639 | nv_wr32(dev, 0x408e08, |
624 | NV_ERROR(dev, "\t0x%08x: 0x%08x\n", r, nv_rd32(dev, r)); | 640 | nv_rd32(dev, 0x408e08) | 0xc0000000); |
625 | nv_wr32(dev, 0x409900, nv_rd32(dev, 0x409904) | 0xc0000000); | 641 | |
626 | for (r = 0x409e08; r <= 0x409e24; r += 4) | 642 | NV_ERROR(dev, "magic set 2:\n"); |
627 | NV_ERROR(dev, "\t0x%08x: 0x%08x\n", r, nv_rd32(dev, r)); | 643 | for (r = 0x409900; r <= 0x409910; r += 4) |
628 | nv_wr32(dev, 0x409e08, nv_rd32(dev, 0x409e08) | 0xc0000000); | 644 | NV_ERROR(dev, "\t0x%08x: 0x%08x\n", r, |
629 | 645 | nv_rd32(dev, r)); | |
630 | status &= ~0x00200000; | 646 | nv_wr32(dev, 0x409900, |
631 | nv_wr32(dev, NV03_PGRAPH_NSOURCE, nsource); | 647 | nv_rd32(dev, 0x409904) | 0xc0000000); |
632 | nv_wr32(dev, NV03_PGRAPH_INTR, 0x00200000); | 648 | for (r = 0x409e08; r <= 0x409e24; r += 4) |
633 | } | 649 | NV_ERROR(dev, "\t0x%08x: 0x%08x\n", r, |
650 | nv_rd32(dev, r)); | ||
651 | nv_wr32(dev, 0x409e08, | ||
652 | nv_rd32(dev, 0x409e08) | 0xc0000000); | ||
653 | |||
654 | status &= ~0x00200000; | ||
655 | nv_wr32(dev, NV03_PGRAPH_NSOURCE, nsource); | ||
656 | nv_wr32(dev, NV03_PGRAPH_INTR, 0x00200000); | ||
657 | } | ||
634 | 658 | ||
635 | if (status) { | 659 | if (status) { |
636 | NV_INFO(dev, "Unhandled PGRAPH_INTR - 0x%08x\n", status); | 660 | NV_INFO(dev, "Unhandled PGRAPH_INTR - 0x%08x\n", |
637 | nv_wr32(dev, NV03_PGRAPH_INTR, status); | 661 | status); |
638 | } | 662 | nv_wr32(dev, NV03_PGRAPH_INTR, status); |
663 | } | ||
639 | 664 | ||
640 | { | 665 | { |
641 | const int isb = (1 << 16) | (1 << 0); | 666 | const int isb = (1 << 16) | (1 << 0); |
642 | 667 | ||
643 | if ((nv_rd32(dev, 0x400500) & isb) != isb) | 668 | if ((nv_rd32(dev, 0x400500) & isb) != isb) |
644 | nv_wr32(dev, 0x400500, nv_rd32(dev, 0x400500) | isb); | 669 | nv_wr32(dev, 0x400500, |
645 | nv_wr32(dev, 0x400824, nv_rd32(dev, 0x400824) & ~(1 << 31)); | 670 | nv_rd32(dev, 0x400500) | isb); |
671 | } | ||
646 | } | 672 | } |
647 | 673 | ||
648 | nv_wr32(dev, NV03_PMC_INTR_0, NV_PMC_INTR_0_PGRAPH_PENDING); | 674 | nv_wr32(dev, NV03_PMC_INTR_0, NV_PMC_INTR_0_PGRAPH_PENDING); |
675 | nv_wr32(dev, 0x400824, nv_rd32(dev, 0x400824) & ~(1 << 31)); | ||
649 | } | 676 | } |
650 | 677 | ||
651 | static void | 678 | static void |
diff --git a/drivers/gpu/drm/nouveau/nouveau_notifier.c b/drivers/gpu/drm/nouveau/nouveau_notifier.c index 6c66a34b6345..d99dc087f9b1 100644 --- a/drivers/gpu/drm/nouveau/nouveau_notifier.c +++ b/drivers/gpu/drm/nouveau/nouveau_notifier.c | |||
@@ -34,15 +34,20 @@ nouveau_notifier_init_channel(struct nouveau_channel *chan) | |||
34 | { | 34 | { |
35 | struct drm_device *dev = chan->dev; | 35 | struct drm_device *dev = chan->dev; |
36 | struct nouveau_bo *ntfy = NULL; | 36 | struct nouveau_bo *ntfy = NULL; |
37 | uint32_t flags; | ||
37 | int ret; | 38 | int ret; |
38 | 39 | ||
39 | ret = nouveau_gem_new(dev, NULL, PAGE_SIZE, 0, nouveau_vram_notify ? | 40 | if (nouveau_vram_notify) |
40 | TTM_PL_FLAG_VRAM : TTM_PL_FLAG_TT, | 41 | flags = TTM_PL_FLAG_VRAM; |
42 | else | ||
43 | flags = TTM_PL_FLAG_TT; | ||
44 | |||
45 | ret = nouveau_gem_new(dev, NULL, PAGE_SIZE, 0, flags, | ||
41 | 0, 0x0000, false, true, &ntfy); | 46 | 0, 0x0000, false, true, &ntfy); |
42 | if (ret) | 47 | if (ret) |
43 | return ret; | 48 | return ret; |
44 | 49 | ||
45 | ret = nouveau_bo_pin(ntfy, TTM_PL_FLAG_VRAM); | 50 | ret = nouveau_bo_pin(ntfy, flags); |
46 | if (ret) | 51 | if (ret) |
47 | goto out_err; | 52 | goto out_err; |
48 | 53 | ||
@@ -128,6 +133,8 @@ nouveau_notifier_alloc(struct nouveau_channel *chan, uint32_t handle, | |||
128 | target = NV_DMA_TARGET_PCI; | 133 | target = NV_DMA_TARGET_PCI; |
129 | } else { | 134 | } else { |
130 | target = NV_DMA_TARGET_AGP; | 135 | target = NV_DMA_TARGET_AGP; |
136 | if (dev_priv->card_type >= NV_50) | ||
137 | offset += dev_priv->vm_gart_base; | ||
131 | } | 138 | } |
132 | } else { | 139 | } else { |
133 | NV_ERROR(dev, "Bad DMA target, mem_type %d!\n", | 140 | NV_ERROR(dev, "Bad DMA target, mem_type %d!\n", |
diff --git a/drivers/gpu/drm/nouveau/nouveau_object.c b/drivers/gpu/drm/nouveau/nouveau_object.c index 6c2cf81716df..e7c100ba63a1 100644 --- a/drivers/gpu/drm/nouveau/nouveau_object.c +++ b/drivers/gpu/drm/nouveau/nouveau_object.c | |||
@@ -885,11 +885,12 @@ int | |||
885 | nouveau_gpuobj_sw_new(struct nouveau_channel *chan, int class, | 885 | nouveau_gpuobj_sw_new(struct nouveau_channel *chan, int class, |
886 | struct nouveau_gpuobj **gpuobj_ret) | 886 | struct nouveau_gpuobj **gpuobj_ret) |
887 | { | 887 | { |
888 | struct drm_nouveau_private *dev_priv = chan->dev->dev_private; | 888 | struct drm_nouveau_private *dev_priv; |
889 | struct nouveau_gpuobj *gpuobj; | 889 | struct nouveau_gpuobj *gpuobj; |
890 | 890 | ||
891 | if (!chan || !gpuobj_ret || *gpuobj_ret != NULL) | 891 | if (!chan || !gpuobj_ret || *gpuobj_ret != NULL) |
892 | return -EINVAL; | 892 | return -EINVAL; |
893 | dev_priv = chan->dev->dev_private; | ||
893 | 894 | ||
894 | gpuobj = kzalloc(sizeof(*gpuobj), GFP_KERNEL); | 895 | gpuobj = kzalloc(sizeof(*gpuobj), GFP_KERNEL); |
895 | if (!gpuobj) | 896 | if (!gpuobj) |
diff --git a/drivers/gpu/drm/nouveau/nouveau_reg.h b/drivers/gpu/drm/nouveau/nouveau_reg.h index 251f1b3b38b9..aa9b310e41be 100644 --- a/drivers/gpu/drm/nouveau/nouveau_reg.h +++ b/drivers/gpu/drm/nouveau/nouveau_reg.h | |||
@@ -99,6 +99,7 @@ | |||
99 | * the card will hang early on in the X init process. | 99 | * the card will hang early on in the X init process. |
100 | */ | 100 | */ |
101 | # define NV_PMC_ENABLE_UNK13 (1<<13) | 101 | # define NV_PMC_ENABLE_UNK13 (1<<13) |
102 | #define NV40_PMC_GRAPH_UNITS 0x00001540 | ||
102 | #define NV40_PMC_BACKLIGHT 0x000015f0 | 103 | #define NV40_PMC_BACKLIGHT 0x000015f0 |
103 | # define NV40_PMC_BACKLIGHT_MASK 0x001f0000 | 104 | # define NV40_PMC_BACKLIGHT_MASK 0x001f0000 |
104 | #define NV40_PMC_1700 0x00001700 | 105 | #define NV40_PMC_1700 0x00001700 |
diff --git a/drivers/gpu/drm/nouveau/nouveau_sgdma.c b/drivers/gpu/drm/nouveau/nouveau_sgdma.c index 4c7f1e403e80..ed1590577b6c 100644 --- a/drivers/gpu/drm/nouveau/nouveau_sgdma.c +++ b/drivers/gpu/drm/nouveau/nouveau_sgdma.c | |||
@@ -54,11 +54,12 @@ static void | |||
54 | nouveau_sgdma_clear(struct ttm_backend *be) | 54 | nouveau_sgdma_clear(struct ttm_backend *be) |
55 | { | 55 | { |
56 | struct nouveau_sgdma_be *nvbe = (struct nouveau_sgdma_be *)be; | 56 | struct nouveau_sgdma_be *nvbe = (struct nouveau_sgdma_be *)be; |
57 | struct drm_device *dev = nvbe->dev; | 57 | struct drm_device *dev; |
58 | |||
59 | NV_DEBUG(nvbe->dev, "\n"); | ||
60 | 58 | ||
61 | if (nvbe && nvbe->pages) { | 59 | if (nvbe && nvbe->pages) { |
60 | dev = nvbe->dev; | ||
61 | NV_DEBUG(dev, "\n"); | ||
62 | |||
62 | if (nvbe->bound) | 63 | if (nvbe->bound) |
63 | be->func->unbind(be); | 64 | be->func->unbind(be); |
64 | 65 | ||
diff --git a/drivers/gpu/drm/nouveau/nouveau_state.c b/drivers/gpu/drm/nouveau/nouveau_state.c index f2d0187ba152..a4851af5b05e 100644 --- a/drivers/gpu/drm/nouveau/nouveau_state.c +++ b/drivers/gpu/drm/nouveau/nouveau_state.c | |||
@@ -310,6 +310,14 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev) | |||
310 | static unsigned int | 310 | static unsigned int |
311 | nouveau_vga_set_decode(void *priv, bool state) | 311 | nouveau_vga_set_decode(void *priv, bool state) |
312 | { | 312 | { |
313 | struct drm_device *dev = priv; | ||
314 | struct drm_nouveau_private *dev_priv = dev->dev_private; | ||
315 | |||
316 | if (dev_priv->chipset >= 0x40) | ||
317 | nv_wr32(dev, 0x88054, state); | ||
318 | else | ||
319 | nv_wr32(dev, 0x1854, state); | ||
320 | |||
313 | if (state) | 321 | if (state) |
314 | return VGA_RSRC_LEGACY_IO | VGA_RSRC_LEGACY_MEM | | 322 | return VGA_RSRC_LEGACY_IO | VGA_RSRC_LEGACY_MEM | |
315 | VGA_RSRC_NORMAL_IO | VGA_RSRC_NORMAL_MEM; | 323 | VGA_RSRC_NORMAL_IO | VGA_RSRC_NORMAL_MEM; |
@@ -427,15 +435,19 @@ nouveau_card_init(struct drm_device *dev) | |||
427 | if (ret) | 435 | if (ret) |
428 | goto out_timer; | 436 | goto out_timer; |
429 | 437 | ||
430 | /* PGRAPH */ | 438 | if (nouveau_noaccel) |
431 | ret = engine->graph.init(dev); | 439 | engine->graph.accel_blocked = true; |
432 | if (ret) | 440 | else { |
433 | goto out_fb; | 441 | /* PGRAPH */ |
442 | ret = engine->graph.init(dev); | ||
443 | if (ret) | ||
444 | goto out_fb; | ||
434 | 445 | ||
435 | /* PFIFO */ | 446 | /* PFIFO */ |
436 | ret = engine->fifo.init(dev); | 447 | ret = engine->fifo.init(dev); |
437 | if (ret) | 448 | if (ret) |
438 | goto out_graph; | 449 | goto out_graph; |
450 | } | ||
439 | 451 | ||
440 | /* this call irq_preinstall, register irq handler and | 452 | /* this call irq_preinstall, register irq handler and |
441 | * call irq_postinstall | 453 | * call irq_postinstall |
@@ -479,9 +491,11 @@ nouveau_card_init(struct drm_device *dev) | |||
479 | out_irq: | 491 | out_irq: |
480 | drm_irq_uninstall(dev); | 492 | drm_irq_uninstall(dev); |
481 | out_fifo: | 493 | out_fifo: |
482 | engine->fifo.takedown(dev); | 494 | if (!nouveau_noaccel) |
495 | engine->fifo.takedown(dev); | ||
483 | out_graph: | 496 | out_graph: |
484 | engine->graph.takedown(dev); | 497 | if (!nouveau_noaccel) |
498 | engine->graph.takedown(dev); | ||
485 | out_fb: | 499 | out_fb: |
486 | engine->fb.takedown(dev); | 500 | engine->fb.takedown(dev); |
487 | out_timer: | 501 | out_timer: |
@@ -518,8 +532,10 @@ static void nouveau_card_takedown(struct drm_device *dev) | |||
518 | dev_priv->channel = NULL; | 532 | dev_priv->channel = NULL; |
519 | } | 533 | } |
520 | 534 | ||
521 | engine->fifo.takedown(dev); | 535 | if (!nouveau_noaccel) { |
522 | engine->graph.takedown(dev); | 536 | engine->fifo.takedown(dev); |
537 | engine->graph.takedown(dev); | ||
538 | } | ||
523 | engine->fb.takedown(dev); | 539 | engine->fb.takedown(dev); |
524 | engine->timer.takedown(dev); | 540 | engine->timer.takedown(dev); |
525 | engine->mc.takedown(dev); | 541 | engine->mc.takedown(dev); |
@@ -817,6 +833,15 @@ int nouveau_ioctl_getparam(struct drm_device *dev, void *data, | |||
817 | case NOUVEAU_GETPARAM_VM_VRAM_BASE: | 833 | case NOUVEAU_GETPARAM_VM_VRAM_BASE: |
818 | getparam->value = dev_priv->vm_vram_base; | 834 | getparam->value = dev_priv->vm_vram_base; |
819 | break; | 835 | break; |
836 | case NOUVEAU_GETPARAM_GRAPH_UNITS: | ||
837 | /* NV40 and NV50 versions are quite different, but register | ||
838 | * address is the same. User is supposed to know the card | ||
839 | * family anyway... */ | ||
840 | if (dev_priv->chipset >= 0x40) { | ||
841 | getparam->value = nv_rd32(dev, NV40_PMC_GRAPH_UNITS); | ||
842 | break; | ||
843 | } | ||
844 | /* FALLTHRU */ | ||
820 | default: | 845 | default: |
821 | NV_ERROR(dev, "unknown parameter %lld\n", getparam->param); | 846 | NV_ERROR(dev, "unknown parameter %lld\n", getparam->param); |
822 | return -EINVAL; | 847 | return -EINVAL; |
diff --git a/drivers/gpu/drm/nouveau/nv04_fbcon.c b/drivers/gpu/drm/nouveau/nv04_fbcon.c index d910873c1368..fd01caabd5c3 100644 --- a/drivers/gpu/drm/nouveau/nv04_fbcon.c +++ b/drivers/gpu/drm/nouveau/nv04_fbcon.c | |||
@@ -27,7 +27,7 @@ | |||
27 | #include "nouveau_dma.h" | 27 | #include "nouveau_dma.h" |
28 | #include "nouveau_fbcon.h" | 28 | #include "nouveau_fbcon.h" |
29 | 29 | ||
30 | static void | 30 | void |
31 | nv04_fbcon_copyarea(struct fb_info *info, const struct fb_copyarea *region) | 31 | nv04_fbcon_copyarea(struct fb_info *info, const struct fb_copyarea *region) |
32 | { | 32 | { |
33 | struct nouveau_fbcon_par *par = info->par; | 33 | struct nouveau_fbcon_par *par = info->par; |
@@ -54,7 +54,7 @@ nv04_fbcon_copyarea(struct fb_info *info, const struct fb_copyarea *region) | |||
54 | FIRE_RING(chan); | 54 | FIRE_RING(chan); |
55 | } | 55 | } |
56 | 56 | ||
57 | static void | 57 | void |
58 | nv04_fbcon_fillrect(struct fb_info *info, const struct fb_fillrect *rect) | 58 | nv04_fbcon_fillrect(struct fb_info *info, const struct fb_fillrect *rect) |
59 | { | 59 | { |
60 | struct nouveau_fbcon_par *par = info->par; | 60 | struct nouveau_fbcon_par *par = info->par; |
@@ -88,7 +88,7 @@ nv04_fbcon_fillrect(struct fb_info *info, const struct fb_fillrect *rect) | |||
88 | FIRE_RING(chan); | 88 | FIRE_RING(chan); |
89 | } | 89 | } |
90 | 90 | ||
91 | static void | 91 | void |
92 | nv04_fbcon_imageblit(struct fb_info *info, const struct fb_image *image) | 92 | nv04_fbcon_imageblit(struct fb_info *info, const struct fb_image *image) |
93 | { | 93 | { |
94 | struct nouveau_fbcon_par *par = info->par; | 94 | struct nouveau_fbcon_par *par = info->par; |
@@ -307,9 +307,6 @@ nv04_fbcon_accel_init(struct fb_info *info) | |||
307 | 307 | ||
308 | FIRE_RING(chan); | 308 | FIRE_RING(chan); |
309 | 309 | ||
310 | info->fbops->fb_fillrect = nv04_fbcon_fillrect; | ||
311 | info->fbops->fb_copyarea = nv04_fbcon_copyarea; | ||
312 | info->fbops->fb_imageblit = nv04_fbcon_imageblit; | ||
313 | return 0; | 310 | return 0; |
314 | } | 311 | } |
315 | 312 | ||
diff --git a/drivers/gpu/drm/nouveau/nv50_crtc.c b/drivers/gpu/drm/nouveau/nv50_crtc.c index 40b7360841f8..d1a651e3400c 100644 --- a/drivers/gpu/drm/nouveau/nv50_crtc.c +++ b/drivers/gpu/drm/nouveau/nv50_crtc.c | |||
@@ -298,14 +298,17 @@ nv50_crtc_set_clock(struct drm_device *dev, int head, int pclk) | |||
298 | static void | 298 | static void |
299 | nv50_crtc_destroy(struct drm_crtc *crtc) | 299 | nv50_crtc_destroy(struct drm_crtc *crtc) |
300 | { | 300 | { |
301 | struct drm_device *dev = crtc->dev; | 301 | struct drm_device *dev; |
302 | struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); | 302 | struct nouveau_crtc *nv_crtc; |
303 | |||
304 | NV_DEBUG_KMS(dev, "\n"); | ||
305 | 303 | ||
306 | if (!crtc) | 304 | if (!crtc) |
307 | return; | 305 | return; |
308 | 306 | ||
307 | dev = crtc->dev; | ||
308 | nv_crtc = nouveau_crtc(crtc); | ||
309 | |||
310 | NV_DEBUG_KMS(dev, "\n"); | ||
311 | |||
309 | drm_crtc_cleanup(&nv_crtc->base); | 312 | drm_crtc_cleanup(&nv_crtc->base); |
310 | 313 | ||
311 | nv50_cursor_fini(nv_crtc); | 314 | nv50_cursor_fini(nv_crtc); |
diff --git a/drivers/gpu/drm/nouveau/nv50_fbcon.c b/drivers/gpu/drm/nouveau/nv50_fbcon.c index e4f279ee61cf..0f57cdf7ccb2 100644 --- a/drivers/gpu/drm/nouveau/nv50_fbcon.c +++ b/drivers/gpu/drm/nouveau/nv50_fbcon.c | |||
@@ -3,7 +3,7 @@ | |||
3 | #include "nouveau_dma.h" | 3 | #include "nouveau_dma.h" |
4 | #include "nouveau_fbcon.h" | 4 | #include "nouveau_fbcon.h" |
5 | 5 | ||
6 | static void | 6 | void |
7 | nv50_fbcon_fillrect(struct fb_info *info, const struct fb_fillrect *rect) | 7 | nv50_fbcon_fillrect(struct fb_info *info, const struct fb_fillrect *rect) |
8 | { | 8 | { |
9 | struct nouveau_fbcon_par *par = info->par; | 9 | struct nouveau_fbcon_par *par = info->par; |
@@ -46,7 +46,7 @@ nv50_fbcon_fillrect(struct fb_info *info, const struct fb_fillrect *rect) | |||
46 | FIRE_RING(chan); | 46 | FIRE_RING(chan); |
47 | } | 47 | } |
48 | 48 | ||
49 | static void | 49 | void |
50 | nv50_fbcon_copyarea(struct fb_info *info, const struct fb_copyarea *region) | 50 | nv50_fbcon_copyarea(struct fb_info *info, const struct fb_copyarea *region) |
51 | { | 51 | { |
52 | struct nouveau_fbcon_par *par = info->par; | 52 | struct nouveau_fbcon_par *par = info->par; |
@@ -81,7 +81,7 @@ nv50_fbcon_copyarea(struct fb_info *info, const struct fb_copyarea *region) | |||
81 | FIRE_RING(chan); | 81 | FIRE_RING(chan); |
82 | } | 82 | } |
83 | 83 | ||
84 | static void | 84 | void |
85 | nv50_fbcon_imageblit(struct fb_info *info, const struct fb_image *image) | 85 | nv50_fbcon_imageblit(struct fb_info *info, const struct fb_image *image) |
86 | { | 86 | { |
87 | struct nouveau_fbcon_par *par = info->par; | 87 | struct nouveau_fbcon_par *par = info->par; |
@@ -262,9 +262,6 @@ nv50_fbcon_accel_init(struct fb_info *info) | |||
262 | OUT_RING(chan, info->fix.smem_start - dev_priv->fb_phys + | 262 | OUT_RING(chan, info->fix.smem_start - dev_priv->fb_phys + |
263 | dev_priv->vm_vram_base); | 263 | dev_priv->vm_vram_base); |
264 | 264 | ||
265 | info->fbops->fb_fillrect = nv50_fbcon_fillrect; | ||
266 | info->fbops->fb_copyarea = nv50_fbcon_copyarea; | ||
267 | info->fbops->fb_imageblit = nv50_fbcon_imageblit; | ||
268 | return 0; | 265 | return 0; |
269 | } | 266 | } |
270 | 267 | ||
diff --git a/drivers/gpu/drm/nouveau/nv50_fifo.c b/drivers/gpu/drm/nouveau/nv50_fifo.c index 32b244bcb482..204a79ff10f4 100644 --- a/drivers/gpu/drm/nouveau/nv50_fifo.c +++ b/drivers/gpu/drm/nouveau/nv50_fifo.c | |||
@@ -317,17 +317,20 @@ void | |||
317 | nv50_fifo_destroy_context(struct nouveau_channel *chan) | 317 | nv50_fifo_destroy_context(struct nouveau_channel *chan) |
318 | { | 318 | { |
319 | struct drm_device *dev = chan->dev; | 319 | struct drm_device *dev = chan->dev; |
320 | struct nouveau_gpuobj_ref *ramfc = chan->ramfc; | ||
320 | 321 | ||
321 | NV_DEBUG(dev, "ch%d\n", chan->id); | 322 | NV_DEBUG(dev, "ch%d\n", chan->id); |
322 | 323 | ||
323 | nouveau_gpuobj_ref_del(dev, &chan->ramfc); | 324 | /* This will ensure the channel is seen as disabled. */ |
324 | nouveau_gpuobj_ref_del(dev, &chan->cache); | 325 | chan->ramfc = NULL; |
325 | |||
326 | nv50_fifo_channel_disable(dev, chan->id, false); | 326 | nv50_fifo_channel_disable(dev, chan->id, false); |
327 | 327 | ||
328 | /* Dummy channel, also used on ch 127 */ | 328 | /* Dummy channel, also used on ch 127 */ |
329 | if (chan->id == 0) | 329 | if (chan->id == 0) |
330 | nv50_fifo_channel_disable(dev, 127, false); | 330 | nv50_fifo_channel_disable(dev, 127, false); |
331 | |||
332 | nouveau_gpuobj_ref_del(dev, &ramfc); | ||
333 | nouveau_gpuobj_ref_del(dev, &chan->cache); | ||
331 | } | 334 | } |
332 | 335 | ||
333 | int | 336 | int |
diff --git a/drivers/gpu/drm/nouveau/nv50_graph.c b/drivers/gpu/drm/nouveau/nv50_graph.c index 20319e59d368..6d504801b514 100644 --- a/drivers/gpu/drm/nouveau/nv50_graph.c +++ b/drivers/gpu/drm/nouveau/nv50_graph.c | |||
@@ -165,6 +165,12 @@ nv50_graph_channel(struct drm_device *dev) | |||
165 | uint32_t inst; | 165 | uint32_t inst; |
166 | int i; | 166 | int i; |
167 | 167 | ||
168 | /* Be sure we're not in the middle of a context switch or bad things | ||
169 | * will happen, such as unloading the wrong pgraph context. | ||
170 | */ | ||
171 | if (!nv_wait(0x400300, 0x00000001, 0x00000000)) | ||
172 | NV_ERROR(dev, "Ctxprog is still running\n"); | ||
173 | |||
168 | inst = nv_rd32(dev, NV50_PGRAPH_CTXCTL_CUR); | 174 | inst = nv_rd32(dev, NV50_PGRAPH_CTXCTL_CUR); |
169 | if (!(inst & NV50_PGRAPH_CTXCTL_CUR_LOADED)) | 175 | if (!(inst & NV50_PGRAPH_CTXCTL_CUR_LOADED)) |
170 | return NULL; | 176 | return NULL; |
@@ -275,7 +281,7 @@ nv50_graph_load_context(struct nouveau_channel *chan) | |||
275 | int | 281 | int |
276 | nv50_graph_unload_context(struct drm_device *dev) | 282 | nv50_graph_unload_context(struct drm_device *dev) |
277 | { | 283 | { |
278 | uint32_t inst, fifo = nv_rd32(dev, 0x400500); | 284 | uint32_t inst; |
279 | 285 | ||
280 | inst = nv_rd32(dev, NV50_PGRAPH_CTXCTL_CUR); | 286 | inst = nv_rd32(dev, NV50_PGRAPH_CTXCTL_CUR); |
281 | if (!(inst & NV50_PGRAPH_CTXCTL_CUR_LOADED)) | 287 | if (!(inst & NV50_PGRAPH_CTXCTL_CUR_LOADED)) |
@@ -283,12 +289,10 @@ nv50_graph_unload_context(struct drm_device *dev) | |||
283 | inst &= NV50_PGRAPH_CTXCTL_CUR_INSTANCE; | 289 | inst &= NV50_PGRAPH_CTXCTL_CUR_INSTANCE; |
284 | 290 | ||
285 | nouveau_wait_for_idle(dev); | 291 | nouveau_wait_for_idle(dev); |
286 | nv_wr32(dev, 0x400500, fifo & ~1); | ||
287 | nv_wr32(dev, 0x400784, inst); | 292 | nv_wr32(dev, 0x400784, inst); |
288 | nv_wr32(dev, 0x400824, nv_rd32(dev, 0x400824) | 0x20); | 293 | nv_wr32(dev, 0x400824, nv_rd32(dev, 0x400824) | 0x20); |
289 | nv_wr32(dev, 0x400304, nv_rd32(dev, 0x400304) | 0x01); | 294 | nv_wr32(dev, 0x400304, nv_rd32(dev, 0x400304) | 0x01); |
290 | nouveau_wait_for_idle(dev); | 295 | nouveau_wait_for_idle(dev); |
291 | nv_wr32(dev, 0x400500, fifo); | ||
292 | 296 | ||
293 | nv_wr32(dev, NV50_PGRAPH_CTXCTL_CUR, inst); | 297 | nv_wr32(dev, NV50_PGRAPH_CTXCTL_CUR, inst); |
294 | return 0; | 298 | return 0; |
diff --git a/drivers/gpu/drm/nouveau/nv50_sor.c b/drivers/gpu/drm/nouveau/nv50_sor.c index ecf1936b8224..c2fff543b06f 100644 --- a/drivers/gpu/drm/nouveau/nv50_sor.c +++ b/drivers/gpu/drm/nouveau/nv50_sor.c | |||
@@ -101,6 +101,7 @@ nv50_sor_dpms(struct drm_encoder *encoder, int mode) | |||
101 | struct nouveau_encoder *nvenc = nouveau_encoder(enc); | 101 | struct nouveau_encoder *nvenc = nouveau_encoder(enc); |
102 | 102 | ||
103 | if (nvenc == nv_encoder || | 103 | if (nvenc == nv_encoder || |
104 | nvenc->disconnect != nv50_sor_disconnect || | ||
104 | nvenc->dcb->or != nv_encoder->dcb->or) | 105 | nvenc->dcb->or != nv_encoder->dcb->or) |
105 | continue; | 106 | continue; |
106 | 107 | ||
diff --git a/drivers/gpu/drm/radeon/Kconfig b/drivers/gpu/drm/radeon/Kconfig index 5982321be4d5..1c02d23f6fcc 100644 --- a/drivers/gpu/drm/radeon/Kconfig +++ b/drivers/gpu/drm/radeon/Kconfig | |||
@@ -1,10 +1,14 @@ | |||
1 | config DRM_RADEON_KMS | 1 | config DRM_RADEON_KMS |
2 | bool "Enable modesetting on radeon by default" | 2 | bool "Enable modesetting on radeon by default - NEW DRIVER" |
3 | depends on DRM_RADEON | 3 | depends on DRM_RADEON |
4 | help | 4 | help |
5 | Choose this option if you want kernel modesetting enabled by default, | 5 | Choose this option if you want kernel modesetting enabled by default. |
6 | and you have a new enough userspace to support this. Running old | 6 | |
7 | userspaces with this enabled will cause pain. | 7 | This is a completely new driver. It's only part of the existing drm |
8 | for compatibility reasons. It requires an entirely different graphics | ||
9 | stack above it and works very differently from the old drm stack. | ||
10 | i.e. don't enable this unless you know what you are doing it may | ||
11 | cause issues or bugs compared to the previous userspace driver stack. | ||
8 | 12 | ||
9 | When kernel modesetting is enabled the IOCTL of radeon/drm | 13 | When kernel modesetting is enabled the IOCTL of radeon/drm |
10 | driver are considered as invalid and an error message is printed | 14 | driver are considered as invalid and an error message is printed |
diff --git a/drivers/gpu/drm/radeon/atombios_dp.c b/drivers/gpu/drm/radeon/atombios_dp.c index 71060114d5de..b32eeea5bb8b 100644 --- a/drivers/gpu/drm/radeon/atombios_dp.c +++ b/drivers/gpu/drm/radeon/atombios_dp.c | |||
@@ -332,11 +332,13 @@ bool radeon_process_aux_ch(struct radeon_i2c_chan *chan, u8 *req_bytes, | |||
332 | PROCESS_AUX_CHANNEL_TRANSACTION_PS_ALLOCATION args; | 332 | PROCESS_AUX_CHANNEL_TRANSACTION_PS_ALLOCATION args; |
333 | int index = GetIndexIntoMasterTable(COMMAND, ProcessAuxChannelTransaction); | 333 | int index = GetIndexIntoMasterTable(COMMAND, ProcessAuxChannelTransaction); |
334 | unsigned char *base; | 334 | unsigned char *base; |
335 | int retry_count = 0; | ||
335 | 336 | ||
336 | memset(&args, 0, sizeof(args)); | 337 | memset(&args, 0, sizeof(args)); |
337 | 338 | ||
338 | base = (unsigned char *)rdev->mode_info.atom_context->scratch; | 339 | base = (unsigned char *)rdev->mode_info.atom_context->scratch; |
339 | 340 | ||
341 | retry: | ||
340 | memcpy(base, req_bytes, num_bytes); | 342 | memcpy(base, req_bytes, num_bytes); |
341 | 343 | ||
342 | args.lpAuxRequest = 0; | 344 | args.lpAuxRequest = 0; |
@@ -347,10 +349,12 @@ bool radeon_process_aux_ch(struct radeon_i2c_chan *chan, u8 *req_bytes, | |||
347 | 349 | ||
348 | atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); | 350 | atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); |
349 | 351 | ||
350 | if (args.ucReplyStatus) { | 352 | if (args.ucReplyStatus && !args.ucDataOutLen) { |
351 | DRM_DEBUG("failed to get auxch %02x%02x %02x %02x 0x%02x %02x\n", | 353 | if (args.ucReplyStatus == 0x20 && retry_count < 10) |
354 | goto retry; | ||
355 | DRM_DEBUG("failed to get auxch %02x%02x %02x %02x 0x%02x %02x after %d retries\n", | ||
352 | req_bytes[1], req_bytes[0], req_bytes[2], req_bytes[3], | 356 | req_bytes[1], req_bytes[0], req_bytes[2], req_bytes[3], |
353 | chan->rec.i2c_id, args.ucReplyStatus); | 357 | chan->rec.i2c_id, args.ucReplyStatus, retry_count); |
354 | return false; | 358 | return false; |
355 | } | 359 | } |
356 | 360 | ||
diff --git a/drivers/gpu/drm/radeon/r600.c b/drivers/gpu/drm/radeon/r600.c index a1198d99cdf9..2ffcf5a03551 100644 --- a/drivers/gpu/drm/radeon/r600.c +++ b/drivers/gpu/drm/radeon/r600.c | |||
@@ -1950,6 +1950,13 @@ int r600_resume(struct radeon_device *rdev) | |||
1950 | DRM_ERROR("radeon: failled testing IB (%d).\n", r); | 1950 | DRM_ERROR("radeon: failled testing IB (%d).\n", r); |
1951 | return r; | 1951 | return r; |
1952 | } | 1952 | } |
1953 | |||
1954 | r = r600_audio_init(rdev); | ||
1955 | if (r) { | ||
1956 | DRM_ERROR("radeon: audio resume failed\n"); | ||
1957 | return r; | ||
1958 | } | ||
1959 | |||
1953 | return r; | 1960 | return r; |
1954 | } | 1961 | } |
1955 | 1962 | ||
@@ -1957,6 +1964,7 @@ int r600_suspend(struct radeon_device *rdev) | |||
1957 | { | 1964 | { |
1958 | int r; | 1965 | int r; |
1959 | 1966 | ||
1967 | r600_audio_fini(rdev); | ||
1960 | /* FIXME: we should wait for ring to be empty */ | 1968 | /* FIXME: we should wait for ring to be empty */ |
1961 | r600_cp_stop(rdev); | 1969 | r600_cp_stop(rdev); |
1962 | rdev->cp.ready = false; | 1970 | rdev->cp.ready = false; |
diff --git a/drivers/gpu/drm/radeon/r600_audio.c b/drivers/gpu/drm/radeon/r600_audio.c index b1c1d3433454..0dcb6904c4ff 100644 --- a/drivers/gpu/drm/radeon/r600_audio.c +++ b/drivers/gpu/drm/radeon/r600_audio.c | |||
@@ -261,7 +261,6 @@ void r600_audio_fini(struct radeon_device *rdev) | |||
261 | if (!r600_audio_chipset_supported(rdev)) | 261 | if (!r600_audio_chipset_supported(rdev)) |
262 | return; | 262 | return; |
263 | 263 | ||
264 | WREG32_P(R600_AUDIO_ENABLE, 0x0, ~0x81000000); | ||
265 | |||
266 | del_timer(&rdev->audio_timer); | 264 | del_timer(&rdev->audio_timer); |
265 | WREG32_P(R600_AUDIO_ENABLE, 0x0, ~0x81000000); | ||
267 | } | 266 | } |
diff --git a/drivers/gpu/drm/radeon/radeon_atombios.c b/drivers/gpu/drm/radeon/radeon_atombios.c index fa82ca74324e..2dcda6115874 100644 --- a/drivers/gpu/drm/radeon/radeon_atombios.c +++ b/drivers/gpu/drm/radeon/radeon_atombios.c | |||
@@ -287,6 +287,15 @@ static bool radeon_atom_apply_quirks(struct drm_device *dev, | |||
287 | *connector_type = DRM_MODE_CONNECTOR_DVID; | 287 | *connector_type = DRM_MODE_CONNECTOR_DVID; |
288 | } | 288 | } |
289 | 289 | ||
290 | /* XFX Pine Group device rv730 reports no VGA DDC lines | ||
291 | * even though they are wired up to record 0x93 | ||
292 | */ | ||
293 | if ((dev->pdev->device == 0x9498) && | ||
294 | (dev->pdev->subsystem_vendor == 0x1682) && | ||
295 | (dev->pdev->subsystem_device == 0x2452)) { | ||
296 | struct radeon_device *rdev = dev->dev_private; | ||
297 | *i2c_bus = radeon_lookup_i2c_gpio(rdev, 0x93); | ||
298 | } | ||
290 | return true; | 299 | return true; |
291 | } | 300 | } |
292 | 301 | ||
diff --git a/drivers/gpu/drm/radeon/radeon_benchmark.c b/drivers/gpu/drm/radeon/radeon_benchmark.c index 4ddfd4b5bc51..7932dc4d6b90 100644 --- a/drivers/gpu/drm/radeon/radeon_benchmark.c +++ b/drivers/gpu/drm/radeon/radeon_benchmark.c | |||
@@ -65,31 +65,42 @@ void radeon_benchmark_move(struct radeon_device *rdev, unsigned bsize, | |||
65 | if (r) { | 65 | if (r) { |
66 | goto out_cleanup; | 66 | goto out_cleanup; |
67 | } | 67 | } |
68 | start_jiffies = jiffies; | 68 | |
69 | for (i = 0; i < n; i++) { | 69 | /* r100 doesn't have dma engine so skip the test */ |
70 | r = radeon_fence_create(rdev, &fence); | 70 | if (rdev->asic->copy_dma) { |
71 | if (r) { | 71 | |
72 | goto out_cleanup; | 72 | start_jiffies = jiffies; |
73 | for (i = 0; i < n; i++) { | ||
74 | r = radeon_fence_create(rdev, &fence); | ||
75 | if (r) { | ||
76 | goto out_cleanup; | ||
77 | } | ||
78 | |||
79 | r = radeon_copy_dma(rdev, saddr, daddr, | ||
80 | size / RADEON_GPU_PAGE_SIZE, fence); | ||
81 | |||
82 | if (r) { | ||
83 | goto out_cleanup; | ||
84 | } | ||
85 | r = radeon_fence_wait(fence, false); | ||
86 | if (r) { | ||
87 | goto out_cleanup; | ||
88 | } | ||
89 | radeon_fence_unref(&fence); | ||
73 | } | 90 | } |
74 | r = radeon_copy_dma(rdev, saddr, daddr, size / RADEON_GPU_PAGE_SIZE, fence); | 91 | end_jiffies = jiffies; |
75 | if (r) { | 92 | time = end_jiffies - start_jiffies; |
76 | goto out_cleanup; | 93 | time = jiffies_to_msecs(time); |
94 | if (time > 0) { | ||
95 | i = ((n * size) >> 10) / time; | ||
96 | printk(KERN_INFO "radeon: dma %u bo moves of %ukb from" | ||
97 | " %d to %d in %lums (%ukb/ms %ukb/s %uM/s)\n", | ||
98 | n, size >> 10, | ||
99 | sdomain, ddomain, time, | ||
100 | i, i * 1000, (i * 1000) / 1024); | ||
77 | } | 101 | } |
78 | r = radeon_fence_wait(fence, false); | ||
79 | if (r) { | ||
80 | goto out_cleanup; | ||
81 | } | ||
82 | radeon_fence_unref(&fence); | ||
83 | } | ||
84 | end_jiffies = jiffies; | ||
85 | time = end_jiffies - start_jiffies; | ||
86 | time = jiffies_to_msecs(time); | ||
87 | if (time > 0) { | ||
88 | i = ((n * size) >> 10) / time; | ||
89 | printk(KERN_INFO "radeon: dma %u bo moves of %ukb from %d to %d" | ||
90 | " in %lums (%ukb/ms %ukb/s %uM/s)\n", n, size >> 10, | ||
91 | sdomain, ddomain, time, i, i * 1000, (i * 1000) / 1024); | ||
92 | } | 102 | } |
103 | |||
93 | start_jiffies = jiffies; | 104 | start_jiffies = jiffies; |
94 | for (i = 0; i < n; i++) { | 105 | for (i = 0; i < n; i++) { |
95 | r = radeon_fence_create(rdev, &fence); | 106 | r = radeon_fence_create(rdev, &fence); |
diff --git a/drivers/gpu/drm/radeon/radeon_connectors.c b/drivers/gpu/drm/radeon/radeon_connectors.c index 2d8e5a70f284..238188540017 100644 --- a/drivers/gpu/drm/radeon/radeon_connectors.c +++ b/drivers/gpu/drm/radeon/radeon_connectors.c | |||
@@ -580,16 +580,18 @@ static enum drm_connector_status radeon_vga_detect(struct drm_connector *connect | |||
580 | struct radeon_connector *radeon_connector = to_radeon_connector(connector); | 580 | struct radeon_connector *radeon_connector = to_radeon_connector(connector); |
581 | struct drm_encoder *encoder; | 581 | struct drm_encoder *encoder; |
582 | struct drm_encoder_helper_funcs *encoder_funcs; | 582 | struct drm_encoder_helper_funcs *encoder_funcs; |
583 | bool dret; | 583 | bool dret = false; |
584 | enum drm_connector_status ret = connector_status_disconnected; | 584 | enum drm_connector_status ret = connector_status_disconnected; |
585 | 585 | ||
586 | encoder = radeon_best_single_encoder(connector); | 586 | encoder = radeon_best_single_encoder(connector); |
587 | if (!encoder) | 587 | if (!encoder) |
588 | ret = connector_status_disconnected; | 588 | ret = connector_status_disconnected; |
589 | 589 | ||
590 | radeon_i2c_do_lock(radeon_connector->ddc_bus, 1); | 590 | if (radeon_connector->ddc_bus) { |
591 | dret = radeon_ddc_probe(radeon_connector); | 591 | radeon_i2c_do_lock(radeon_connector->ddc_bus, 1); |
592 | radeon_i2c_do_lock(radeon_connector->ddc_bus, 0); | 592 | dret = radeon_ddc_probe(radeon_connector); |
593 | radeon_i2c_do_lock(radeon_connector->ddc_bus, 0); | ||
594 | } | ||
593 | if (dret) { | 595 | if (dret) { |
594 | if (radeon_connector->edid) { | 596 | if (radeon_connector->edid) { |
595 | kfree(radeon_connector->edid); | 597 | kfree(radeon_connector->edid); |
@@ -740,11 +742,13 @@ static enum drm_connector_status radeon_dvi_detect(struct drm_connector *connect | |||
740 | struct drm_mode_object *obj; | 742 | struct drm_mode_object *obj; |
741 | int i; | 743 | int i; |
742 | enum drm_connector_status ret = connector_status_disconnected; | 744 | enum drm_connector_status ret = connector_status_disconnected; |
743 | bool dret; | 745 | bool dret = false; |
744 | 746 | ||
745 | radeon_i2c_do_lock(radeon_connector->ddc_bus, 1); | 747 | if (radeon_connector->ddc_bus) { |
746 | dret = radeon_ddc_probe(radeon_connector); | 748 | radeon_i2c_do_lock(radeon_connector->ddc_bus, 1); |
747 | radeon_i2c_do_lock(radeon_connector->ddc_bus, 0); | 749 | dret = radeon_ddc_probe(radeon_connector); |
750 | radeon_i2c_do_lock(radeon_connector->ddc_bus, 0); | ||
751 | } | ||
748 | if (dret) { | 752 | if (dret) { |
749 | if (radeon_connector->edid) { | 753 | if (radeon_connector->edid) { |
750 | kfree(radeon_connector->edid); | 754 | kfree(radeon_connector->edid); |
diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c index 6a92f994cc26..7e17a362b54b 100644 --- a/drivers/gpu/drm/radeon/radeon_display.c +++ b/drivers/gpu/drm/radeon/radeon_display.c | |||
@@ -278,7 +278,7 @@ static void radeon_print_display_setup(struct drm_device *dev) | |||
278 | DRM_INFO(" %s\n", connector_names[connector->connector_type]); | 278 | DRM_INFO(" %s\n", connector_names[connector->connector_type]); |
279 | if (radeon_connector->hpd.hpd != RADEON_HPD_NONE) | 279 | if (radeon_connector->hpd.hpd != RADEON_HPD_NONE) |
280 | DRM_INFO(" %s\n", hpd_names[radeon_connector->hpd.hpd]); | 280 | DRM_INFO(" %s\n", hpd_names[radeon_connector->hpd.hpd]); |
281 | if (radeon_connector->ddc_bus) | 281 | if (radeon_connector->ddc_bus) { |
282 | DRM_INFO(" DDC: 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x\n", | 282 | DRM_INFO(" DDC: 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x\n", |
283 | radeon_connector->ddc_bus->rec.mask_clk_reg, | 283 | radeon_connector->ddc_bus->rec.mask_clk_reg, |
284 | radeon_connector->ddc_bus->rec.mask_data_reg, | 284 | radeon_connector->ddc_bus->rec.mask_data_reg, |
@@ -288,6 +288,15 @@ static void radeon_print_display_setup(struct drm_device *dev) | |||
288 | radeon_connector->ddc_bus->rec.en_data_reg, | 288 | radeon_connector->ddc_bus->rec.en_data_reg, |
289 | radeon_connector->ddc_bus->rec.y_clk_reg, | 289 | radeon_connector->ddc_bus->rec.y_clk_reg, |
290 | radeon_connector->ddc_bus->rec.y_data_reg); | 290 | radeon_connector->ddc_bus->rec.y_data_reg); |
291 | } else { | ||
292 | if (connector->connector_type == DRM_MODE_CONNECTOR_VGA || | ||
293 | connector->connector_type == DRM_MODE_CONNECTOR_DVII || | ||
294 | connector->connector_type == DRM_MODE_CONNECTOR_DVID || | ||
295 | connector->connector_type == DRM_MODE_CONNECTOR_DVIA || | ||
296 | connector->connector_type == DRM_MODE_CONNECTOR_HDMIA || | ||
297 | connector->connector_type == DRM_MODE_CONNECTOR_HDMIB) | ||
298 | DRM_INFO(" DDC: no ddc bus - possible BIOS bug - please report to xorg-driver-ati@lists.x.org\n"); | ||
299 | } | ||
291 | DRM_INFO(" Encoders:\n"); | 300 | DRM_INFO(" Encoders:\n"); |
292 | list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { | 301 | list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { |
293 | radeon_encoder = to_radeon_encoder(encoder); | 302 | radeon_encoder = to_radeon_encoder(encoder); |
diff --git a/drivers/gpu/drm/radeon/radeon_fb.c b/drivers/gpu/drm/radeon/radeon_fb.c index 3ba213d1b06c..d71e346e9ab5 100644 --- a/drivers/gpu/drm/radeon/radeon_fb.c +++ b/drivers/gpu/drm/radeon/radeon_fb.c | |||
@@ -248,7 +248,7 @@ int radeonfb_create(struct drm_device *dev, | |||
248 | if (ret) | 248 | if (ret) |
249 | goto out_unref; | 249 | goto out_unref; |
250 | 250 | ||
251 | memset_io(fbptr, 0xff, aligned_size); | 251 | memset_io(fbptr, 0x0, aligned_size); |
252 | 252 | ||
253 | strcpy(info->fix.id, "radeondrmfb"); | 253 | strcpy(info->fix.id, "radeondrmfb"); |
254 | 254 | ||
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h index 135be9688c90..356dc935ec13 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h | |||
@@ -39,10 +39,10 @@ | |||
39 | #include "ttm/ttm_execbuf_util.h" | 39 | #include "ttm/ttm_execbuf_util.h" |
40 | #include "ttm/ttm_module.h" | 40 | #include "ttm/ttm_module.h" |
41 | 41 | ||
42 | #define VMWGFX_DRIVER_DATE "20090724" | 42 | #define VMWGFX_DRIVER_DATE "20100209" |
43 | #define VMWGFX_DRIVER_MAJOR 0 | 43 | #define VMWGFX_DRIVER_MAJOR 1 |
44 | #define VMWGFX_DRIVER_MINOR 1 | 44 | #define VMWGFX_DRIVER_MINOR 0 |
45 | #define VMWGFX_DRIVER_PATCHLEVEL 2 | 45 | #define VMWGFX_DRIVER_PATCHLEVEL 0 |
46 | #define VMWGFX_FILE_PAGE_OFFSET 0x00100000 | 46 | #define VMWGFX_FILE_PAGE_OFFSET 0x00100000 |
47 | #define VMWGFX_FIFO_STATIC_SIZE (1024*1024) | 47 | #define VMWGFX_FIFO_STATIC_SIZE (1024*1024) |
48 | #define VMWGFX_MAX_RELOCATIONS 2048 | 48 | #define VMWGFX_MAX_RELOCATIONS 2048 |
@@ -113,6 +113,7 @@ struct vmw_fifo_state { | |||
113 | unsigned long static_buffer_size; | 113 | unsigned long static_buffer_size; |
114 | bool using_bounce_buffer; | 114 | bool using_bounce_buffer; |
115 | uint32_t capabilities; | 115 | uint32_t capabilities; |
116 | struct mutex fifo_mutex; | ||
116 | struct rw_semaphore rwsem; | 117 | struct rw_semaphore rwsem; |
117 | }; | 118 | }; |
118 | 119 | ||
@@ -213,7 +214,7 @@ struct vmw_private { | |||
213 | * Fencing and IRQs. | 214 | * Fencing and IRQs. |
214 | */ | 215 | */ |
215 | 216 | ||
216 | uint32_t fence_seq; | 217 | atomic_t fence_seq; |
217 | wait_queue_head_t fence_queue; | 218 | wait_queue_head_t fence_queue; |
218 | wait_queue_head_t fifo_queue; | 219 | wait_queue_head_t fifo_queue; |
219 | atomic_t fence_queue_waiters; | 220 | atomic_t fence_queue_waiters; |
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_fifo.c b/drivers/gpu/drm/vmwgfx/vmwgfx_fifo.c index 4157547cc6e4..39d43a01d846 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_fifo.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_fifo.c | |||
@@ -74,6 +74,7 @@ int vmw_fifo_init(struct vmw_private *dev_priv, struct vmw_fifo_state *fifo) | |||
74 | fifo->reserved_size = 0; | 74 | fifo->reserved_size = 0; |
75 | fifo->using_bounce_buffer = false; | 75 | fifo->using_bounce_buffer = false; |
76 | 76 | ||
77 | mutex_init(&fifo->fifo_mutex); | ||
77 | init_rwsem(&fifo->rwsem); | 78 | init_rwsem(&fifo->rwsem); |
78 | 79 | ||
79 | /* | 80 | /* |
@@ -117,7 +118,7 @@ int vmw_fifo_init(struct vmw_private *dev_priv, struct vmw_fifo_state *fifo) | |||
117 | (unsigned int) min, | 118 | (unsigned int) min, |
118 | (unsigned int) fifo->capabilities); | 119 | (unsigned int) fifo->capabilities); |
119 | 120 | ||
120 | dev_priv->fence_seq = dev_priv->last_read_sequence; | 121 | atomic_set(&dev_priv->fence_seq, dev_priv->last_read_sequence); |
121 | iowrite32(dev_priv->last_read_sequence, fifo_mem + SVGA_FIFO_FENCE); | 122 | iowrite32(dev_priv->last_read_sequence, fifo_mem + SVGA_FIFO_FENCE); |
122 | 123 | ||
123 | return vmw_fifo_send_fence(dev_priv, &dummy); | 124 | return vmw_fifo_send_fence(dev_priv, &dummy); |
@@ -283,7 +284,7 @@ void *vmw_fifo_reserve(struct vmw_private *dev_priv, uint32_t bytes) | |||
283 | uint32_t reserveable = fifo_state->capabilities & SVGA_FIFO_CAP_RESERVE; | 284 | uint32_t reserveable = fifo_state->capabilities & SVGA_FIFO_CAP_RESERVE; |
284 | int ret; | 285 | int ret; |
285 | 286 | ||
286 | down_write(&fifo_state->rwsem); | 287 | mutex_lock(&fifo_state->fifo_mutex); |
287 | max = ioread32(fifo_mem + SVGA_FIFO_MAX); | 288 | max = ioread32(fifo_mem + SVGA_FIFO_MAX); |
288 | min = ioread32(fifo_mem + SVGA_FIFO_MIN); | 289 | min = ioread32(fifo_mem + SVGA_FIFO_MIN); |
289 | next_cmd = ioread32(fifo_mem + SVGA_FIFO_NEXT_CMD); | 290 | next_cmd = ioread32(fifo_mem + SVGA_FIFO_NEXT_CMD); |
@@ -351,7 +352,7 @@ void *vmw_fifo_reserve(struct vmw_private *dev_priv, uint32_t bytes) | |||
351 | } | 352 | } |
352 | out_err: | 353 | out_err: |
353 | fifo_state->reserved_size = 0; | 354 | fifo_state->reserved_size = 0; |
354 | up_write(&fifo_state->rwsem); | 355 | mutex_unlock(&fifo_state->fifo_mutex); |
355 | return NULL; | 356 | return NULL; |
356 | } | 357 | } |
357 | 358 | ||
@@ -426,6 +427,7 @@ void vmw_fifo_commit(struct vmw_private *dev_priv, uint32_t bytes) | |||
426 | 427 | ||
427 | } | 428 | } |
428 | 429 | ||
430 | down_write(&fifo_state->rwsem); | ||
429 | if (fifo_state->using_bounce_buffer || reserveable) { | 431 | if (fifo_state->using_bounce_buffer || reserveable) { |
430 | next_cmd += bytes; | 432 | next_cmd += bytes; |
431 | if (next_cmd >= max) | 433 | if (next_cmd >= max) |
@@ -437,8 +439,9 @@ void vmw_fifo_commit(struct vmw_private *dev_priv, uint32_t bytes) | |||
437 | if (reserveable) | 439 | if (reserveable) |
438 | iowrite32(0, fifo_mem + SVGA_FIFO_RESERVED); | 440 | iowrite32(0, fifo_mem + SVGA_FIFO_RESERVED); |
439 | mb(); | 441 | mb(); |
440 | vmw_fifo_ping_host(dev_priv, SVGA_SYNC_GENERIC); | ||
441 | up_write(&fifo_state->rwsem); | 442 | up_write(&fifo_state->rwsem); |
443 | vmw_fifo_ping_host(dev_priv, SVGA_SYNC_GENERIC); | ||
444 | mutex_unlock(&fifo_state->fifo_mutex); | ||
442 | } | 445 | } |
443 | 446 | ||
444 | int vmw_fifo_send_fence(struct vmw_private *dev_priv, uint32_t *sequence) | 447 | int vmw_fifo_send_fence(struct vmw_private *dev_priv, uint32_t *sequence) |
@@ -451,9 +454,7 @@ int vmw_fifo_send_fence(struct vmw_private *dev_priv, uint32_t *sequence) | |||
451 | 454 | ||
452 | fm = vmw_fifo_reserve(dev_priv, bytes); | 455 | fm = vmw_fifo_reserve(dev_priv, bytes); |
453 | if (unlikely(fm == NULL)) { | 456 | if (unlikely(fm == NULL)) { |
454 | down_write(&fifo_state->rwsem); | 457 | *sequence = atomic_read(&dev_priv->fence_seq); |
455 | *sequence = dev_priv->fence_seq; | ||
456 | up_write(&fifo_state->rwsem); | ||
457 | ret = -ENOMEM; | 458 | ret = -ENOMEM; |
458 | (void)vmw_fallback_wait(dev_priv, false, true, *sequence, | 459 | (void)vmw_fallback_wait(dev_priv, false, true, *sequence, |
459 | false, 3*HZ); | 460 | false, 3*HZ); |
@@ -461,7 +462,7 @@ int vmw_fifo_send_fence(struct vmw_private *dev_priv, uint32_t *sequence) | |||
461 | } | 462 | } |
462 | 463 | ||
463 | do { | 464 | do { |
464 | *sequence = dev_priv->fence_seq++; | 465 | *sequence = atomic_add_return(1, &dev_priv->fence_seq); |
465 | } while (*sequence == 0); | 466 | } while (*sequence == 0); |
466 | 467 | ||
467 | if (!(fifo_state->capabilities & SVGA_FIFO_CAP_FENCE)) { | 468 | if (!(fifo_state->capabilities & SVGA_FIFO_CAP_FENCE)) { |
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_ioctl.c b/drivers/gpu/drm/vmwgfx/vmwgfx_ioctl.c index 778851f9f1d6..1c7a316454d8 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_ioctl.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_ioctl.c | |||
@@ -48,6 +48,12 @@ int vmw_getparam_ioctl(struct drm_device *dev, void *data, | |||
48 | case DRM_VMW_PARAM_FIFO_OFFSET: | 48 | case DRM_VMW_PARAM_FIFO_OFFSET: |
49 | param->value = dev_priv->mmio_start; | 49 | param->value = dev_priv->mmio_start; |
50 | break; | 50 | break; |
51 | case DRM_VMW_PARAM_HW_CAPS: | ||
52 | param->value = dev_priv->capabilities; | ||
53 | break; | ||
54 | case DRM_VMW_PARAM_FIFO_CAPS: | ||
55 | param->value = dev_priv->fifo.capabilities; | ||
56 | break; | ||
51 | default: | 57 | default: |
52 | DRM_ERROR("Illegal vmwgfx get param request: %d\n", | 58 | DRM_ERROR("Illegal vmwgfx get param request: %d\n", |
53 | param->param); | 59 | param->param); |
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_irq.c b/drivers/gpu/drm/vmwgfx/vmwgfx_irq.c index d40086fc8647..4d7cb5393860 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_irq.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_irq.c | |||
@@ -85,19 +85,12 @@ bool vmw_fence_signaled(struct vmw_private *dev_priv, | |||
85 | return true; | 85 | return true; |
86 | 86 | ||
87 | /** | 87 | /** |
88 | * Below is to signal stale fences that have wrapped. | ||
89 | * First, block fence submission. | ||
90 | */ | ||
91 | |||
92 | down_read(&fifo_state->rwsem); | ||
93 | |||
94 | /** | ||
95 | * Then check if the sequence is higher than what we've actually | 88 | * Then check if the sequence is higher than what we've actually |
96 | * emitted. Then the fence is stale and signaled. | 89 | * emitted. Then the fence is stale and signaled. |
97 | */ | 90 | */ |
98 | 91 | ||
99 | ret = ((dev_priv->fence_seq - sequence) > VMW_FENCE_WRAP); | 92 | ret = ((atomic_read(&dev_priv->fence_seq) - sequence) |
100 | up_read(&fifo_state->rwsem); | 93 | > VMW_FENCE_WRAP); |
101 | 94 | ||
102 | return ret; | 95 | return ret; |
103 | } | 96 | } |
@@ -127,7 +120,7 @@ int vmw_fallback_wait(struct vmw_private *dev_priv, | |||
127 | 120 | ||
128 | if (fifo_idle) | 121 | if (fifo_idle) |
129 | down_read(&fifo_state->rwsem); | 122 | down_read(&fifo_state->rwsem); |
130 | signal_seq = dev_priv->fence_seq; | 123 | signal_seq = atomic_read(&dev_priv->fence_seq); |
131 | ret = 0; | 124 | ret = 0; |
132 | 125 | ||
133 | for (;;) { | 126 | for (;;) { |
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c index eeba6d1d06e4..31f9afed0a63 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c | |||
@@ -769,10 +769,10 @@ int vmw_kms_init(struct vmw_private *dev_priv) | |||
769 | 769 | ||
770 | drm_mode_config_init(dev); | 770 | drm_mode_config_init(dev); |
771 | dev->mode_config.funcs = &vmw_kms_funcs; | 771 | dev->mode_config.funcs = &vmw_kms_funcs; |
772 | dev->mode_config.min_width = 640; | 772 | dev->mode_config.min_width = 1; |
773 | dev->mode_config.min_height = 480; | 773 | dev->mode_config.min_height = 1; |
774 | dev->mode_config.max_width = 2048; | 774 | dev->mode_config.max_width = dev_priv->fb_max_width; |
775 | dev->mode_config.max_height = 2048; | 775 | dev->mode_config.max_height = dev_priv->fb_max_height; |
776 | 776 | ||
777 | ret = vmw_kms_init_legacy_display_system(dev_priv); | 777 | ret = vmw_kms_init_legacy_display_system(dev_priv); |
778 | 778 | ||
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c b/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c index c7efbd47ab84..f8fbbc67a406 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c | |||
@@ -35,11 +35,6 @@ | |||
35 | #define VMW_RES_SURFACE ttm_driver_type1 | 35 | #define VMW_RES_SURFACE ttm_driver_type1 |
36 | #define VMW_RES_STREAM ttm_driver_type2 | 36 | #define VMW_RES_STREAM ttm_driver_type2 |
37 | 37 | ||
38 | /* XXX: This isn't a real hardware flag, but just a hack for kernel to | ||
39 | * know about primary surfaces. Find a better way to accomplish this. | ||
40 | */ | ||
41 | #define SVGA3D_SURFACE_HINT_SCANOUT (1 << 9) | ||
42 | |||
43 | struct vmw_user_context { | 38 | struct vmw_user_context { |
44 | struct ttm_base_object base; | 39 | struct ttm_base_object base; |
45 | struct vmw_resource res; | 40 | struct vmw_resource res; |
@@ -579,6 +574,7 @@ int vmw_surface_define_ioctl(struct drm_device *dev, void *data, | |||
579 | 574 | ||
580 | srf->flags = req->flags; | 575 | srf->flags = req->flags; |
581 | srf->format = req->format; | 576 | srf->format = req->format; |
577 | srf->scanout = req->scanout; | ||
582 | memcpy(srf->mip_levels, req->mip_levels, sizeof(srf->mip_levels)); | 578 | memcpy(srf->mip_levels, req->mip_levels, sizeof(srf->mip_levels)); |
583 | srf->num_sizes = 0; | 579 | srf->num_sizes = 0; |
584 | for (i = 0; i < DRM_VMW_MAX_SURFACE_FACES; ++i) | 580 | for (i = 0; i < DRM_VMW_MAX_SURFACE_FACES; ++i) |
@@ -604,16 +600,6 @@ int vmw_surface_define_ioctl(struct drm_device *dev, void *data, | |||
604 | if (unlikely(ret != 0)) | 600 | if (unlikely(ret != 0)) |
605 | goto out_err1; | 601 | goto out_err1; |
606 | 602 | ||
607 | if (srf->flags & SVGA3D_SURFACE_HINT_SCANOUT) { | ||
608 | /* we should not send this flag down to hardware since | ||
609 | * its not a official one | ||
610 | */ | ||
611 | srf->flags &= ~SVGA3D_SURFACE_HINT_SCANOUT; | ||
612 | srf->scanout = true; | ||
613 | } else { | ||
614 | srf->scanout = false; | ||
615 | } | ||
616 | |||
617 | if (srf->scanout && | 603 | if (srf->scanout && |
618 | srf->num_sizes == 1 && | 604 | srf->num_sizes == 1 && |
619 | srf->sizes[0].width == 64 && | 605 | srf->sizes[0].width == 64 && |
diff --git a/drivers/gpu/vga/vgaarb.c b/drivers/gpu/vga/vgaarb.c index 1ac0c93603c9..24b56dc54597 100644 --- a/drivers/gpu/vga/vgaarb.c +++ b/drivers/gpu/vga/vgaarb.c | |||
@@ -961,7 +961,7 @@ static ssize_t vga_arb_write(struct file *file, const char __user * buf, | |||
961 | remaining -= 7; | 961 | remaining -= 7; |
962 | pr_devel("client 0x%p called 'target'\n", priv); | 962 | pr_devel("client 0x%p called 'target'\n", priv); |
963 | /* if target is default */ | 963 | /* if target is default */ |
964 | if (!strncmp(buf, "default", 7)) | 964 | if (!strncmp(kbuf, "default", 7)) |
965 | pdev = pci_dev_get(vga_default_device()); | 965 | pdev = pci_dev_get(vga_default_device()); |
966 | else { | 966 | else { |
967 | if (!vga_pci_str_to_vars(curr_pos, remaining, | 967 | if (!vga_pci_str_to_vars(curr_pos, remaining, |
diff --git a/include/drm/nouveau_drm.h b/include/drm/nouveau_drm.h index 1e67c441ea82..f745948b61e4 100644 --- a/include/drm/nouveau_drm.h +++ b/include/drm/nouveau_drm.h | |||
@@ -77,6 +77,7 @@ struct drm_nouveau_gpuobj_free { | |||
77 | #define NOUVEAU_GETPARAM_PCI_PHYSICAL 10 | 77 | #define NOUVEAU_GETPARAM_PCI_PHYSICAL 10 |
78 | #define NOUVEAU_GETPARAM_CHIPSET_ID 11 | 78 | #define NOUVEAU_GETPARAM_CHIPSET_ID 11 |
79 | #define NOUVEAU_GETPARAM_VM_VRAM_BASE 12 | 79 | #define NOUVEAU_GETPARAM_VM_VRAM_BASE 12 |
80 | #define NOUVEAU_GETPARAM_GRAPH_UNITS 13 | ||
80 | struct drm_nouveau_getparam { | 81 | struct drm_nouveau_getparam { |
81 | uint64_t param; | 82 | uint64_t param; |
82 | uint64_t value; | 83 | uint64_t value; |
diff --git a/include/drm/vmwgfx_drm.h b/include/drm/vmwgfx_drm.h index 2be7e1249b6f..c7645f480d12 100644 --- a/include/drm/vmwgfx_drm.h +++ b/include/drm/vmwgfx_drm.h | |||
@@ -68,7 +68,8 @@ | |||
68 | #define DRM_VMW_PARAM_NUM_FREE_STREAMS 1 | 68 | #define DRM_VMW_PARAM_NUM_FREE_STREAMS 1 |
69 | #define DRM_VMW_PARAM_3D 2 | 69 | #define DRM_VMW_PARAM_3D 2 |
70 | #define DRM_VMW_PARAM_FIFO_OFFSET 3 | 70 | #define DRM_VMW_PARAM_FIFO_OFFSET 3 |
71 | 71 | #define DRM_VMW_PARAM_HW_CAPS 4 | |
72 | #define DRM_VMW_PARAM_FIFO_CAPS 5 | ||
72 | 73 | ||
73 | /** | 74 | /** |
74 | * struct drm_vmw_getparam_arg | 75 | * struct drm_vmw_getparam_arg |
@@ -181,6 +182,8 @@ struct drm_vmw_context_arg { | |||
181 | * The size of the array should equal the total number of mipmap levels. | 182 | * The size of the array should equal the total number of mipmap levels. |
182 | * @shareable: Boolean whether other clients (as identified by file descriptors) | 183 | * @shareable: Boolean whether other clients (as identified by file descriptors) |
183 | * may reference this surface. | 184 | * may reference this surface. |
185 | * @scanout: Boolean whether the surface is intended to be used as a | ||
186 | * scanout. | ||
184 | * | 187 | * |
185 | * Input data to the DRM_VMW_CREATE_SURFACE Ioctl. | 188 | * Input data to the DRM_VMW_CREATE_SURFACE Ioctl. |
186 | * Output data from the DRM_VMW_REF_SURFACE Ioctl. | 189 | * Output data from the DRM_VMW_REF_SURFACE Ioctl. |
@@ -192,7 +195,7 @@ struct drm_vmw_surface_create_req { | |||
192 | uint32_t mip_levels[DRM_VMW_MAX_SURFACE_FACES]; | 195 | uint32_t mip_levels[DRM_VMW_MAX_SURFACE_FACES]; |
193 | uint64_t size_addr; | 196 | uint64_t size_addr; |
194 | int32_t shareable; | 197 | int32_t shareable; |
195 | uint32_t pad64; | 198 | int32_t scanout; |
196 | }; | 199 | }; |
197 | 200 | ||
198 | /** | 201 | /** |
@@ -295,17 +298,28 @@ union drm_vmw_surface_reference_arg { | |||
295 | * | 298 | * |
296 | * @commands: User-space address of a command buffer cast to an uint64_t. | 299 | * @commands: User-space address of a command buffer cast to an uint64_t. |
297 | * @command-size: Size in bytes of the command buffer. | 300 | * @command-size: Size in bytes of the command buffer. |
301 | * @throttle-us: Sleep until software is less than @throttle_us | ||
302 | * microseconds ahead of hardware. The driver may round this value | ||
303 | * to the nearest kernel tick. | ||
298 | * @fence_rep: User-space address of a struct drm_vmw_fence_rep cast to an | 304 | * @fence_rep: User-space address of a struct drm_vmw_fence_rep cast to an |
299 | * uint64_t. | 305 | * uint64_t. |
306 | * @version: Allows expanding the execbuf ioctl parameters without breaking | ||
307 | * backwards compatibility, since user-space will always tell the kernel | ||
308 | * which version it uses. | ||
309 | * @flags: Execbuf flags. None currently. | ||
300 | * | 310 | * |
301 | * Argument to the DRM_VMW_EXECBUF Ioctl. | 311 | * Argument to the DRM_VMW_EXECBUF Ioctl. |
302 | */ | 312 | */ |
303 | 313 | ||
314 | #define DRM_VMW_EXECBUF_VERSION 0 | ||
315 | |||
304 | struct drm_vmw_execbuf_arg { | 316 | struct drm_vmw_execbuf_arg { |
305 | uint64_t commands; | 317 | uint64_t commands; |
306 | uint32_t command_size; | 318 | uint32_t command_size; |
307 | uint32_t pad64; | 319 | uint32_t throttle_us; |
308 | uint64_t fence_rep; | 320 | uint64_t fence_rep; |
321 | uint32_t version; | ||
322 | uint32_t flags; | ||
309 | }; | 323 | }; |
310 | 324 | ||
311 | /** | 325 | /** |