static int mhuv2_allocate_channels()

in arm_mhuv2.c [870:927]


static int mhuv2_allocate_channels(struct mhuv2 *mhu)
{
	struct mbox_controller *mbox = &mhu->mbox;
	struct mhuv2_mbox_chan_priv *priv;
	struct device *dev = mbox->dev;
	struct mbox_chan *chans;
	int protocol, windows = 0, next_window = 0, i, j, k;

	chans = devm_kcalloc(dev, mbox->num_chans, sizeof(*chans), GFP_KERNEL);
	if (!chans)
		return -ENOMEM;

	mbox->chans = chans;

	for (i = 0; i < mhu->length; i += 2) {
		next_window += windows;

		protocol = mhu->protocols[i];
		windows = mhu->protocols[i + 1];

		if (protocol == DATA_TRANSFER) {
			priv = devm_kmalloc(dev, sizeof(*priv), GFP_KERNEL);
			if (!priv)
				return -ENOMEM;

			priv->ch_wn_idx = next_window;
			priv->ops = &mhuv2_data_transfer_ops;
			priv->windows = windows;
			chans++->con_priv = priv;
			continue;
		}

		for (j = 0; j < windows; j++) {
			for (k = 0; k < MHUV2_STAT_BITS; k++) {
				priv = devm_kmalloc(dev, sizeof(*priv), GFP_KERNEL);
				if (!priv)
					return -ENOMEM;

				priv->ch_wn_idx = next_window + j;
				priv->ops = &mhuv2_doorbell_ops;
				priv->doorbell = k;
				chans++->con_priv = priv;
			}

			/*
			 * Permanently enable interrupt as we can't
			 * control it per doorbell.
			 */
			if (mhu->frame == SENDER_FRAME && mhu->minor)
				writel_relaxed(0x1, &mhu->send->ch_wn[priv->ch_wn_idx].int_en);
		}
	}

	/* Make sure we have initialized all channels */
	BUG_ON(chans - mbox->chans != mbox->num_chans);

	return 0;
}