File Index
Files and directories
Sign in
FILE

acpi.c

File preview with syntax highlighting.

linux-6.19.14/drivers/platform/x86/amd/hsmp/acpi.c C
  1// SPDX-License-Identifier: GPL-2.0
  2/*
  3 * AMD HSMP Platform Driver
  4 * Copyright (c) 2024, AMD.
  5 * All Rights Reserved.
  6 *
  7 * This file provides an ACPI based driver implementation for HSMP interface.
  8 */
  9
 10#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 11
 12#include <asm/amd/hsmp.h>
 13
 14#include <linux/acpi.h>
 15#include <linux/array_size.h>
 16#include <linux/bits.h>
 17#include <linux/bitfield.h>
 18#include <linux/device.h>
 19#include <linux/dev_printk.h>
 20#include <linux/ioport.h>
 21#include <linux/kstrtox.h>
 22#include <linux/module.h>
 23#include <linux/platform_device.h>
 24#include <linux/sysfs.h>
 25#include <linux/topology.h>
 26#include <linux/uuid.h>
 27
 28#include <uapi/asm-generic/errno-base.h>
 29
 30#include "hsmp.h"
 31
 32#define DRIVER_NAME		"hsmp_acpi"
 33
 34/* These are the strings specified in ACPI table */
 35#define MSG_IDOFF_STR		"MsgIdOffset"
 36#define MSG_ARGOFF_STR		"MsgArgOffset"
 37#define MSG_RESPOFF_STR		"MsgRspOffset"
 38
 39static struct hsmp_plat_device *hsmp_pdev;
 40
 41struct hsmp_sys_attr {
 42	struct device_attribute dattr;
 43	u32 msg_id;
 44};
 45
 46static int amd_hsmp_acpi_rdwr(struct hsmp_socket *sock, u32 offset,
 47			      u32 *value, bool write)
 48{
 49	if (write)
 50		iowrite32(*value, sock->virt_base_addr + offset);
 51	else
 52		*value = ioread32(sock->virt_base_addr + offset);
 53
 54	return 0;
 55}
 56
 57/* This is the UUID used for HSMP */
 58static const guid_t acpi_hsmp_uuid = GUID_INIT(0xb74d619d, 0x5707, 0x48bd,
 59						0xa6, 0x9f, 0x4e, 0xa2,
 60						0x87, 0x1f, 0xc2, 0xf6);
 61
 62static inline bool is_acpi_hsmp_uuid(union acpi_object *obj)
 63{
 64	if (obj->type == ACPI_TYPE_BUFFER && obj->buffer.length == UUID_SIZE)
 65		return guid_equal((guid_t *)obj->buffer.pointer, &acpi_hsmp_uuid);
 66
 67	return false;
 68}
 69
 70static inline int hsmp_get_uid(struct device *dev, u16 *sock_ind)
 71{
 72	char *uid;
 73
 74	/*
 75	 * UID (ID00, ID01..IDXX) is used for differentiating sockets,
 76	 * read it and strip the "ID" part of it and convert the remaining
 77	 * bytes to integer.
 78	 */
 79	uid = acpi_device_uid(ACPI_COMPANION(dev));
 80
 81	return kstrtou16(uid + 2, 10, sock_ind);
 82}
 83
 84static acpi_status hsmp_resource(struct acpi_resource *res, void *data)
 85{
 86	struct hsmp_socket *sock = data;
 87	struct resource r;
 88
 89	switch (res->type) {
 90	case ACPI_RESOURCE_TYPE_FIXED_MEMORY32:
 91		if (!acpi_dev_resource_memory(res, &r))
 92			return AE_ERROR;
 93		if (!r.start || r.end < r.start || !(r.flags & IORESOURCE_MEM_WRITEABLE))
 94			return AE_ERROR;
 95		sock->mbinfo.base_addr = r.start;
 96		sock->mbinfo.size = resource_size(&r);
 97		break;
 98	case ACPI_RESOURCE_TYPE_END_TAG:
 99		break;
100	default:
101		return AE_ERROR;
102	}
103
104	return AE_OK;
105}
106
107static int hsmp_read_acpi_dsd(struct hsmp_socket *sock)
108{
109	struct acpi_buffer buf = { ACPI_ALLOCATE_BUFFER, NULL };
110	union acpi_object *guid, *mailbox_package;
111	union acpi_object *dsd;
112	acpi_status status;
113	int ret = 0;
114	int j;
115
116	status = acpi_evaluate_object_typed(ACPI_HANDLE(sock->dev), "_DSD", NULL,
117					    &buf, ACPI_TYPE_PACKAGE);
118	if (ACPI_FAILURE(status)) {
119		dev_err(sock->dev, "Failed to read mailbox reg offsets from DSD table, err: %s\n",
120			acpi_format_exception(status));
121		return -ENODEV;
122	}
123
124	dsd = buf.pointer;
125
126	/* HSMP _DSD property should contain 2 objects.
127	 * 1. guid which is an acpi object of type ACPI_TYPE_BUFFER
128	 * 2. mailbox which is an acpi object of type ACPI_TYPE_PACKAGE
129	 *    This mailbox object contains 3 more acpi objects of type
130	 *    ACPI_TYPE_PACKAGE for holding msgid, msgresp, msgarg offsets
131	 *    these packages inturn contain 2 acpi objects of type
132	 *    ACPI_TYPE_STRING and ACPI_TYPE_INTEGER
133	 */
134	if (!dsd || dsd->type != ACPI_TYPE_PACKAGE || dsd->package.count != 2) {
135		ret = -EINVAL;
136		goto free_buf;
137	}
138
139	guid = &dsd->package.elements[0];
140	mailbox_package = &dsd->package.elements[1];
141	if (!is_acpi_hsmp_uuid(guid) || mailbox_package->type != ACPI_TYPE_PACKAGE) {
142		dev_err(sock->dev, "Invalid hsmp _DSD table data\n");
143		ret = -EINVAL;
144		goto free_buf;
145	}
146
147	for (j = 0; j < mailbox_package->package.count; j++) {
148		union acpi_object *msgobj, *msgstr, *msgint;
149
150		msgobj	= &mailbox_package->package.elements[j];
151		msgstr	= &msgobj->package.elements[0];
152		msgint	= &msgobj->package.elements[1];
153
154		/* package should have 1 string and 1 integer object */
155		if (msgobj->type != ACPI_TYPE_PACKAGE ||
156		    msgstr->type != ACPI_TYPE_STRING ||
157		    msgint->type != ACPI_TYPE_INTEGER) {
158			ret = -EINVAL;
159			goto free_buf;
160		}
161
162		if (!strncmp(msgstr->string.pointer, MSG_IDOFF_STR,
163			     msgstr->string.length)) {
164			sock->mbinfo.msg_id_off = msgint->integer.value;
165		} else if (!strncmp(msgstr->string.pointer, MSG_RESPOFF_STR,
166				    msgstr->string.length)) {
167			sock->mbinfo.msg_resp_off =  msgint->integer.value;
168		} else if (!strncmp(msgstr->string.pointer, MSG_ARGOFF_STR,
169				    msgstr->string.length)) {
170			sock->mbinfo.msg_arg_off = msgint->integer.value;
171		} else {
172			ret = -ENOENT;
173			goto free_buf;
174		}
175	}
176
177	if (!sock->mbinfo.msg_id_off || !sock->mbinfo.msg_resp_off ||
178	    !sock->mbinfo.msg_arg_off)
179		ret = -EINVAL;
180
181free_buf:
182	ACPI_FREE(buf.pointer);
183	return ret;
184}
185
186static int hsmp_read_acpi_crs(struct hsmp_socket *sock)
187{
188	acpi_status status;
189
190	status = acpi_walk_resources(ACPI_HANDLE(sock->dev), METHOD_NAME__CRS,
191				     hsmp_resource, sock);
192	if (ACPI_FAILURE(status)) {
193		dev_err(sock->dev, "Failed to look up MP1 base address from CRS method, err: %s\n",
194			acpi_format_exception(status));
195		return -EINVAL;
196	}
197	if (!sock->mbinfo.base_addr || !sock->mbinfo.size)
198		return -EINVAL;
199
200	/* The mapped region should be un-cached */
201	sock->virt_base_addr = devm_ioremap_uc(sock->dev, sock->mbinfo.base_addr,
202					       sock->mbinfo.size);
203	if (!sock->virt_base_addr) {
204		dev_err(sock->dev, "Failed to ioremap MP1 base address\n");
205		return -ENOMEM;
206	}
207
208	return 0;
209}
210
211/* Parse the ACPI table to read the data */
212static int hsmp_parse_acpi_table(struct device *dev, u16 sock_ind)
213{
214	struct hsmp_socket *sock = &hsmp_pdev->sock[sock_ind];
215	int ret;
216
217	sock->sock_ind		= sock_ind;
218	sock->dev		= dev;
219	sock->amd_hsmp_rdwr	= amd_hsmp_acpi_rdwr;
220
221	sema_init(&sock->hsmp_sem, 1);
222
223	dev_set_drvdata(dev, sock);
224
225	/* Read MP1 base address from CRS method */
226	ret = hsmp_read_acpi_crs(sock);
227	if (ret)
228		return ret;
229
230	/* Read mailbox offsets from DSD table */
231	return hsmp_read_acpi_dsd(sock);
232}
233
234static ssize_t hsmp_metric_tbl_acpi_read(struct file *filp, struct kobject *kobj,
235					 const struct bin_attribute *bin_attr, char *buf,
236					 loff_t off, size_t count)
237{
238	struct device *dev = container_of(kobj, struct device, kobj);
239	struct hsmp_socket *sock = dev_get_drvdata(dev);
240
241	return hsmp_metric_tbl_read(sock, buf, count);
242}
243
244static umode_t hsmp_is_sock_attr_visible(struct kobject *kobj,
245					 const struct bin_attribute *battr, int id)
246{
247	if (hsmp_pdev->proto_ver == HSMP_PROTO_VER6)
248		return battr->attr.mode;
249
250	return 0;
251}
252
253static umode_t hsmp_is_sock_dev_attr_visible(struct kobject *kobj,
254					     struct attribute *attr, int id)
255{
256	return attr->mode;
257}
258
259#define to_hsmp_sys_attr(_attr) container_of(_attr, struct hsmp_sys_attr, dattr)
260
261static ssize_t hsmp_msg_resp32_show(struct device *dev, struct device_attribute *attr,
262				    char *buf)
263{
264	struct hsmp_sys_attr *hattr = to_hsmp_sys_attr(attr);
265	struct hsmp_socket *sock = dev_get_drvdata(dev);
266	u32 data;
267	int ret;
268
269	ret = hsmp_msg_get_nargs(sock->sock_ind, hattr->msg_id, &data, 1);
270	if (ret)
271		return ret;
272
273	return sysfs_emit(buf, "%u\n", data);
274}
275
276#define DDR_MAX_BW_MASK		GENMASK(31, 20)
277#define DDR_UTIL_BW_MASK	GENMASK(19, 8)
278#define DDR_UTIL_BW_PERC_MASK	GENMASK(7, 0)
279#define FW_VER_MAJOR_MASK	GENMASK(23, 16)
280#define FW_VER_MINOR_MASK	GENMASK(15, 8)
281#define FW_VER_DEBUG_MASK	GENMASK(7, 0)
282#define FMAX_MASK		GENMASK(31, 16)
283#define FMIN_MASK		GENMASK(15, 0)
284#define FREQ_LIMIT_MASK		GENMASK(31, 16)
285#define FREQ_SRC_IND_MASK	GENMASK(15, 0)
286
287static ssize_t hsmp_ddr_max_bw_show(struct device *dev, struct device_attribute *attr,
288				    char *buf)
289{
290	struct hsmp_sys_attr *hattr = to_hsmp_sys_attr(attr);
291	struct hsmp_socket *sock = dev_get_drvdata(dev);
292	u32 data;
293	int ret;
294
295	ret = hsmp_msg_get_nargs(sock->sock_ind, hattr->msg_id, &data, 1);
296	if (ret)
297		return ret;
298
299	return sysfs_emit(buf, "%lu\n", FIELD_GET(DDR_MAX_BW_MASK, data));
300}
301
302static ssize_t hsmp_ddr_util_bw_show(struct device *dev, struct device_attribute *attr,
303				     char *buf)
304{
305	struct hsmp_sys_attr *hattr = to_hsmp_sys_attr(attr);
306	struct hsmp_socket *sock = dev_get_drvdata(dev);
307	u32 data;
308	int ret;
309
310	ret = hsmp_msg_get_nargs(sock->sock_ind, hattr->msg_id, &data, 1);
311	if (ret)
312		return ret;
313
314	return sysfs_emit(buf, "%lu\n", FIELD_GET(DDR_UTIL_BW_MASK, data));
315}
316
317static ssize_t hsmp_ddr_util_bw_perc_show(struct device *dev, struct device_attribute *attr,
318					  char *buf)
319{
320	struct hsmp_sys_attr *hattr = to_hsmp_sys_attr(attr);
321	struct hsmp_socket *sock = dev_get_drvdata(dev);
322	u32 data;
323	int ret;
324
325	ret = hsmp_msg_get_nargs(sock->sock_ind, hattr->msg_id, &data, 1);
326	if (ret)
327		return ret;
328
329	return sysfs_emit(buf, "%lu\n", FIELD_GET(DDR_UTIL_BW_PERC_MASK, data));
330}
331
332static ssize_t hsmp_msg_fw_ver_show(struct device *dev, struct device_attribute *attr,
333				    char *buf)
334{
335	struct hsmp_sys_attr *hattr = to_hsmp_sys_attr(attr);
336	struct hsmp_socket *sock = dev_get_drvdata(dev);
337	u32 data;
338	int ret;
339
340	ret = hsmp_msg_get_nargs(sock->sock_ind, hattr->msg_id, &data, 1);
341	if (ret)
342		return ret;
343
344	return sysfs_emit(buf, "%lu.%lu.%lu\n",
345			  FIELD_GET(FW_VER_MAJOR_MASK, data),
346			  FIELD_GET(FW_VER_MINOR_MASK, data),
347			  FIELD_GET(FW_VER_DEBUG_MASK, data));
348}
349
350static ssize_t hsmp_fclk_show(struct device *dev, struct device_attribute *attr,
351			      char *buf)
352{
353	struct hsmp_sys_attr *hattr = to_hsmp_sys_attr(attr);
354	struct hsmp_socket *sock = dev_get_drvdata(dev);
355	u32 data[2];
356	int ret;
357
358	ret = hsmp_msg_get_nargs(sock->sock_ind, hattr->msg_id, data, 2);
359	if (ret)
360		return ret;
361
362	return sysfs_emit(buf, "%u\n", data[0]);
363}
364
365static ssize_t hsmp_mclk_show(struct device *dev, struct device_attribute *attr,
366			      char *buf)
367{
368	struct hsmp_sys_attr *hattr = to_hsmp_sys_attr(attr);
369	struct hsmp_socket *sock = dev_get_drvdata(dev);
370	u32 data[2];
371	int ret;
372
373	ret = hsmp_msg_get_nargs(sock->sock_ind, hattr->msg_id, data, 2);
374	if (ret)
375		return ret;
376
377	return sysfs_emit(buf, "%u\n", data[1]);
378}
379
380static ssize_t hsmp_clk_fmax_show(struct device *dev, struct device_attribute *attr,
381				  char *buf)
382{
383	struct hsmp_sys_attr *hattr = to_hsmp_sys_attr(attr);
384	struct hsmp_socket *sock = dev_get_drvdata(dev);
385	u32 data;
386	int ret;
387
388	ret = hsmp_msg_get_nargs(sock->sock_ind, hattr->msg_id, &data, 1);
389	if (ret)
390		return ret;
391
392	return sysfs_emit(buf, "%lu\n", FIELD_GET(FMAX_MASK, data));
393}
394
395static ssize_t hsmp_clk_fmin_show(struct device *dev, struct device_attribute *attr,
396				  char *buf)
397{
398	struct hsmp_sys_attr *hattr = to_hsmp_sys_attr(attr);
399	struct hsmp_socket *sock = dev_get_drvdata(dev);
400	u32 data;
401	int ret;
402
403	ret = hsmp_msg_get_nargs(sock->sock_ind, hattr->msg_id, &data, 1);
404	if (ret)
405		return ret;
406
407	return sysfs_emit(buf, "%lu\n", FIELD_GET(FMIN_MASK, data));
408}
409
410static ssize_t hsmp_freq_limit_show(struct device *dev, struct device_attribute *attr,
411				    char *buf)
412{
413	struct hsmp_sys_attr *hattr = to_hsmp_sys_attr(attr);
414	struct hsmp_socket *sock = dev_get_drvdata(dev);
415	u32 data;
416	int ret;
417
418	ret = hsmp_msg_get_nargs(sock->sock_ind, hattr->msg_id, &data, 1);
419	if (ret)
420		return ret;
421
422	return sysfs_emit(buf, "%lu\n", FIELD_GET(FREQ_LIMIT_MASK, data));
423}
424
425static const char * const freqlimit_srcnames[] = {
426	"cHTC-Active",
427	"PROCHOT",
428	"TDC limit",
429	"PPT Limit",
430	"OPN Max",
431	"Reliability Limit",
432	"APML Agent",
433	"HSMP Agent",
434};
435
436static ssize_t hsmp_freq_limit_source_show(struct device *dev, struct device_attribute *attr,
437					   char *buf)
438{
439	struct hsmp_sys_attr *hattr = to_hsmp_sys_attr(attr);
440	struct hsmp_socket *sock = dev_get_drvdata(dev);
441	unsigned int index;
442	int len = 0;
443	u16 src_ind;
444	u32 data;
445	int ret;
446
447	ret = hsmp_msg_get_nargs(sock->sock_ind, hattr->msg_id, &data, 1);
448	if (ret)
449		return ret;
450
451	src_ind = FIELD_GET(FREQ_SRC_IND_MASK, data);
452	for (index = 0; index < ARRAY_SIZE(freqlimit_srcnames); index++) {
453		if (!src_ind)
454			break;
455		if (src_ind & 1)
456			len += sysfs_emit_at(buf, len, "%s\n", freqlimit_srcnames[index]);
457		src_ind >>= 1;
458	}
459	return len;
460}
461
462static int init_acpi(struct device *dev)
463{
464	u16 sock_ind;
465	int ret;
466
467	ret = hsmp_get_uid(dev, &sock_ind);
468	if (ret)
469		return ret;
470	if (sock_ind >= hsmp_pdev->num_sockets)
471		return -EINVAL;
472
473	ret = hsmp_parse_acpi_table(dev, sock_ind);
474	if (ret) {
475		dev_err(dev, "Failed to parse ACPI table\n");
476		return ret;
477	}
478
479	/* Test the hsmp interface */
480	ret = hsmp_test(sock_ind, 0xDEADBEEF);
481	if (ret) {
482		dev_err(dev, "HSMP test message failed on Fam:%x model:%x\n",
483			boot_cpu_data.x86, boot_cpu_data.x86_model);
484		dev_err(dev, "Is HSMP disabled in BIOS ?\n");
485		return ret;
486	}
487
488	ret = hsmp_cache_proto_ver(sock_ind);
489	if (ret) {
490		dev_err(dev, "Failed to read HSMP protocol version\n");
491		return ret;
492	}
493
494	if (hsmp_pdev->proto_ver == HSMP_PROTO_VER6) {
495		ret = hsmp_get_tbl_dram_base(sock_ind);
496		if (ret)
497			dev_info(dev, "Failed to init metric table\n");
498	}
499
500	ret = hsmp_create_sensor(dev, sock_ind);
501	if (ret)
502		dev_info(dev, "Failed to register HSMP sensors with hwmon\n");
503
504	dev_set_drvdata(dev, &hsmp_pdev->sock[sock_ind]);
505
506	return 0;
507}
508
509static const struct bin_attribute  hsmp_metric_tbl_attr = {
510	.attr = { .name = HSMP_METRICS_TABLE_NAME, .mode = 0444},
511	.read = hsmp_metric_tbl_acpi_read,
512	.size = sizeof(struct hsmp_metric_table),
513};
514
515static const struct bin_attribute *hsmp_attr_list[] = {
516	&hsmp_metric_tbl_attr,
517	NULL
518};
519
520#define HSMP_DEV_ATTR(_name, _msg_id, _show, _mode)	\
521static struct hsmp_sys_attr hattr_##_name = {		\
522	.dattr = __ATTR(_name, _mode, _show, NULL),	\
523	.msg_id = _msg_id,				\
524}
525
526HSMP_DEV_ATTR(c0_residency_input, HSMP_GET_C0_PERCENT, hsmp_msg_resp32_show, 0444);
527HSMP_DEV_ATTR(prochot_status, HSMP_GET_PROC_HOT, hsmp_msg_resp32_show, 0444);
528HSMP_DEV_ATTR(smu_fw_version, HSMP_GET_SMU_VER, hsmp_msg_fw_ver_show, 0444);
529HSMP_DEV_ATTR(protocol_version, HSMP_GET_PROTO_VER, hsmp_msg_resp32_show, 0444);
530HSMP_DEV_ATTR(cclk_freq_limit_input, HSMP_GET_CCLK_THROTTLE_LIMIT, hsmp_msg_resp32_show, 0444);
531HSMP_DEV_ATTR(ddr_max_bw, HSMP_GET_DDR_BANDWIDTH, hsmp_ddr_max_bw_show, 0444);
532HSMP_DEV_ATTR(ddr_utilised_bw_input, HSMP_GET_DDR_BANDWIDTH, hsmp_ddr_util_bw_show, 0444);
533HSMP_DEV_ATTR(ddr_utilised_bw_perc_input, HSMP_GET_DDR_BANDWIDTH, hsmp_ddr_util_bw_perc_show, 0444);
534HSMP_DEV_ATTR(fclk_input, HSMP_GET_FCLK_MCLK, hsmp_fclk_show, 0444);
535HSMP_DEV_ATTR(mclk_input, HSMP_GET_FCLK_MCLK, hsmp_mclk_show, 0444);
536HSMP_DEV_ATTR(clk_fmax, HSMP_GET_SOCKET_FMAX_FMIN, hsmp_clk_fmax_show, 0444);
537HSMP_DEV_ATTR(clk_fmin, HSMP_GET_SOCKET_FMAX_FMIN, hsmp_clk_fmin_show, 0444);
538HSMP_DEV_ATTR(pwr_current_active_freq_limit, HSMP_GET_SOCKET_FREQ_LIMIT,
539	      hsmp_freq_limit_show, 0444);
540HSMP_DEV_ATTR(pwr_current_active_freq_limit_source, HSMP_GET_SOCKET_FREQ_LIMIT,
541	      hsmp_freq_limit_source_show, 0444);
542
543static struct attribute *hsmp_dev_attr_list[] = {
544	&hattr_c0_residency_input.dattr.attr,
545	&hattr_prochot_status.dattr.attr,
546	&hattr_smu_fw_version.dattr.attr,
547	&hattr_protocol_version.dattr.attr,
548	&hattr_cclk_freq_limit_input.dattr.attr,
549	&hattr_ddr_max_bw.dattr.attr,
550	&hattr_ddr_utilised_bw_input.dattr.attr,
551	&hattr_ddr_utilised_bw_perc_input.dattr.attr,
552	&hattr_fclk_input.dattr.attr,
553	&hattr_mclk_input.dattr.attr,
554	&hattr_clk_fmax.dattr.attr,
555	&hattr_clk_fmin.dattr.attr,
556	&hattr_pwr_current_active_freq_limit.dattr.attr,
557	&hattr_pwr_current_active_freq_limit_source.dattr.attr,
558	NULL
559};
560
561static const struct attribute_group hsmp_attr_grp = {
562	.bin_attrs = hsmp_attr_list,
563	.attrs = hsmp_dev_attr_list,
564	.is_bin_visible = hsmp_is_sock_attr_visible,
565	.is_visible = hsmp_is_sock_dev_attr_visible,
566};
567
568static const struct attribute_group *hsmp_groups[] = {
569	&hsmp_attr_grp,
570	NULL
571};
572
573static const struct acpi_device_id amd_hsmp_acpi_ids[] = {
574	{ACPI_HSMP_DEVICE_HID, 0},
575	{}
576};
577MODULE_DEVICE_TABLE(acpi, amd_hsmp_acpi_ids);
578
579static int hsmp_acpi_probe(struct platform_device *pdev)
580{
581	int ret;
582
583	hsmp_pdev = get_hsmp_pdev();
584	if (!hsmp_pdev)
585		return -ENOMEM;
586
587	if (!hsmp_pdev->is_probed) {
588		hsmp_pdev->num_sockets = topology_max_packages();
589		if (!hsmp_pdev->num_sockets) {
590			dev_err(&pdev->dev, "No CPU sockets detected\n");
591			return -ENODEV;
592		}
593
594		hsmp_pdev->sock = devm_kcalloc(&pdev->dev, hsmp_pdev->num_sockets,
595					       sizeof(*hsmp_pdev->sock),
596					       GFP_KERNEL);
597		if (!hsmp_pdev->sock)
598			return -ENOMEM;
599	}
600
601	ret = init_acpi(&pdev->dev);
602	if (ret) {
603		dev_err(&pdev->dev, "Failed to initialize HSMP interface.\n");
604		return ret;
605	}
606
607	if (!hsmp_pdev->is_probed) {
608		ret = hsmp_misc_register(&pdev->dev);
609		if (ret) {
610			dev_err(&pdev->dev, "Failed to register misc device\n");
611			return ret;
612		}
613		hsmp_pdev->is_probed = true;
614		dev_dbg(&pdev->dev, "AMD HSMP ACPI is probed successfully\n");
615	}
616
617	return 0;
618}
619
620static void hsmp_acpi_remove(struct platform_device *pdev)
621{
622	/*
623	 * We register only one misc_device even on multi-socket system.
624	 * So, deregister should happen only once.
625	 */
626	if (hsmp_pdev->is_probed) {
627		hsmp_misc_deregister();
628		hsmp_pdev->is_probed = false;
629	}
630}
631
632static struct platform_driver amd_hsmp_driver = {
633	.probe		= hsmp_acpi_probe,
634	.remove		= hsmp_acpi_remove,
635	.driver		= {
636		.name	= DRIVER_NAME,
637		.acpi_match_table = amd_hsmp_acpi_ids,
638		.dev_groups = hsmp_groups,
639	},
640};
641
642module_platform_driver(amd_hsmp_driver);
643
644MODULE_IMPORT_NS("AMD_HSMP");
645MODULE_DESCRIPTION("AMD HSMP Platform Interface Driver");
646MODULE_VERSION(DRIVER_VERSION);
647MODULE_LICENSE("GPL");
~/ Read-only file preview.