static bool hci_pio_dequeue_xfer_common()

in master/mipi-i3c-hci/pio.c [621:681]


static bool hci_pio_dequeue_xfer_common(struct i3c_hci *hci,
					struct hci_pio_data *pio,
					struct hci_xfer *xfer, int n)
{
	struct hci_xfer *p, **p_prev_next;
	int i;

	/*
	 * To safely dequeue a transfer request, it must be either entirely
	 * processed, or not yet processed at all. If our request tail is
	 * reachable from either the data or resp list that means the command
	 * was submitted and not yet completed.
	 */
	for (p = pio->curr_resp; p; p = p->next_resp)
		for (i = 0; i < n; i++)
			if (p == &xfer[i])
				goto pio_screwed;
	for (p = pio->curr_rx; p; p = p->next_data)
		for (i = 0; i < n; i++)
			if (p == &xfer[i])
				goto pio_screwed;
	for (p = pio->curr_tx; p; p = p->next_data)
		for (i = 0; i < n; i++)
			if (p == &xfer[i])
				goto pio_screwed;

	/*
	 * The command was completed, or wasn't yet submitted.
	 * Unlink it from the que if the later.
	 */
	p_prev_next = &pio->curr_xfer;
	for (p = pio->curr_xfer; p; p = p->next_xfer) {
		if (p == &xfer[0]) {
			*p_prev_next = xfer[n - 1].next_xfer;
			break;
		}
		p_prev_next = &p->next_xfer;
	}

	/* return true if we actually unqueued something */
	return !!p;

pio_screwed:
	/*
	 * Life is tough. We must invalidate the hardware state and
	 * discard everything that is still queued.
	 */
	for (p = pio->curr_resp; p; p = p->next_resp) {
		p->response = FIELD_PREP(RESP_ERR_FIELD, RESP_ERR_HC_TERMINATED);
		if (p->completion)
			complete(p->completion);
	}
	for (p = pio->curr_xfer; p; p = p->next_xfer) {
		p->response = FIELD_PREP(RESP_ERR_FIELD, RESP_ERR_HC_TERMINATED);
		if (p->completion)
			complete(p->completion);
	}
	pio->curr_xfer = pio->curr_rx = pio->curr_tx = pio->curr_resp = NULL;

	return true;
}