Skip to content

Commit

Permalink
ipts: Implement new companion interface
Browse files Browse the repository at this point in the history
This makes it easier to extend the companion driver, since everything is
stored in a single struct.

The ipts_companion_t struct is stored in two places, the IPTS main driver,
and the driver registering it. It is still passed through to the functions
that the companion driver implements to allow for device specific behaviour.

Signed-off-by: Dorian Stoll <dorian.stoll@tmsp.io>
  • Loading branch information
StollD committed Oct 25, 2019
1 parent d6e78a3 commit a1531a7
Show file tree
Hide file tree
Showing 16 changed files with 216 additions and 204 deletions.
2 changes: 1 addition & 1 deletion drivers/gpu/drm/i915_legacy/intel_ipts.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/module.h>
#include <linux/intel_ipts_if.h>
#include <linux/ipts-gfx.h>
#include <drm/drmP.h>

#include "intel_guc_submission.h"
Expand Down
2 changes: 1 addition & 1 deletion drivers/misc/ipts/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
#

obj-$(CONFIG_INTEL_IPTS)+= intel-ipts.o
intel-ipts-objs += ipts-fw.o
intel-ipts-objs += ipts-companion.o
intel-ipts-objs += ipts-mei.o
intel-ipts-objs += ipts-hid.o
intel-ipts-objs += ipts-msg-handler.o
Expand Down
76 changes: 38 additions & 38 deletions drivers/misc/ipts/companion/ipts-surface.c
Original file line number Diff line number Diff line change
@@ -1,44 +1,38 @@
#include <linux/acpi.h>
#include <linux/firmware.h>
#include <linux/intel_ipts_fw.h>
#include <linux/intel_ipts_if.h>
#include <linux/ipts.h>
#include <linux/ipts-companion.h>
#include <linux/module.h>
#include <linux/platform_device.h>

#define IPTS_SURFACE_FW_PATH_FMT "intel/ipts/%s/%s"

#define __IPTS_SURFACE_FIRMWARE(X, Y) \
MODULE_FIRMWARE("intel/ipts/" X "/" Y)

#define IPTS_SURFACE_FIRMWARE(X) \
__IPTS_SURFACE_FIRMWARE(X, "config.bin"); \
__IPTS_SURFACE_FIRMWARE(X, "intel_desc.bin"); \
__IPTS_SURFACE_FIRMWARE(X, "intel_fw_config.bin"); \
__IPTS_SURFACE_FIRMWARE(X, "vendor_desc.bin"); \
__IPTS_SURFACE_FIRMWARE(X, "vendor_kernel.bin")

IPTS_SURFACE_FIRMWARE("MSHW0076");
IPTS_SURFACE_FIRMWARE("MSHW0078");
IPTS_SURFACE_FIRMWARE("MSHW0079");
IPTS_SURFACE_FIRMWARE("MSHW0101");
IPTS_SURFACE_FIRMWARE("MSHW0102");
IPTS_SURFACE_FIRMWARE("MSHW0103");
IPTS_SURFACE_FIRMWARE("MSHW0137");
#define IPTS_SURFACE_FIRMWARE(X) \
MODULE_FIRMWARE("intel/ipts/" X "/config.bin"); \
MODULE_FIRMWARE("intel/ipts/" X "/intel_desc.bin"); \
MODULE_FIRMWARE("intel/ipts/" X "/ipts_fw_config.bin"); \
MODULE_FIRMWARE("intel/ipts/" X "/vendor_desc.bin"); \
MODULE_FIRMWARE("intel/ipts/" X "/vendor_kernel.bin"); \

int ipts_surface_request_firmware(const struct firmware **fw, const char *name,
struct device *device, void *data)
struct device *device, ipts_companion_t *companion)
{
char fw_path[MAX_IOCL_FILE_PATH_LEN];

if (data == NULL) {
if (companion == NULL || companion->data == NULL) {
return -ENOENT;
}

snprintf(fw_path, MAX_IOCL_FILE_PATH_LEN, IPTS_SURFACE_FW_PATH_FMT,
(const char *)data, name);
(const char *)companion->data, name);
return request_firmware(fw, fw_path, device);
}

static ipts_companion_t ipts_surface_companion = {
.firmware_request = &ipts_surface_request_firmware,
.name = "ipts_surface",
};

static int ipts_surface_probe(struct platform_device *pdev)
{
int ret;
Expand All @@ -49,11 +43,11 @@ static int ipts_surface_probe(struct platform_device *pdev)
return -ENODEV;
}

ret = intel_ipts_add_fw_handler(&ipts_surface_request_firmware,
(void *)acpi_device_hid(adev));
ipts_surface_companion.data = (void *)acpi_device_hid(adev);
ret = ipts_add_companion(&ipts_surface_companion);
if (ret) {
dev_info(&pdev->dev, "Adding IPTS firmware handler failed, "
"error: %d\n", ret);
dev_info(&pdev->dev, "Adding IPTS companion failed, "
"error: %d\n", ret);
return ret;
}

Expand All @@ -62,25 +56,23 @@ static int ipts_surface_probe(struct platform_device *pdev)

static int ipts_surface_remove(struct platform_device *pdev)
{
int ret;

ret = intel_ipts_rm_fw_handler(&ipts_surface_request_firmware);
int ret = ipts_remove_companion(&ipts_surface_companion);
if (ret) {
dev_info(&pdev->dev, "Removing IPTS firmware handler failed, "
"error: %d\n", ret);
dev_info(&pdev->dev, "Removing IPTS companion failed, "
"error: %d\n", ret);
}

return 0;
}

