cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

amd_sfh_hid.c (4349B)


      1// SPDX-License-Identifier: GPL-2.0-or-later
      2/*
      3 * AMD MP2 Sensors transport driver
      4 *
      5 * Copyright 2020-2021 Advanced Micro Devices, Inc.
      6 * Authors: Nehal Bakulchandra Shah <Nehal-bakulchandra.shah@amd.com>
      7 *	    Sandeep Singh <sandeep.singh@amd.com>
      8 *	    Basavaraj Natikar <Basavaraj.Natikar@amd.com>
      9 */
     10#include <linux/hid.h>
     11#include <linux/wait.h>
     12#include <linux/sched.h>
     13
     14#include "amd_sfh_hid.h"
     15#include "amd_sfh_pcie.h"
     16
     17#define AMD_SFH_RESPONSE_TIMEOUT	1500
     18
     19/**
     20 * amdtp_hid_parse() - hid-core .parse() callback
     21 * @hid:	hid device instance
     22 *
     23 * This function gets called during call to hid_add_device
     24 *
     25 * Return: 0 on success and non zero on error
     26 */
     27static int amdtp_hid_parse(struct hid_device *hid)
     28{
     29	struct amdtp_hid_data *hid_data = hid->driver_data;
     30	struct amdtp_cl_data *cli_data = hid_data->cli_data;
     31
     32	return hid_parse_report(hid, cli_data->report_descr[hid_data->index],
     33			      cli_data->report_descr_sz[hid_data->index]);
     34}
     35
     36/* Empty callbacks with success return code */
     37static int amdtp_hid_start(struct hid_device *hid)
     38{
     39	return 0;
     40}
     41
     42static void amdtp_hid_stop(struct hid_device *hid)
     43{
     44}
     45
     46static int amdtp_hid_open(struct hid_device *hid)
     47{
     48	return 0;
     49}
     50
     51static void amdtp_hid_close(struct hid_device *hid)
     52{
     53}
     54
     55static int amdtp_raw_request(struct hid_device *hdev, u8 reportnum,
     56			     u8 *buf, size_t len, u8 rtype, int reqtype)
     57{
     58	return 0;
     59}
     60
     61static void amdtp_hid_request(struct hid_device *hid, struct hid_report *rep, int reqtype)
     62{
     63	int rc;
     64
     65	switch (reqtype) {
     66	case HID_REQ_GET_REPORT:
     67		rc = amd_sfh_get_report(hid, rep->id, rep->type);
     68		if (rc)
     69			dev_err(&hid->dev, "AMDSFH  get report error\n");
     70		break;
     71	case HID_REQ_SET_REPORT:
     72		amd_sfh_set_report(hid, rep->id, reqtype);
     73		break;
     74	default:
     75		break;
     76	}
     77}
     78
     79static int amdtp_wait_for_response(struct hid_device *hid)
     80{
     81	struct amdtp_hid_data *hid_data =  hid->driver_data;
     82	struct amdtp_cl_data *cli_data = hid_data->cli_data;
     83	int i, ret = 0;
     84
     85	for (i = 0; i < cli_data->num_hid_devices; i++) {
     86		if (cli_data->hid_sensor_hubs[i] == hid)
     87			break;
     88	}
     89
     90	if (!cli_data->request_done[i])
     91		ret = wait_event_interruptible_timeout(hid_data->hid_wait,
     92						       cli_data->request_done[i],
     93						       msecs_to_jiffies(AMD_SFH_RESPONSE_TIMEOUT));
     94	if (ret == -ERESTARTSYS)
     95		return -ERESTARTSYS;
     96	else if (ret < 0)
     97		return -ETIMEDOUT;
     98	else
     99		return 0;
    100}
    101
    102void amdtp_hid_wakeup(struct hid_device *hid)
    103{
    104	struct amdtp_hid_data *hid_data = hid->driver_data;
    105	struct amdtp_cl_data *cli_data = hid_data->cli_data;
    106
    107	cli_data->request_done[cli_data->cur_hid_dev] = true;
    108	wake_up_interruptible(&hid_data->hid_wait);
    109}
    110
    111static struct hid_ll_driver amdtp_hid_ll_driver = {
    112	.parse	=	amdtp_hid_parse,
    113	.start	=	amdtp_hid_start,
    114	.stop	=	amdtp_hid_stop,
    115	.open	=	amdtp_hid_open,
    116	.close	=	amdtp_hid_close,
    117	.request  =	amdtp_hid_request,
    118	.wait	=	amdtp_wait_for_response,
    119	.raw_request  =	amdtp_raw_request,
    120};
    121
    122int amdtp_hid_probe(u32 cur_hid_dev, struct amdtp_cl_data *cli_data)
    123{
    124	struct amd_mp2_dev *mp2 = container_of(cli_data->in_data, struct amd_mp2_dev, in_data);
    125	struct device *dev = &mp2->pdev->dev;
    126	struct hid_device *hid;
    127	struct amdtp_hid_data *hid_data;
    128	int rc;
    129
    130	hid = hid_allocate_device();
    131	if (IS_ERR(hid))
    132		return PTR_ERR(hid);
    133
    134	hid_data = kzalloc(sizeof(*hid_data), GFP_KERNEL);
    135	if (!hid_data) {
    136		rc = -ENOMEM;
    137		goto err_hid_data;
    138	}
    139
    140	hid->ll_driver = &amdtp_hid_ll_driver;
    141	hid_data->index = cur_hid_dev;
    142	hid_data->cli_data = cli_data;
    143	init_waitqueue_head(&hid_data->hid_wait);
    144
    145	hid->driver_data = hid_data;
    146	cli_data->hid_sensor_hubs[cur_hid_dev] = hid;
    147	strscpy(hid->phys, dev->driver ? dev->driver->name : dev_name(dev),
    148		sizeof(hid->phys));
    149	hid->bus = BUS_AMD_SFH;
    150	hid->vendor = AMD_SFH_HID_VENDOR;
    151	hid->product = AMD_SFH_HID_PRODUCT;
    152	snprintf(hid->name, sizeof(hid->name), "%s %04X:%04X", "hid-amdsfh",
    153		 hid->vendor, hid->product);
    154
    155	rc = hid_add_device(hid);
    156	if (rc)
    157		goto err_hid_device;
    158	return 0;
    159
    160err_hid_device:
    161	kfree(hid_data);
    162err_hid_data:
    163	hid_destroy_device(hid);
    164	return rc;
    165}
    166
    167void amdtp_hid_remove(struct amdtp_cl_data *cli_data)
    168{
    169	int i;
    170
    171	for (i = 0; i < cli_data->num_hid_devices; ++i) {
    172		if (cli_data->hid_sensor_hubs[i]) {
    173			kfree(cli_data->hid_sensor_hubs[i]->driver_data);
    174			hid_destroy_device(cli_data->hid_sensor_hubs[i]);
    175			cli_data->hid_sensor_hubs[i] = NULL;
    176		}
    177	}
    178}