// SPDX-License-Identifier: GPL-2.0-only /* * ISHTP bus driver * * Copyright (c) 2012-2016, Intel Corporation. */ #include <linux/module.h> #include <linux/init.h> #include <linux/kernel.h> #include <linux/device.h> #include <linux/sched.h> #include <linux/slab.h> #include "bus.h" #include "ishtp-dev.h" #include "client.h" #include "hbm.h" static int ishtp_use_dma; module_param_named(ishtp_use_dma, ishtp_use_dma, int, 0600); MODULE_PARM_DESC(…) …; #define to_ishtp_cl_driver(d) … #define to_ishtp_cl_device(d) … static bool ishtp_device_ready; /** * ishtp_recv() - process ishtp message * @dev: ishtp device * * If a message with valid header and size is received, then * this function calls appropriate handler. The host or firmware * address is zero, then they are host bus management message, * otherwise they are message fo clients. */ void ishtp_recv(struct ishtp_device *dev) { … } EXPORT_SYMBOL(…); /** * ishtp_send_msg() - Send ishtp message * @dev: ishtp device * @hdr: Message header * @msg: Message contents * @ipc_send_compl: completion callback * @ipc_send_compl_prm: completion callback parameter * * Send a multi fragment message via IPC. After sending the first fragment * the completion callback is called to schedule transmit of next fragment. * * Return: This returns IPC send message status. */ int ishtp_send_msg(struct ishtp_device *dev, struct ishtp_msg_hdr *hdr, void *msg, void(*ipc_send_compl)(void *), void *ipc_send_compl_prm) { … } /** * ishtp_write_message() - Send ishtp single fragment message * @dev: ishtp device * @hdr: Message header * @buf: message data * * Send a single fragment message via IPC. This returns IPC send message * status. * * Return: This returns IPC send message status. */ int ishtp_write_message(struct ishtp_device *dev, struct ishtp_msg_hdr *hdr, void *buf) { … } /** * ishtp_fw_cl_by_uuid() - locate index of fw client * @dev: ishtp device * @uuid: uuid of the client to search * * Search firmware client using UUID. * * Return: fw client index or -ENOENT if not found */ int ishtp_fw_cl_by_uuid(struct ishtp_device *dev, const guid_t *uuid) { … } EXPORT_SYMBOL(…); /** * ishtp_fw_cl_get_client() - return client information to client * @dev: the ishtp device structure * @uuid: uuid of the client to search * * Search firmware client using UUID and reture related client information. * * Return: pointer of client information on success, NULL on failure. */ struct ishtp_fw_client *ishtp_fw_cl_get_client(struct ishtp_device *dev, const guid_t *uuid) { … } EXPORT_SYMBOL(…); /** * ishtp_get_fw_client_id() - Get fw client id * @fw_client: firmware client used to fetch the ID * * This interface is used to reset HW get FW client id. * * Return: firmware client id. */ int ishtp_get_fw_client_id(struct ishtp_fw_client *fw_client) { … } EXPORT_SYMBOL(…); /** * ishtp_fw_cl_by_id() - return index to fw_clients for client_id * @dev: the ishtp device structure * @client_id: fw client id to search * * Search firmware client using client id. * * Return: index on success, -ENOENT on failure. */ int ishtp_fw_cl_by_id(struct ishtp_device *dev, uint8_t client_id) { … } /** * ishtp_cl_device_probe() - Bus probe() callback * @dev: the device structure * * This is a bus probe callback and calls the drive probe function. * * Return: Return value from driver probe() call. */ static int ishtp_cl_device_probe(struct device *dev) { … } /** * ishtp_cl_bus_match() - Bus match() callback * @dev: the device structure * @drv: the driver structure * * This is a bus match callback, called when a new ishtp_cl_device is * registered during ishtp bus client enumeration. Use the guid_t in * drv and dev to decide whether they match or not. * * Return: 1 if dev & drv matches, 0 otherwise. */ static int ishtp_cl_bus_match(struct device *dev, const struct device_driver *drv) { … } /** * ishtp_cl_device_remove() - Bus remove() callback * @dev: the device structure * * This is a bus remove callback and calls the drive remove function. * Since the ISH driver model supports only built in, this is * primarily can be called during pci driver init failure. * * Return: Return value from driver remove() call. */ static void ishtp_cl_device_remove(struct device *dev) { … } /** * ishtp_cl_device_suspend() - Bus suspend callback * @dev: device * * Called during device suspend process. * * Return: Return value from driver suspend() call. */ static int ishtp_cl_device_suspend(struct device *dev) { … } /** * ishtp_cl_device_resume() - Bus resume callback * @dev: device * * Called during device resume process. * * Return: Return value from driver resume() call. */ static int ishtp_cl_device_resume(struct device *dev) { … } /** * ishtp_cl_device_reset() - Reset callback * @device: ishtp client device instance * * This is a callback when HW reset is done and the device need * reinit. * * Return: Return value from driver reset() call. */ static int ishtp_cl_device_reset(struct ishtp_cl_device *device) { … } static ssize_t modalias_show(struct device *dev, struct device_attribute *a, char *buf) { … } static DEVICE_ATTR_RO(modalias); static struct attribute *ishtp_cl_dev_attrs[] = …; ATTRIBUTE_GROUPS(…); static int ishtp_cl_uevent(const struct device *dev, struct kobj_uevent_env *env) { … } static const struct dev_pm_ops ishtp_cl_bus_dev_pm_ops = …; static const struct bus_type ishtp_cl_bus_type = …; static void ishtp_cl_dev_release(struct device *dev) { … } static const struct device_type ishtp_cl_device_type = …; /** * ishtp_bus_add_device() - Function to create device on bus * @dev: ishtp device * @uuid: uuid of the client * @name: Name of the client * * Allocate ISHTP bus client device, attach it to uuid * and register with ISHTP bus. * * Return: ishtp_cl_device pointer or NULL on failure */ static struct ishtp_cl_device *ishtp_bus_add_device(struct ishtp_device *dev, guid_t uuid, char *name) { … } /** * ishtp_bus_remove_device() - Function to relase device on bus * @device: client device instance * * This is a counterpart of ishtp_bus_add_device. * Device is unregistered. * the device structure is freed in 'ishtp_cl_dev_release' function * Called only during error in pci driver init path. */ static void ishtp_bus_remove_device(struct ishtp_cl_device *device) { … } /** * ishtp_cl_driver_register() - Client driver register * @driver: the client driver instance * @owner: Owner of this driver module * * Once a client driver is probed, it created a client * instance and registers with the bus. * * Return: Return value of driver_register or -ENODEV if not ready */ int ishtp_cl_driver_register(struct ishtp_cl_driver *driver, struct module *owner) { … } EXPORT_SYMBOL(…); /** * ishtp_cl_driver_unregister() - Client driver unregister * @driver: the client driver instance * * Unregister client during device removal process. */ void ishtp_cl_driver_unregister(struct ishtp_cl_driver *driver) { … } EXPORT_SYMBOL(…); /** * ishtp_bus_event_work() - event work function * @work: work struct pointer * * Once an event is received for a client this work * function is called. If the device has registered a * callback then the callback is called. */ static void ishtp_bus_event_work(struct work_struct *work) { … } /** * ishtp_cl_bus_rx_event() - schedule event work * @device: client device instance * * Once an event is received for a client this schedules * a work function to process. */ void ishtp_cl_bus_rx_event(struct ishtp_cl_device *device) { … } /** * ishtp_register_event_cb() - Register callback * @device: client device instance * @event_cb: Event processor for an client * * Register a callback for events, called from client driver * * Return: Return 0 or -EALREADY if already registered */ int ishtp_register_event_cb(struct ishtp_cl_device *device, void (*event_cb)(struct ishtp_cl_device *)) { … } EXPORT_SYMBOL(…); /** * ishtp_get_device() - update usage count for the device * @cl_device: client device instance * * Increment the usage count. The device can't be deleted */ void ishtp_get_device(struct ishtp_cl_device *cl_device) { … } EXPORT_SYMBOL(…); /** * ishtp_put_device() - decrement usage count for the device * @cl_device: client device instance * * Decrement the usage count. The device can be deleted is count = 0 */ void ishtp_put_device(struct ishtp_cl_device *cl_device) { … } EXPORT_SYMBOL(…); /** * ishtp_set_drvdata() - set client driver data * @cl_device: client device instance * @data: driver data need to be set * * Set client driver data to cl_device->driver_data. */ void ishtp_set_drvdata(struct ishtp_cl_device *cl_device, void *data) { … } EXPORT_SYMBOL(…); /** * ishtp_get_drvdata() - get client driver data * @cl_device: client device instance * * Get client driver data from cl_device->driver_data. * * Return: pointer of driver data */ void *ishtp_get_drvdata(struct ishtp_cl_device *cl_device) { … } EXPORT_SYMBOL(…); /** * ishtp_dev_to_cl_device() - get ishtp_cl_device instance from device instance * @device: device instance * * Get ish_cl_device instance which embeds device instance in it. * * Return: pointer to ishtp_cl_device instance */ struct ishtp_cl_device *ishtp_dev_to_cl_device(struct device *device) { … } EXPORT_SYMBOL(…); /** * ishtp_bus_new_client() - Create a new client * @dev: ISHTP device instance * * Once bus protocol enumerates a client, this is called * to add a device for the client. * * Return: 0 on success or error code on failure */ int ishtp_bus_new_client(struct ishtp_device *dev) { … } /** * ishtp_cl_device_bind() - bind a device * @cl: ishtp client device * * Binds connected ishtp_cl to ISHTP bus device * * Return: 0 on success or fault code */ int ishtp_cl_device_bind(struct ishtp_cl *cl) { … } /** * ishtp_bus_remove_all_clients() - Remove all clients * @ishtp_dev: ishtp device * @warm_reset: Reset due to FW reset dure to errors or S3 suspend * * This is part of reset/remove flow. This function the main processing * only targets error processing, if the FW has forced reset or * error to remove connected clients. When warm reset the client devices are * not removed. */ void ishtp_bus_remove_all_clients(struct ishtp_device *ishtp_dev, bool warm_reset) { … } EXPORT_SYMBOL(…); /** * ishtp_reset_handler() - IPC reset handler * @dev: ishtp device * * ISHTP Handler for IPC_RESET notification */ void ishtp_reset_handler(struct ishtp_device *dev) { … } EXPORT_SYMBOL(…); /** * ishtp_reset_compl_handler() - Reset completion handler * @dev: ishtp device * * ISHTP handler for IPC_RESET sequence completion to start * host message bus start protocol sequence. */ void ishtp_reset_compl_handler(struct ishtp_device *dev) { … } EXPORT_SYMBOL(…); /** * ishtp_use_dma_transfer() - Function to use DMA * * This interface is used to enable usage of DMA * * Return non zero if DMA can be enabled */ int ishtp_use_dma_transfer(void) { … } /** * ishtp_device() - Return device pointer * @device: ISH-TP client device instance * * This interface is used to return device pointer from ishtp_cl_device * instance. * * Return: device *. */ struct device *ishtp_device(struct ishtp_cl_device *device) { … } EXPORT_SYMBOL(…); /** * ishtp_wait_resume() - Wait for IPC resume * @dev: ishtp device * * Wait for IPC resume * * Return: resume complete or not */ bool ishtp_wait_resume(struct ishtp_device *dev) { … } EXPORT_SYMBOL_GPL(…); /** * ishtp_get_pci_device() - Return PCI device dev pointer * This interface is used to return PCI device pointer * from ishtp_cl_device instance. * @device: ISH-TP client device instance * * Return: device *. */ struct device *ishtp_get_pci_device(struct ishtp_cl_device *device) { … } EXPORT_SYMBOL(…); /** * ishtp_trace_callback() - Return trace callback * @cl_device: ISH-TP client device instance * * This interface is used to return trace callback function pointer. * * Return: *ishtp_print_log() */ ishtp_print_log ishtp_trace_callback(struct ishtp_cl_device *cl_device) { … } EXPORT_SYMBOL(…); /** * ish_hw_reset() - Call HW reset IPC callback * @dev: ISHTP device instance * * This interface is used to reset HW in case of error. * * Return: value from IPC hw_reset callback */ int ish_hw_reset(struct ishtp_device *dev) { … } EXPORT_SYMBOL(…); /** * ishtp_bus_register() - Function to register bus * * This register ishtp bus * * Return: Return output of bus_register */ static int __init ishtp_bus_register(void) { … } /** * ishtp_bus_unregister() - Function to unregister bus * * This unregister ishtp bus */ static void __exit ishtp_bus_unregister(void) { … } module_init(…) …; module_exit(ishtp_bus_unregister); MODULE_DESCRIPTION(…) …; MODULE_LICENSE(…) …;