static const struct acpi_device_id ipts_surface_acpi_match[] = {
{ "MSHW0076", 0 }, /* Surface Book 1 / Surface Studio */
{ "MSHW0078", 0 }, /* Surface Pro 4 */
{ "MSHW0079", 0 }, /* Surface Laptop 1 / 2 */
{ "MSHW0101", 0 }, /* Surface Book 2 15" */
{ "MSHW0102", 0 }, /* Surface Pro 2017 / 6 */
{ "MSHW0103", 0 }, /* unknown, but firmware exists */
{ "MSHW0137", 0 }, /* Surface Book 2 */
{ "MSHW0076", 0 }, // Surface Book 1 / Surface Studio
{ "MSHW0078", 0 }, // Surface Pro 4
{ "MSHW0079", 0 }, // Surface Laptop 1 / 2
{ "MSHW0101", 0 }, // Surface Book 2 15"
{ "MSHW0102", 0 }, // Surface Pro 2017 / 6
{ "MSHW0103", 0 }, // unknown, but firmware exists
{ "MSHW0137", 0 }, // Surface Book 2
{ },
};
MODULE_DEVICE_TABLE(acpi, ipts_surface_acpi_match);
Expand All @@ -98,3 +90,11 @@ module_platform_driver(ipts_surface_driver);
MODULE_AUTHOR("Dorian Stoll <dorian.stoll@tmsp.io>");
MODULE_DESCRIPTION("IPTS companion driver for Microsoft Surface");
MODULE_LICENSE("GPL v2");

IPTS_SURFACE_FIRMWARE("MSHW0076");
IPTS_SURFACE_FIRMWARE("MSHW0078");
IPTS_SURFACE_FIRMWARE("MSHW0079");
IPTS_SURFACE_FIRMWARE("MSHW0101");
IPTS_SURFACE_FIRMWARE("MSHW0102");
IPTS_SURFACE_FIRMWARE("MSHW0103");
IPTS_SURFACE_FIRMWARE("MSHW0137");
118 changes: 118 additions & 0 deletions drivers/misc/ipts/ipts-companion.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
#include <linux/firmware.h>
#include <linux/ipts.h>
#include <linux/ipts-companion.h>
#include <linux/mutex.h>

#include "ipts.h"
#include "ipts-companion.h"
#include "ipts-params.h"

#define IPTS_FW_PATH_FMT "intel/ipts/%s"

ipts_companion_t *ipts_companion;
DEFINE_MUTEX(ipts_companion_lock);

bool ipts_companion_available(void)
{
bool ret;
mutex_lock(&ipts_companion_lock);

ret = ipts_companion != NULL;

mutex_unlock(&ipts_companion_lock);
return ret;
}

/*
* General purpose API for adding or removing a companion driver
* A companion driver is a driver that implements hardware specific
* behaviour into IPTS, so it doesn't have to be hardcoded into the
* main driver. All requests to the companion driver should be wrapped,
* with a fallback in case a companion driver cannot be found.
*/

int ipts_add_companion(ipts_companion_t *companion)
{
int ret = 0;
mutex_lock(&ipts_companion_lock);

if (ipts_companion != NULL) {
ret = -EBUSY;
goto add_companion_return;
}

ipts_companion = companion;

add_companion_return:

mutex_unlock(&ipts_companion_lock);
return ret;
}
EXPORT_SYMBOL_GPL(ipts_add_companion);

int ipts_remove_companion(ipts_companion_t *companion)
{
int ret = 0;
mutex_lock(&ipts_companion_lock);

if (ipts_companion == NULL || companion == NULL) {
ret = 0;
goto remove_companion_return;
}

if (ipts_companion->name != companion->name) {
ret = -EPERM;
goto remove_companion_return;
}

ipts_companion = NULL;

remove_companion_return:

mutex_unlock(&ipts_companion_lock);
return ret;
}
EXPORT_SYMBOL_GPL(ipts_remove_companion);

/*
* Utility functions for IPTS. These functions replace codepaths in the IPTS
* driver, and redirect them to the companion driver, if one was found.
* Otherwise the legacy code gets executed as a fallback.
*/

int ipts_request_firmware(const struct firmware **fw, const char *name,
struct device *device)
{
int ret = 0;
char fw_path[MAX_IOCL_FILE_PATH_LEN];
mutex_lock(&ipts_companion_lock);

// Check if a companion was registered. If not, skip
// forward and try to load the firmware from the legacy path
if (ipts_companion == NULL || ipts_modparams.ignore_companion) {
goto request_firmware_fallback;
}

ret = ipts_companion->firmware_request(fw, name, device, ipts_companion);
if (!ret) {
goto request_firmware_return;
}

request_firmware_fallback:

// If fallback loading for firmware was disabled, abort.
// Return -ENOENT as no firmware file was found.
if (ipts_modparams.ignore_fw_fallback) {
ret = -ENOENT;
goto request_firmware_return;
}

// No firmware was found by the companion driver, try the generic path.
snprintf(fw_path, MAX_IOCL_FILE_PATH_LEN, IPTS_FW_PATH_FMT, name);
ret = request_firmware(fw, fw_path, device);

request_firmware_return:

mutex_unlock(&ipts_companion_lock);
return ret;
}
10 changes: 10 additions & 0 deletions drivers/misc/ipts/ipts-companion.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
#ifndef _IPTS_COMPANION_H_
#define _IPTS_COMPANION_H_

#include <linux/firmware.h>

bool ipts_companion_available(void);
int ipts_request_firmware(const struct firmware **fw, const char *name,
struct device *device);

#endif // _IPTS_COMPANION_H_
113 changes: 0 additions & 113 deletions drivers/misc/ipts/ipts-fw.c

This file was deleted.

12 changes: 0 additions & 12 deletions drivers/misc/ipts/ipts-fw.h

This file was deleted.

Loading

0 comments on commit a1531a7

Please sign in to comment.