aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBen Skeggs <bskeggs@redhat.com>2010-09-18 08:13:04 -0400
committerBen Skeggs <bskeggs@redhat.com>2010-09-24 02:27:48 -0400
commit07b1266962085412e85af2e7df471ec9ed0c35f5 (patch)
tree5b200821f274126a28365ad19f004160e2e928f7
parente022878571690e09e965e8c6bfc837b3dc5b6b74 (diff)
drm/nouveau: fix potential accuracy loss when parsing perf 0x1c tables
Reported-by: Roy Spliet <r.spliet@student.tudelft.nl> Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_perf.c34
1 files changed, 14 insertions, 20 deletions
diff --git a/drivers/gpu/drm/nouveau/nouveau_perf.c b/drivers/gpu/drm/nouveau/nouveau_perf.c
index a882a366487f..a397420e46c6 100644
--- a/drivers/gpu/drm/nouveau/nouveau_perf.c
+++ b/drivers/gpu/drm/nouveau/nouveau_perf.c
@@ -90,50 +90,44 @@ nouveau_perf_init(struct drm_device *dev)
90 case 0x15: 90 case 0x15:
91 perflvl->fanspeed = entry[55]; 91 perflvl->fanspeed = entry[55];
92 perflvl->voltage = entry[56]; 92 perflvl->voltage = entry[56];
93 perflvl->core = ROM32(entry[1]) / 100; 93 perflvl->core = ROM32(entry[1]) * 10;
94 perflvl->memory = ROM32(entry[5]) / 100; 94 perflvl->memory = ROM32(entry[5]) * 10;
95 break; 95 break;
96 case 0x21: 96 case 0x21:
97 case 0x23: 97 case 0x23:
98 case 0x24: 98 case 0x24:
99 perflvl->fanspeed = entry[4]; 99 perflvl->fanspeed = entry[4];
100 perflvl->voltage = entry[5]; 100 perflvl->voltage = entry[5];
101 perflvl->core = ROM16(entry[6]); 101 perflvl->core = ROM16(entry[6]) * 1000;
102 perflvl->memory = ROM16(entry[11]); 102 perflvl->memory = ROM16(entry[11]) * 1000;
103 break; 103 break;
104 case 0x25: 104 case 0x25:
105 perflvl->fanspeed = entry[4]; 105 perflvl->fanspeed = entry[4];
106 perflvl->voltage = entry[5]; 106 perflvl->voltage = entry[5];
107 perflvl->core = ROM16(entry[6]); 107 perflvl->core = ROM16(entry[6]) * 1000;
108 perflvl->shader = ROM16(entry[10]); 108 perflvl->shader = ROM16(entry[10]) * 1000;
109 perflvl->memory = ROM16(entry[12]); 109 perflvl->memory = ROM16(entry[12]) * 1000;
110 break; 110 break;
111 case 0x30: 111 case 0x30:
112 case 0x35: 112 case 0x35:
113 perflvl->fanspeed = entry[6]; 113 perflvl->fanspeed = entry[6];
114 perflvl->voltage = entry[7]; 114 perflvl->voltage = entry[7];
115 perflvl->core = ROM16(entry[8]); 115 perflvl->core = ROM16(entry[8]) * 1000;
116 perflvl->shader = ROM16(entry[10]); 116 perflvl->shader = ROM16(entry[10]) * 1000;
117 perflvl->memory = ROM16(entry[12]); 117 perflvl->memory = ROM16(entry[12]) * 1000;
118 /*XXX: confirm on 0x35 */ 118 /*XXX: confirm on 0x35 */
119 perflvl->unk05 = ROM16(entry[16]); 119 perflvl->unk05 = ROM16(entry[16]) * 1000;
120 break; 120 break;
121 case 0x40: 121 case 0x40:
122#define subent(n) entry[perf[2] + ((n) * perf[3])] 122#define subent(n) entry[perf[2] + ((n) * perf[3])]
123 perflvl->fanspeed = 0; /*XXX*/ 123 perflvl->fanspeed = 0; /*XXX*/
124 perflvl->voltage = 0; /*XXX: entry[2] */; 124 perflvl->voltage = 0; /*XXX: entry[2] */;
125 perflvl->core = ROM16(subent(0)) & 0xfff; 125 perflvl->core = (ROM16(subent(0)) & 0xfff) * 1000;
126 perflvl->shader = ROM16(subent(1)) & 0xfff; 126 perflvl->shader = (ROM16(subent(1)) & 0xfff) * 1000;
127 perflvl->memory = ROM16(subent(2)) & 0xfff; 127 perflvl->memory = (ROM16(subent(2)) & 0xfff) * 1000;
128 break; 128 break;
129 } 129 }
130 130
131 /* convert MHz -> KHz, it's more convenient */
132 perflvl->core *= 1000;
133 perflvl->memory *= 1000;
134 perflvl->shader *= 1000;
135 perflvl->unk05 *= 1000;
136
137 /* make sure vid is valid */ 131 /* make sure vid is valid */
138 if (pm->voltage.supported && perflvl->voltage) { 132 if (pm->voltage.supported && perflvl->voltage) {
139 vid = nouveau_volt_vid_lookup(dev, perflvl->voltage); 133 vid = nouveau_volt_vid_lookup(dev, perflvl->voltage);