/** * DOC: MEI_PXP Client Driver * * The mei_pxp driver acts as a translation layer between PXP * protocol implementer (I915) and ME FW by translating PXP * negotiation messages to ME FW command payloads and vice versa.
*/
staticinlineint mei_pxp_reenable(conststruct device *dev, struct mei_cl_device *cldev)
{ int ret;
dev_warn(dev, "Trying to reset the channel...\n");
ret = mei_cldev_disable(cldev); if (ret < 0)
dev_warn(dev, "mei_cldev_disable failed. %d\n", ret); /* * Explicitly ignoring disable failure, * enable may fix the states and succeed
*/
ret = mei_cldev_enable(cldev); if (ret < 0)
dev_err(dev, "mei_cldev_enable failed. %d\n", ret); return ret;
}
/** * mei_pxp_send_message() - Sends a PXP message to ME FW. * @dev: device corresponding to the mei_cl_device * @message: a message buffer to send * @size: size of the message * @timeout_ms: timeout in milliseconds, zero means wait indefinitely. * * Returns: 0 on Success, <0 on Failure with the following defined failures. * -ENODEV: Client was not connected. * Caller may attempt to try again immediately. * -ENOMEM: Internal memory allocation failure experienced. * Caller may sleep to allow kernel reclaim before retrying. * -EINTR : Calling thread received a signal. Caller may choose * to abandon with the same thread id. * -ETIME : Request is timed out. * Caller may attempt to try again immediately.
*/ staticint
mei_pxp_send_message(struct device *dev, constvoid *message, size_t size, unsignedlong timeout_ms)
{ struct mei_cl_device *cldev;
ssize_t byte; int ret;
if (!dev || !message) return -EINVAL;
cldev = to_mei_cl_device(dev);
byte = mei_cldev_send_timeout(cldev, message, size, timeout_ms); if (byte < 0) {
dev_dbg(dev, "mei_cldev_send failed. %zd\n", byte); switch (byte) { case -ENOMEM:
fallthrough; case -ENODEV:
fallthrough; case -ETIME:
ret = mei_pxp_reenable(dev, cldev); if (ret)
byte = ret; break;
} return byte;
}
return 0;
}
/** * mei_pxp_receive_message() - Receives a PXP message from ME FW. * @dev: device corresponding to the mei_cl_device * @buffer: a message buffer to contain the received message * @size: size of the buffer * @timeout_ms: timeout in milliseconds, zero means wait indefinitely. * * Returns: number of bytes send on Success, <0 on Failure with the following defined failures. * -ENODEV: Client was not connected. * Caller may attempt to try again from send immediately. * -ENOMEM: Internal memory allocation failure experienced. * Caller may sleep to allow kernel reclaim before retrying. * -EINTR : Calling thread received a signal. Caller will need to repeat calling * (with a different owning thread) to retrieve existing unclaimed response * (and may discard it). * -ETIME : Request is timed out. * Caller may attempt to try again from send immediately.
*/ staticint
mei_pxp_receive_message(struct device *dev, void *buffer, size_t size, unsignedlong timeout_ms)
{ struct mei_cl_device *cldev;
ssize_t byte; bool retry = false; int ret;
if (!dev || !buffer) return -EINVAL;
cldev = to_mei_cl_device(dev);
retry:
byte = mei_cldev_recv_timeout(cldev, buffer, size, timeout_ms); if (byte < 0) {
dev_dbg(dev, "mei_cldev_recv failed. %zd\n", byte); switch (byte) { case -ENOMEM: /* Retry the read when pages are reclaimed */
msleep(20); if (!retry) {
retry = true; goto retry;
}
fallthrough; case -ENODEV:
fallthrough; case -ETIME:
ret = mei_pxp_reenable(dev, cldev); if (ret)
byte = ret; break;
}
}
return byte;
}
/** * mei_pxp_gsc_command() - sends a gsc command, by sending * a sgl mei message to gsc and receiving reply from gsc * * @dev: device corresponding to the mei_cl_device * @client_id: client id to send the command to * @fence_id: fence id to send the command to * @sg_in: scatter gather list containing addresses for rx message buffer * @total_in_len: total length of data in 'in' sg, can be less than the sum of buffers sizes * @sg_out: scatter gather list containing addresses for tx message buffer * * Return: bytes sent on Success, <0 on Failure
*/ static ssize_t mei_pxp_gsc_command(struct device *dev, u8 client_id, u32 fence_id, struct scatterlist *sg_in, size_t total_in_len, struct scatterlist *sg_out)
{ struct mei_cl_device *cldev;
/** * mei_pxp_component_match - compare function for matching mei pxp. * * The function checks if the driver is i915, the subcomponent is PXP * and the grand parent of pxp and the parent of i915 are the same * PCH device. * * @dev: master device * @subcomponent: subcomponent to match (I915_COMPONENT_PXP) * @data: compare data (mei pxp device) * * Return: * * 1 - if components match * * 0 - otherwise
*/ staticint mei_pxp_component_match(struct device *dev, int subcomponent, void *data)
{ struct device *base = data; struct pci_dev *pdev;
if (!dev) return 0;
if (!dev_is_pci(dev)) return 0;
pdev = to_pci_dev(dev);
if (pdev->vendor != PCI_VENDOR_ID_INTEL) return 0;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.