forked from Minki/linux
firmware: arm_scmi: Add support for notifications message processing
Add the mechanisms to distinguish notifications from delayed responses and command responses. Also add support to properly fetch notification messages upon reception. Notifications processing does not continue any further after the fetch phase. Link: https://lore.kernel.org/r/20200327143438.5382-5-cristian.marussi@arm.com Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com> [Reworked/renamed scmi_handle_xfer_delayed_resp()] Signed-off-by: Cristian Marussi <cristian.marussi@arm.com> Signed-off-by: Sudeep Holla <sudeep.holla@arm.com>
This commit is contained in:
parent
d5141f37c4
commit
4d09852b6f
@ -202,29 +202,42 @@ __scmi_xfer_put(struct scmi_xfers_info *minfo, struct scmi_xfer *xfer)
|
||||
spin_unlock_irqrestore(&minfo->xfer_lock, flags);
|
||||
}
|
||||
|
||||
/**
|
||||
* scmi_rx_callback() - callback for receiving messages
|
||||
*
|
||||
* @cinfo: SCMI channel info
|
||||
* @msg_hdr: Message header
|
||||
*
|
||||
* Processes one received message to appropriate transfer information and
|
||||
* signals completion of the transfer.
|
||||
*
|
||||
* NOTE: This function will be invoked in IRQ context, hence should be
|
||||
* as optimal as possible.
|
||||
*/
|
||||
void scmi_rx_callback(struct scmi_chan_info *cinfo, u32 msg_hdr)
|
||||
static void scmi_handle_notification(struct scmi_chan_info *cinfo, u32 msg_hdr)
|
||||
{
|
||||
struct scmi_xfer *xfer;
|
||||
struct device *dev = cinfo->dev;
|
||||
struct scmi_info *info = handle_to_scmi_info(cinfo->handle);
|
||||
struct scmi_xfers_info *minfo = &info->rx_minfo;
|
||||
|
||||
xfer = scmi_xfer_get(cinfo->handle, minfo);
|
||||
if (IS_ERR(xfer)) {
|
||||
dev_err(dev, "failed to get free message slot (%ld)\n",
|
||||
PTR_ERR(xfer));
|
||||
info->desc->ops->clear_notification(cinfo);
|
||||
return;
|
||||
}
|
||||
|
||||
unpack_scmi_header(msg_hdr, &xfer->hdr);
|
||||
scmi_dump_header_dbg(dev, &xfer->hdr);
|
||||
info->desc->ops->fetch_notification(cinfo, info->desc->max_msg_size,
|
||||
xfer);
|
||||
|
||||
trace_scmi_rx_done(xfer->transfer_id, xfer->hdr.id,
|
||||
xfer->hdr.protocol_id, xfer->hdr.seq,
|
||||
MSG_TYPE_NOTIFICATION);
|
||||
|
||||
__scmi_xfer_put(minfo, xfer);
|
||||
|
||||
info->desc->ops->clear_notification(cinfo);
|
||||
}
|
||||
|
||||
static void scmi_handle_response(struct scmi_chan_info *cinfo,
|
||||
u16 xfer_id, u8 msg_type)
|
||||
{
|
||||
struct scmi_xfer *xfer;
|
||||
struct device *dev = cinfo->dev;
|
||||
struct scmi_info *info = handle_to_scmi_info(cinfo->handle);
|
||||
struct scmi_xfers_info *minfo = &info->tx_minfo;
|
||||
u16 xfer_id = MSG_XTRACT_TOKEN(msg_hdr);
|
||||
u8 msg_type = MSG_XTRACT_TYPE(msg_hdr);
|
||||
struct device *dev = cinfo->dev;
|
||||
struct scmi_xfer *xfer;
|
||||
|
||||
if (msg_type == MSG_TYPE_NOTIFICATION)
|
||||
return; /* Notifications not yet supported */
|
||||
|
||||
/* Are we even expecting this? */
|
||||
if (!test_bit(xfer_id, minfo->xfer_alloc_table)) {
|
||||
@ -248,6 +261,37 @@ void scmi_rx_callback(struct scmi_chan_info *cinfo, u32 msg_hdr)
|
||||
complete(&xfer->done);
|
||||
}
|
||||
|
||||
/**
|
||||
* scmi_rx_callback() - callback for receiving messages
|
||||
*
|
||||
* @cinfo: SCMI channel info
|
||||
* @msg_hdr: Message header
|
||||
*
|
||||
* Processes one received message to appropriate transfer information and
|
||||
* signals completion of the transfer.
|
||||
*
|
||||
* NOTE: This function will be invoked in IRQ context, hence should be
|
||||
* as optimal as possible.
|
||||
*/
|
||||
void scmi_rx_callback(struct scmi_chan_info *cinfo, u32 msg_hdr)
|
||||
{
|
||||
u16 xfer_id = MSG_XTRACT_TOKEN(msg_hdr);
|
||||
u8 msg_type = MSG_XTRACT_TYPE(msg_hdr);
|
||||
|
||||
switch (msg_type) {
|
||||
case MSG_TYPE_NOTIFICATION:
|
||||
scmi_handle_notification(cinfo, msg_hdr);
|
||||
break;
|
||||
case MSG_TYPE_COMMAND:
|
||||
case MSG_TYPE_DELAYED_RESP:
|
||||
scmi_handle_response(cinfo, xfer_id, msg_type);
|
||||
break;
|
||||
default:
|
||||
WARN_ONCE(1, "received unknown msg_type:%d\n", msg_type);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* scmi_xfer_put() - Release a transmit message
|
||||
*
|
||||
|
Loading…
Reference in New Issue
Block a user