return no_free_ptr(i);
}
-static int scmi_iterator_run(void *iter)
+static int __scmi_iterator_run(void *iter, unsigned int *start, unsigned int *end)
{
int ret;
struct scmi_iterator_ops *iops;
const struct scmi_protocol_handle *ph;
struct scmi_iterator_state *st;
+ struct scmi_iterator *i;
if (!iter)
return -EINVAL;
- /* Take ownership of the iterator */
- struct scmi_iterator *i __free(kfree) = iter;
-
+ i = iter;
iops = i->ops;
ph = i->ph;
st = &i->state;
+ /* Reinitialize state for next run */
+ st->num_returned = 0;
+ st->num_remaining = 0;
+ st->desc_index = start ? *start : 0;
+
do {
iops->prepare_message(i->msg, st->desc_index, i->priv);
ret = ph->xops->do_xfer(ph, i->t);
if (ret)
- break;
+ return ret;
st->rx_len = i->t->rx.len;
ret = iops->update_state(st, i->resp, i->priv);
if (ret)
- break;
+ return ret;
if (st->num_returned > st->max_resources - st->desc_index) {
dev_err(ph->dev,
"No. of resources can't exceed %d\n",
st->max_resources);
- ret = -EINVAL;
- break;
+ return -EINVAL;
}
- for (st->loop_idx = 0; !ret && st->loop_idx < st->num_returned;
- st->loop_idx++)
+ for (st->loop_idx = 0; st->loop_idx < st->num_returned; st->loop_idx++) {
ret = iops->process_response(ph, i->resp, st, i->priv);
-
- if (ret)
- break;
+ if (ret)
+ return ret;
+ }
st->desc_index += st->num_returned;
ph->xops->reset_rx_to_maxsz(ph, i->t);
* check for both returned and remaining to avoid infinite
* loop due to buggy firmware
*/
- } while (st->num_returned && st->num_remaining);
+ } while (st->num_returned && st->num_remaining &&
+ (!end || (st->desc_index <= min(*end, st->max_resources - 1))));
- /* Finalize and destroy iterator */
- ph->xops->xfer_put(ph, i->t);
+ return 0;
+}
+
+static void scmi_iterator_cleanup(void *iter)
+{
+ struct scmi_iterator *i = iter;
+
+ i->ph->xops->xfer_put(i->ph, i->t);
+ kfree(i);
+}
+
+static int scmi_iterator_run(void *iter)
+{
+ int ret;
+
+ ret = __scmi_iterator_run(iter, NULL, NULL);
+ scmi_iterator_cleanup(iter);
return ret;
}
+static int scmi_iterator_run_bound(void *iter, unsigned int *start,
+ unsigned int *end)
+{
+ return __scmi_iterator_run(iter, start, end);
+}
+
struct scmi_msg_get_fc_info {
__le32 domain;
__le32 message_id;
.get_max_msg_size = scmi_common_get_max_msg_size,
.iter_response_init = scmi_iterator_init,
.iter_response_run = scmi_iterator_run,
+ .iter_response_run_bound = scmi_iterator_run_bound,
+ .iter_response_cleanup = scmi_iterator_cleanup,
.protocol_msg_check = scmi_protocol_msg_check,
.fastchannel_init = scmi_common_fastchannel_init,
.fastchannel_db_ring = scmi_common_fastchannel_db_ring,
* multi-part responses using the custom operations
* provided in @ops.
* @iter_response_run: A common helper to trigger the run of a previously
- * initialized iterator.
+ * initialized iterator. Note that unbound iterators are
+ * automatically cleaned up.
+ * @iter_response_run_bound: A common helper to trigger the run of a previously
+ * initialized iterator, but only within the
+ * specified, optional, @start and @end resource
+ * indexes. Note that these bound-iterators need
+ * explicit cleanup via @iter_response_bound_cleanup.
+ * @iter_response_bound_cleanup: A common helper to finally release the iterator
+ * for bound iterators.
* @protocol_msg_check: A common helper to check is a specific protocol message
* is supported.
* @fastchannel_init: A common helper used to initialize FC descriptors by
unsigned int max_resources, u8 msg_id,
size_t tx_size, void *priv);
int (*iter_response_run)(void *iter);
+ int (*iter_response_run_bound)(void *iter,
+ unsigned int *start, unsigned int *end);
+ void (*iter_response_cleanup)(void *iter);
int (*protocol_msg_check)(const struct scmi_protocol_handle *ph,
u32 message_id, u32 *attributes);
void (*fastchannel_init)(const struct scmi_protocol_handle *ph,