Skip to content

Commit d57cd91

Browse files
committed
Implement ATI ADL support for GPU parameter monitoring now and setting later (temp, fan, clocks etc.).
Check for the presence of the ADL header files in ADL_SDK. Import adl_functions.h from amd overdrive ctrl. Implement a setup function that tries to detect GPUs that support the ADL and link in the parameters into the gpus struct. Put a summary of monitoring information from the GPU menu.
1 parent 690ab48 commit d57cd91

File tree

9 files changed

+671
-2
lines changed

9 files changed

+671
-2
lines changed

ADL_SDK/.gitignore

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
adl_defines.h
2+
adl_sdk.h
3+
adl_structures.h

ADL_SDK/readme.txt

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Please insert AMD ADL files adl_defines.h adl_sdk.h adl_structures.h here.
2+
(http://developer.amd.com/gpu/adlsdk/Pages/default.aspx)

Makefile.am

+1
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ cgminer_SOURCES = elist.h miner.h compat.h bench_block.h \
2323
sha256_generic.c sha256_4way.c sha256_via.c \
2424
sha256_cryptopp.c sha256_sse2_amd64.c \
2525
sha256_sse4_amd64.c sha256_sse2_i386.c \
26+
adl.c \
2627
phatk110817.cl poclbm110817.cl
2728

2829
cgminer_LDFLAGS = $(PTHREAD_FLAGS)

adl.c

+314
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,314 @@
1+
#include "miner.h"
2+
#include "adl.h"
3+
#ifdef HAVE_ADL
4+
#if defined (__linux)
5+
#include "ADL_SDK/adl_sdk.h"
6+
#include <dlfcn.h>
7+
#include <stdlib.h>
8+
#include <unistd.h>
9+
#else
10+
#include <windows.h>
11+
#include <tchar.h>
12+
#include "ADL_SDK/adl_sdk.h"
13+
#endif
14+
15+
#include <stdio.h>
16+
17+
#include "adl_functions.h"
18+
19+
// Memory allocation function
20+
static void * __stdcall ADL_Main_Memory_Alloc(int iSize)
21+
{
22+
void *lpBuffer = malloc(iSize);
23+
24+
return lpBuffer;
25+
}
26+
27+
// Optional Memory de-allocation function
28+
static void __stdcall ADL_Main_Memory_Free (void **lpBuffer)
29+
{
30+
if (*lpBuffer) {
31+
free (*lpBuffer);
32+
*lpBuffer = NULL;
33+
}
34+
}
35+
36+
#if defined (LINUX)
37+
// equivalent functions in linux
38+
static void *GetProcAddress(void *pLibrary, const char *name)
39+
{
40+
return dlsym( pLibrary, name);
41+
}
42+
#endif
43+
44+
static ADL_MAIN_CONTROL_CREATE ADL_Main_Control_Create;
45+
static ADL_MAIN_CONTROL_DESTROY ADL_Main_Control_Destroy;
46+
static ADL_ADAPTER_NUMBEROFADAPTERS_GET ADL_Adapter_NumberOfAdapters_Get;
47+
static ADL_ADAPTER_ADAPTERINFO_GET ADL_Adapter_AdapterInfo_Get;
48+
static ADL_ADAPTER_ID_GET ADL_Adapter_ID_Get;
49+
static ADL_OVERDRIVE5_TEMPERATURE_GET ADL_Overdrive5_Temperature_Get;
50+
static ADL_ADAPTER_ACTIVE_GET ADL_Adapter_Active_Get;
51+
static ADL_OVERDRIVE5_CURRENTACTIVITY_GET ADL_Overdrive5_CurrentActivity_Get;
52+
static ADL_OVERDRIVE5_ODPARAMETERS_GET ADL_Overdrive5_ODParameters_Get;
53+
static ADL_OVERDRIVE5_FANSPEEDINFO_GET ADL_Overdrive5_FanSpeedInfo_Get;
54+
static ADL_OVERDRIVE5_FANSPEED_GET ADL_Overdrive5_FanSpeed_Get;
55+
static ADL_OVERDRIVE5_FANSPEED_SET ADL_Overdrive5_FanSpeed_Set;
56+
static ADL_OVERDRIVE5_ODPERFORMANCELEVELS_GET ADL_Overdrive5_ODPerformanceLevels_Get;
57+
static ADL_OVERDRIVE5_ODPERFORMANCELEVELS_SET ADL_Overdrive5_ODPerformanceLevels_Set;
58+
static ADL_MAIN_CONTROL_REFRESH ADL_Main_Control_Refresh;
59+
60+
bool adl_active;
61+
#if defined (LINUX)
62+
static void *hDLL; // Handle to .so library
63+
#else
64+
HINSTANCE hDLL; // Handle to DLL
65+
#endif
66+
static int iNumberAdapters;
67+
static LPAdapterInfo lpInfo = NULL;
68+
69+
void init_adl(int nDevs)
70+
{
71+
int i, devices = 0, last_adapter = -1;
72+
73+
#if defined (LINUX)
74+
hDLL = dlopen( "libatiadlxx.so", RTLD_LAZY|RTLD_GLOBAL);
75+
#else
76+
hDLL = LoadLibrary("atiadlxx.dll");
77+
if (hDLL == NULL)
78+
// A 32 bit calling application on 64 bit OS will fail to LoadLIbrary.
79+
// Try to load the 32 bit library (atiadlxy.dll) instead
80+
hDLL = LoadLibrary("atiadlxy.dll");
81+
#endif
82+
if (hDLL == NULL) {
83+
applog(LOG_INFO, "Unable to load ati adl library");
84+
return;
85+
}
86+
87+
ADL_Main_Control_Create = (ADL_MAIN_CONTROL_CREATE) GetProcAddress(hDLL,"ADL_Main_Control_Create");
88+
ADL_Main_Control_Destroy = (ADL_MAIN_CONTROL_DESTROY) GetProcAddress(hDLL,"ADL_Main_Control_Destroy");
89+
ADL_Adapter_NumberOfAdapters_Get = (ADL_ADAPTER_NUMBEROFADAPTERS_GET) GetProcAddress(hDLL,"ADL_Adapter_NumberOfAdapters_Get");
90+
ADL_Adapter_AdapterInfo_Get = (ADL_ADAPTER_ADAPTERINFO_GET) GetProcAddress(hDLL,"ADL_Adapter_AdapterInfo_Get");
91+
ADL_Adapter_ID_Get = (ADL_ADAPTER_ID_GET) GetProcAddress(hDLL,"ADL_Adapter_ID_Get");
92+
ADL_Overdrive5_Temperature_Get = (ADL_OVERDRIVE5_TEMPERATURE_GET) GetProcAddress(hDLL,"ADL_Overdrive5_Temperature_Get");
93+
ADL_Adapter_Active_Get = (ADL_ADAPTER_ACTIVE_GET) GetProcAddress(hDLL, "ADL_Adapter_Active_Get");
94+
ADL_Overdrive5_CurrentActivity_Get = (ADL_OVERDRIVE5_CURRENTACTIVITY_GET) GetProcAddress(hDLL, "ADL_Overdrive5_CurrentActivity_Get");
95+
ADL_Overdrive5_ODParameters_Get = (ADL_OVERDRIVE5_ODPARAMETERS_GET) GetProcAddress(hDLL, "ADL_Overdrive5_ODParameters_Get");
96+
ADL_Overdrive5_FanSpeedInfo_Get = (ADL_OVERDRIVE5_FANSPEEDINFO_GET) GetProcAddress(hDLL, "ADL_Overdrive5_FanSpeedInfo_Get");
97+
ADL_Overdrive5_FanSpeed_Get = (ADL_OVERDRIVE5_FANSPEED_GET) GetProcAddress(hDLL, "ADL_Overdrive5_FanSpeed_Get");
98+
ADL_Overdrive5_FanSpeed_Set = (ADL_OVERDRIVE5_FANSPEED_SET) GetProcAddress(hDLL, "ADL_Overdrive5_FanSpeed_Set");
99+
ADL_Overdrive5_ODPerformanceLevels_Get = (ADL_OVERDRIVE5_ODPERFORMANCELEVELS_GET) GetProcAddress(hDLL, "ADL_Overdrive5_ODPerformanceLevels_Get");
100+
ADL_Overdrive5_ODPerformanceLevels_Set = (ADL_OVERDRIVE5_ODPERFORMANCELEVELS_SET) GetProcAddress(hDLL, "ADL_Overdrive5_ODPerformanceLevels_Set");
101+
ADL_Main_Control_Refresh = (ADL_MAIN_CONTROL_REFRESH) GetProcAddress(hDLL, "ADL_Main_Control_Refresh");
102+
103+
if (!ADL_Main_Control_Create || !ADL_Main_Control_Destroy ||
104+
!ADL_Adapter_NumberOfAdapters_Get || !ADL_Adapter_AdapterInfo_Get ||
105+
!ADL_Adapter_ID_Get || !ADL_Overdrive5_Temperature_Get ||
106+
!ADL_Adapter_Active_Get || !ADL_Overdrive5_CurrentActivity_Get ||
107+
!ADL_Overdrive5_ODParameters_Get || !ADL_Overdrive5_FanSpeedInfo_Get ||
108+
!ADL_Overdrive5_FanSpeed_Get || !ADL_Overdrive5_FanSpeed_Set ||
109+
!ADL_Overdrive5_ODPerformanceLevels_Get || !ADL_Overdrive5_ODPerformanceLevels_Set ||
110+
!ADL_Main_Control_Refresh) {
111+
applog(LOG_INFO, "ATI ADL's API is missing");
112+
return;
113+
}
114+
115+
// Initialise ADL. The second parameter is 1, which means:
116+
// retrieve adapter information only for adapters that are physically present and enabled in the system
117+
if (ADL_Main_Control_Create (ADL_Main_Memory_Alloc, 1) != ADL_OK) {
118+
applog(LOG_INFO, "ADL Initialisation Error!");
119+
return ;
120+
}
121+
122+
if (ADL_Main_Control_Refresh() != ADL_OK) {
123+
applog(LOG_INFO, "ADL Refresh Error!");
124+
return ;
125+
}
126+
127+
// Obtain the number of adapters for the system
128+
if (ADL_Adapter_NumberOfAdapters_Get ( &iNumberAdapters ) != ADL_OK) {
129+
applog(LOG_INFO, "Cannot get the number of adapters!\n");
130+
return ;
131+
}
132+
133+
if (iNumberAdapters > 0) {
134+
lpInfo = malloc ( sizeof (AdapterInfo) * iNumberAdapters );
135+
memset ( lpInfo,'\0', sizeof (AdapterInfo) * iNumberAdapters );
136+
137+
// Get the AdapterInfo structure for all adapters in the system
138+
if (ADL_Adapter_AdapterInfo_Get (lpInfo, sizeof (AdapterInfo) * iNumberAdapters) != ADL_OK) {
139+
applog(LOG_INFO, "ADL_Adapter_AdapterInfo_Get Error!");
140+
return ;
141+
}
142+
} else {
143+
applog(LOG_INFO, "No adapters found");
144+
return;
145+
}
146+
147+
for ( i = 0; i < iNumberAdapters; i++ ) {
148+
struct gpu_adl *ga;
149+
int iAdapterIndex;
150+
int lpAdapterID;
151+
int lpStatus;
152+
ADLODPerformanceLevels *lpOdPerformanceLevels;
153+
int lev;
154+
155+
iAdapterIndex = lpInfo[i].iAdapterIndex;
156+
/* Get unique identifier of the adapter */
157+
if (ADL_Adapter_ID_Get(iAdapterIndex, &lpAdapterID) != ADL_OK) {
158+
applog(LOG_INFO, "Failed to ADL_Adapter_ID_Get");
159+
continue;
160+
}
161+
if (!lpAdapterID)
162+
continue;
163+
164+
if (lpAdapterID != last_adapter) {
165+
/* We found a truly new adapter instead of a logical
166+
* one. Now since there's no way of correlating the
167+
* opencl enumerated devices and the ADL enumerated
168+
* ones, we have to assume they're in the same order.*/
169+
if (++devices > nDevs) {
170+
applog(LOG_ERR, "ADL found more devices than opencl");
171+
return;
172+
}
173+
last_adapter = lpAdapterID;
174+
}
175+
176+
/* See if the adapter is an AMD device with ADL active */
177+
if (ADL_Adapter_Active_Get(iAdapterIndex, &lpStatus) != ADL_OK) {
178+
applog(LOG_INFO, "Failed to ADL_Adapter_Active_Get");
179+
continue;
180+
}
181+
if (!lpStatus)
182+
continue;
183+
184+
/* From here on we know this device is a discrete device and
185+
* should support ADL */
186+
ga = &gpus[devices - 1].adl;
187+
ga->iAdapterIndex = iAdapterIndex;
188+
ga->lpAdapterID = lpAdapterID;
189+
ga->lpStatus = lpStatus;
190+
if (ADL_Overdrive5_ODParameters_Get(iAdapterIndex, &ga->lpOdParameters) != ADL_OK) {
191+
applog(LOG_INFO, "Failed to ADL_Overdrive5_ODParameters_Get");
192+
continue;
193+
}
194+
195+
lev = ga->lpOdParameters.iNumberOfPerformanceLevels - 1;
196+
/* We're only interested in the top performance level */
197+
lpOdPerformanceLevels = alloca(sizeof(ADLODPerformanceLevels) + (lev * sizeof(ADLODPerformanceLevel)));
198+
lpOdPerformanceLevels->iSize = sizeof(ADLODPerformanceLevels) + sizeof(ADLODPerformanceLevel) * lev;
199+
if (ADL_Overdrive5_ODPerformanceLevels_Get(iAdapterIndex, 0, lpOdPerformanceLevels) != ADL_OK) {
200+
applog(LOG_INFO, "Failed to ADL_Overdrive5_ODPerformanceLevels_Get");
201+
continue;
202+
}
203+
ga->iEngineClock = lpOdPerformanceLevels->aLevels[lev].iEngineClock;
204+
ga->iMemoryClock = lpOdPerformanceLevels->aLevels[lev].iMemoryClock;
205+
ga->iVddc = lpOdPerformanceLevels->aLevels[lev].iVddc;
206+
207+
if (ADL_Overdrive5_FanSpeedInfo_Get(iAdapterIndex, 0, &ga->lpFanSpeedInfo) != ADL_OK) {
208+
applog(LOG_INFO, "Failed to ADL_Overdrive5_FanSpeedInfo_Get");
209+
continue;
210+
}
211+
212+
gpus[devices - 1].has_adl = true;
213+
}
214+
215+
adl_active = true;
216+
}
217+
218+
float gpu_temp(int gpu)
219+
{
220+
struct gpu_adl *ga;
221+
222+
if (!gpus[gpu].has_adl || !adl_active)
223+
return 0;
224+
225+
ga = &gpus[gpu].adl;
226+
if (ADL_Overdrive5_Temperature_Get(ga->iAdapterIndex, 0, &ga->lpTemperature) != ADL_OK)
227+
return 0;
228+
return (float)ga->lpTemperature.iTemperature / 1000;
229+
}
230+
231+
int gpu_engineclock(int gpu)
232+
{
233+
struct gpu_adl *ga;
234+
235+
if (!gpus[gpu].has_adl || !adl_active)
236+
return 0;
237+
238+
ga = &gpus[gpu].adl;
239+
if (ADL_Overdrive5_CurrentActivity_Get(ga->iAdapterIndex, &ga->lpActivity) != ADL_OK)
240+
return 0;
241+
return ga->lpActivity.iEngineClock / 100;
242+
}
243+
244+
int gpu_memclock(int gpu)
245+
{
246+
struct gpu_adl *ga;
247+
248+
if (!gpus[gpu].has_adl || !adl_active)
249+
return 0;
250+
251+
ga = &gpus[gpu].adl;
252+
if (ADL_Overdrive5_CurrentActivity_Get(ga->iAdapterIndex, &ga->lpActivity) != ADL_OK)
253+
return 0;
254+
return ga->lpActivity.iMemoryClock / 100;
255+
}
256+
257+
float gpu_vddc(int gpu)
258+
{
259+
struct gpu_adl *ga;
260+
261+
if (!gpus[gpu].has_adl || !adl_active)
262+
return 0;
263+
264+
ga = &gpus[gpu].adl;
265+
if (ADL_Overdrive5_CurrentActivity_Get(ga->iAdapterIndex, &ga->lpActivity) != ADL_OK)
266+
return 0;
267+
return (float)ga->lpActivity.iVddc / 1000;
268+
}
269+
270+
int gpu_activity(int gpu)
271+
{
272+
struct gpu_adl *ga;
273+
274+
if (!gpus[gpu].has_adl || !adl_active)
275+
return 0;
276+
277+
ga = &gpus[gpu].adl;
278+
if (!ga->lpOdParameters.iActivityReportingSupported)
279+
return 0;
280+
if (ADL_Overdrive5_CurrentActivity_Get(ga->iAdapterIndex, &ga->lpActivity) != ADL_OK)
281+
return 0;
282+
return ga->lpActivity.iActivityPercent;
283+
}
284+
285+
int gpu_fanspeed(int gpu)
286+
{
287+
struct gpu_adl *ga;
288+
289+
if (!gpus[gpu].has_adl || !adl_active)
290+
return 0;
291+
292+
ga = &gpus[gpu].adl;
293+
if (!(ga->lpFanSpeedInfo.iFlags & (ADL_DL_FANCTRL_SUPPORTS_RPM_READ | ADL_DL_FANCTRL_SUPPORTS_PERCENT_READ )))
294+
return 0;
295+
if (ADL_Overdrive5_FanSpeed_Get(ga->iAdapterIndex, 0, &ga->lpFanSpeedValue) != ADL_OK)
296+
return 0;
297+
return ga->lpFanSpeedValue.iFanSpeed;
298+
}
299+
300+
void clear_adl(void)
301+
{
302+
if (!adl_active)
303+
return;
304+
305+
ADL_Main_Memory_Free ( (void **)&lpInfo );
306+
ADL_Main_Control_Destroy ();
307+
308+
#if defined (LINUX)
309+
dlclose(hDLL);
310+
#else
311+
FreeLibrary(hDLL);
312+
#endif
313+
}
314+
#endif /* HAVE_ADL */

adl.h

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
#ifndef __ADL_H__
2+
#define __ADL_H__
3+
#ifdef HAVE_ADL
4+
void init_adl(int nDevs);
5+
float gpu_temp(int gpu);
6+
int gpu_engineclock(int gpu);
7+
int gpu_memclock(int gpu);
8+
float gpu_vddc(int gpu);
9+
int gpu_activity(int gpu);
10+
int gpu_fanspeed(int gpu);
11+
void clear_adl(void);
12+
#else /* HAVE_ADL */
13+
void init_adl(int nDevs) {}
14+
void clear_adl(void) {}
15+
#endif
16+
#endif

0 commit comments

Comments
 (0)