From patchwork Wed Jul 17 19:26:15 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "tushar.khandelwal@arm.com" X-Patchwork-Id: 169161 Delivered-To: patch@linaro.org Received: by 2002:a92:4782:0:0:0:0:0 with SMTP id e2csp1374302ilk; Wed, 17 Jul 2019 12:26:46 -0700 (PDT) X-Google-Smtp-Source: APXvYqysiT6U41LhO5gDWzhjDcunlJAdGXq+fBwGZebOCkKgmzREfSnRKS7NT/IF/wHV4lV0GoCC X-Received: by 2002:a63:6901:: with SMTP id e1mr14180401pgc.390.1563391606625; Wed, 17 Jul 2019 12:26:46 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1563391606; cv=none; d=google.com; s=arc-20160816; b=ZHZ3Ko0F/2qOA5Etl45z4Xc5cDS7AKQfYc3CMlyA/Fgup5dWQRBEONRqt5ykjd2okz BLfTj80aAuc6G+IcOJiSoz0n0kTUl6q/Rw8QCvzf/lC9vJhsmI2ov7t0jcFuMvroSAxB Copys/DSU99+xd2d1K3cj8ICyGuQpNlKq6HG08KKzMxqkCQS7iUN5o9HRrHBqq0Mv2LW N8+R5XPtaInb8wJDigCm6klCda5LWqtlkebNNB5droal5UNWyzB8Q3gbxfPA5SMu4q7v oEovx+gfAB5fMV/p4qdyiOQaBhp9nnyPn9/ZFlx9Fbbe560eWCH3MggK/5EcCfWiSAtH nItA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:references:in-reply-to:message-id:date :subject:cc:to:from; bh=I1MbKJ0i4lcLgytdGcGjE76pdg6qLH27z52oFhcBPnE=; b=sgGa5HWBebH4BXNGwgZml0rX4fnyX62b3E6295vtdCaYqVem/vfGEaUSqooVHRjRaD HWdh+qyHkAslnFw3mIrnvsuKfqly/k7OySEL6awlm09jcl6S7n5vCqDFbxBBMF/fGHT5 6Z/tL8eFSx6q84xVK33S3dS8AzgeEe5jKnSqtJ690gPHyQm+Sfau+lx/qcsihMBYWW7H b6JXz+v1/Qc2oix+7zcmZvk+VbbfbMihcfIBHGAB7CxEIkCEkkJSMqVm8lT6B+UVlTA0 N+a/PDaxe3Je9FD9j0fgb+rBqX+3iuFx0mzNG7r68N4kMaNuwS5etT8f1bUSozUh4PB3 p4bQ== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id h16si215859plr.94.2019.07.17.12.26.46; Wed, 17 Jul 2019 12:26:46 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727556AbfGQT0p (ORCPT + 29 others); Wed, 17 Jul 2019 15:26:45 -0400 Received: from foss.arm.com ([217.140.110.172]:50286 "EHLO foss.arm.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727270AbfGQT0o (ORCPT ); Wed, 17 Jul 2019 15:26:44 -0400 Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id 19D84344; Wed, 17 Jul 2019 12:26:43 -0700 (PDT) Received: from tuskha01.cambridge.arm.com (tuskha01.cambridge.arm.com [10.1.196.61]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPA id EDDEF3F71A; Wed, 17 Jul 2019 12:26:41 -0700 (PDT) From: Tushar Khandelwal To: linux-kernel@vger.kernel.org Cc: tushar.2nov@gmail.com, morten_bp@live.dk, jassisinghbrar@gmail.com, nd@arm.com, Morten Borup Petersen , Tushar Khandelwal , devicetree@vger.kernel.org Subject: [PATCH 3/4] mailbox: arm_mhuv2: add doorbell transport protocol operations Date: Wed, 17 Jul 2019 20:26:15 +0100 Message-Id: <20190717192616.1731-4-tushar.khandelwal@arm.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20190717192616.1731-1-tushar.khandelwal@arm.com> References: <20190717192616.1731-1-tushar.khandelwal@arm.com> Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Morten Borup Petersen In doorbell mode, the mailbox controller will provide a mailbox for each flag bit available in the combined number of channel windows available within the MHU device. When in doorbell mode, the MHU should be used solely as an interrupt generating mechanism. If data is to be transmitted, this must be done out-band, ie. through shared memory, by a driving utilizing the mailbox for interrupt generation. Signed-off-by: Morten Borup Petersen Signed-off-by: Tushar Khandelwal Cc:Jassi Brar reg.recv->channel[ch_window_idx].STAT_CLEAR); + return 0; +} + +static inline int mhuv2_send_data_doorbell(struct arm_mhuv2 *mhuv2, + struct mbox_chan *chan, + const struct arm_mbox_msg *msg) +{ + const u32 ch_mbox_idx = mhuv2_chan_idx(chan); + const u32 ch_window_idx = ch_mbox_idx / MHUV2_STAT_BITS; + const u32 ch_window_reg_idx = ch_mbox_idx % MHUV2_STAT_BITS; + + writel_relaxed( + readl_relaxed(&mhuv2->reg.send->channel[ch_window_idx].STAT) | + BIT(ch_window_reg_idx), + &mhuv2->reg.send->channel[ch_window_idx].STAT_SET); + return 0; +} + +static inline int mhuv2_last_tx_done_doorbell(struct arm_mhuv2 *mhuv2, + struct mbox_chan *chan) +{ + const u32 ch_mbox_idx = mhuv2_chan_idx(chan); + const u32 ch_window_idx = ch_mbox_idx / MHUV2_STAT_BITS; + const u32 ch_window_reg_idx = ch_mbox_idx % MHUV2_STAT_BITS; + + return (readl_relaxed(&mhuv2->reg.send->channel[ch_window_idx].STAT) & + BIT(ch_window_reg_idx)) == 0; +} + +static inline int mhuv2_setup_doorbell(struct arm_mhuv2 *mhuv2) +{ + int i; + const u32 channel_windows = + readl_relaxed_bitfield(mhuv2->frame == RECEIVER_FRAME ? + &mhuv2->reg.recv->MHU_CFG : + &mhuv2->reg.send->MHU_CFG, + NUM_CH); + + mhuv2->mbox.num_chans = MHUV2_STAT_BITS * channel_windows; + mhuv2->mbox.chans = + devm_kzalloc(mhuv2->dev, + mhuv2->mbox.num_chans * sizeof(struct mbox_chan), + GFP_KERNEL); + + for (i = 0; i < mhuv2->mbox.num_chans; i++) { + mhuv2->mbox.chans[i].con_priv = + devm_kzalloc(mhuv2->dev, + sizeof(struct arm_mhuv2_mbox_chan_priv), + GFP_KERNEL); + mhuv2_chan_idx(&mhuv2->mbox.chans[i]) = i; + } + + if (mhuv2->frame == RECEIVER_FRAME) { + /* Ensure all status registers are unmasked */ + for (i = 0; i < channel_windows; i++) { + writel_relaxed(0x0, + &mhuv2->reg.recv->channel[i].MASK_SET); + } + } + + return 0; +} + +static inline struct mbox_chan * + mhuv2_get_active_mbox_chan_doorbell(struct arm_mhuv2 *mhuv2) +{ + const u32 ch_window_idx = mhuv2_combint_idx(mhuv2); + const u32 ch_window_reg_idx = __find_set_bit( + readl_relaxed(&mhuv2->reg.recv->channel[ch_window_idx].STAT)); + if (ch_window_reg_idx == -1) + return ERR_PTR(-EIO); + + return &mhuv2->mbox.chans[ch_window_reg_idx + + ch_window_idx * MHUV2_STAT_BITS]; +} + +static const struct mhuv2_ops mhuv2_doorbell_ops = { + .read_data = mhuv2_read_data_doorbell, + .clear_data = mhuv2_clear_data_doorbell, + .send_data = mhuv2_send_data_doorbell, + .setup = mhuv2_setup_doorbell, + .last_tx_done = mhuv2_last_tx_done_doorbell, + .get_active_mbox_chan = mhuv2_get_active_mbox_chan_doorbell, +}; +/* ========================================================================== */ + /* * MHUv2 receiver interrupt service routine * @@ -638,6 +743,9 @@ static int mhuv2_probe(struct amba_device *adev, const struct amba_id *id) case SINGLE_WORD: mhuv2->ops = &mhuv2_single_word_ops; break; + case DOORBELL: + mhuv2->ops = &mhuv2_doorbell_ops; + break; default: return -ENODEV; } From patchwork Wed Jul 17 19:26:16 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "tushar.khandelwal@arm.com" X-Patchwork-Id: 169162 Delivered-To: patch@linaro.org Received: by 2002:a92:4782:0:0:0:0:0 with SMTP id e2csp1374380ilk; Wed, 17 Jul 2019 12:26:50 -0700 (PDT) X-Google-Smtp-Source: APXvYqx80ON4Y3SDJVS44xnN1jPnnRQ4WRhxhaU0jVqP2o4LRfjcLEv9ThyMwfOTYv+4s7DoXezK X-Received: by 2002:a63:188:: with SMTP id 130mr42454762pgb.231.1563391610240; Wed, 17 Jul 2019 12:26:50 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1563391610; cv=none; d=google.com; s=arc-20160816; b=HM0+vS31sY4o4YzLeWosZtznGveUIY6/oWCshL51IKZoSW9cU7fJype7QfZ9aGRJJa J0rg8lfrEl1EhSAF4C75xdx0WtChcp/FUeOA7yc8kHTLdMLtQGl4l6cBvTyvd9ZjhWcZ ZSJhPxibR9kB+8f/JToeVmCYQgEBtj/RW0K9jO011+xrWBwBFkMUHP+KvwnIjLkghojz 3zQ+DVtnQ49qQY1WAqF8owBFjAHHDxSpJ2PpMuSJjyI2htuFyT8ZiD4Z2LL4vK3+KlC1 i/dGqFWpRogxw85KH40gORqC+3hINY3WZNYlQmvsJFTIX5znu/s91ZKvkz87lywd0XB6 42Hw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:references:in-reply-to:message-id:date :subject:cc:to:from; bh=8qWND4JBlSk8/luycJNomcCEwdCyqlrAhtqFNRjtEBM=; b=007tvxfu/UiBquBn/BalV2KCwcls7NcTosbzsKxwi8KBoJ0MVjsw4nt5mvrqXlP95y T0kwIoUa5U3n1dQZZ1hv3rYuJ8edI4Vu9/7GJQZZ9zYMmsuDlqXczphUQyPgrc6Uvd74 HfUtQj1RSqr2JHyYCnFr1Snvl06VpIzlnwxagD6k7ZNROEdSSOZ3bIiY8CE5TDxOiEjs f8PNyPnpknSZMgXdrFKPRnbHRpRP49aZmTb1IaDMalPJu4BrQHH/nlJ1kh7hG0BDA3FB v4ij/V/q7y5VbPKweyutBtqBEjW4U/m2BBexpMVDHr9dxGl26CmQk/jL3GAeQeb0zcJ0 OEXA== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id v136si25026128pfc.9.2019.07.17.12.26.49; Wed, 17 Jul 2019 12:26:50 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727954AbfGQT0s (ORCPT + 29 others); Wed, 17 Jul 2019 15:26:48 -0400 Received: from foss.arm.com ([217.140.110.172]:50296 "EHLO foss.arm.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727270AbfGQT0r (ORCPT ); Wed, 17 Jul 2019 15:26:47 -0400 Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id 1BD6F337; Wed, 17 Jul 2019 12:26:46 -0700 (PDT) Received: from tuskha01.cambridge.arm.com (tuskha01.cambridge.arm.com [10.1.196.61]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPA id F10953F71A; Wed, 17 Jul 2019 12:26:44 -0700 (PDT) From: Tushar Khandelwal To: linux-kernel@vger.kernel.org Cc: tushar.2nov@gmail.com, morten_bp@live.dk, jassisinghbrar@gmail.com, nd@arm.com, Morten Borup Petersen , Tushar Khandelwal , devicetree@vger.kernel.org Subject: [PATCH 4/4] mailbox: arm_mhuv2: add multi word transport protocol operations Date: Wed, 17 Jul 2019 20:26:16 +0100 Message-Id: <20190717192616.1731-5-tushar.khandelwal@arm.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20190717192616.1731-1-tushar.khandelwal@arm.com> References: <20190717192616.1731-1-tushar.khandelwal@arm.com> Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Morten Borup Petersen When in multi-word mode, the mailbox controller will provide a single mailbox. It is required that the MHU device has at least 2 channel windows available for the MHU to function in multi-word mode. Transmitting and receiving data through the mailbox framework in multi-word mode is done through a struct arm_mbox_msg. Signed-off-by: Morten Borup Petersen Signed-off-by: Tushar Khandelwal Cc: jassisinghbrar@gmail.com Cc: devicetree@vger.kernel.org --- drivers/mailbox/arm_mhu_v2.c | 225 +++++++++++++++++++++++++++++++++++ 1 file changed, 225 insertions(+) -- 2.17.1 diff --git a/drivers/mailbox/arm_mhu_v2.c b/drivers/mailbox/arm_mhu_v2.c index 0e3fa5917925..324b19bdb28a 100644 --- a/drivers/mailbox/arm_mhu_v2.c +++ b/drivers/mailbox/arm_mhu_v2.c @@ -430,6 +430,228 @@ static const struct mhuv2_ops mhuv2_single_word_ops = { }; /* ========================================================================== */ +/* ================ Multi word transport protocol operations ================ */ +static inline int mhuv2_read_data_multi_word(struct arm_mhuv2 *mhuv2, + struct mbox_chan *chan, + struct arm_mbox_msg *msg) +{ + int ch; + const int channels = + readl_relaxed_bitfield(&mhuv2->reg.recv->MHU_CFG, NUM_CH); + + msg->data = kzalloc(MHUV2_STAT_BYTES * channels, GFP_KERNEL); + + for (ch = 0; ch < channels; ch++) { + /* + * Messages are expected to be received in order of most + * significant word to least significant word. + * (see mhuv2_send_data_multi_word) + */ + const mhuv2_stat_reg_t word = + readl_relaxed(&mhuv2->reg.recv->channel[ch].STAT); + ((mhuv2_stat_reg_t *)msg->data)[channels - 1 - ch] = word; + } + + msg->len = channels * MHUV2_STAT_BYTES; + return 0; +} + +static inline int mhuv2_clear_data_multi_word(struct arm_mhuv2 *mhuv2, + struct mbox_chan *chan, + struct arm_mbox_msg *msg) +{ + int ch; + const int channels = + readl_relaxed_bitfield(&mhuv2->reg.recv->MHU_CFG, NUM_CH); + + for (ch = 0; ch < channels; ch++) { + /* + * Last channel window must be cleared as the final operation. + * Upon clearing the last channel window register, which is + * unmasked in multi-word mode, the interrupt is deasserted. + */ + writel_relaxed( + readl_relaxed(&mhuv2->reg.recv->channel[ch].STAT), + &mhuv2->reg.recv->channel[ch].STAT_CLEAR); + } + return 0; +} + +static inline int __mhuv2_mw_bytes_to_send(const int bytes_in_round, + const int bytes_left) +{ + /* + * Bytes to send on the current channel will always be MHUV2_STAT_BYTES + * unless in the last round and + * msg->len % MHUV2_STAT_BYTES != 0 + */ + if (bytes_in_round % MHUV2_STAT_BYTES != 0) { + const int bts = bytes_left % MHUV2_STAT_BYTES; + return bts == 0 ? MHUV2_STAT_BYTES : bts; + } else { + return MHUV2_STAT_BYTES; + } +} + +static inline int mhuv2_send_data_multi_word(struct arm_mhuv2 *mhuv2, + struct mbox_chan *chan, + const struct arm_mbox_msg *msg) +{ + /* + * Message will be transmitted from most significant to least + * significant word. This is to allow for messages shorter than + * $channels to still trigger the receiver interrupt which gets + * activated when the last STAT register is written. As an example, a + * 6-word message is to be written on a 4-channel MHU connection: + * Registers marked with '*' are masked, and will not generate an + * interrupt on the receiver side once written. + * + * uint32_t *data = [0x00000001],[0x00000002],[0x00000003],[0x00000004], + * [0x00000005], [0x00000006] + * + * ROUND 1: + * STAT reg To write Write sequence + * [ STAT 3 ] <- [0x00000001] 4 <- triggers interrupt on receiver + * *[ STAT 2 ] <- [0x00000002] 3 + * *[ STAT 1 ] <- [0x00000003] 2 + * *[ STAT 0 ] <- [0x00000004] 1 + * + * data += 4 // Increment data pointer by number of STAT regs + * + * ROUND 2: + * STAT reg To write Write sequence + * [ STAT 3 ] <- [0x00000005] 2 <- triggers interrupt on receiver + * *[ STAT 2 ] <- [0x00000006] 1 + * *[ STAT 1 ] <- [0x00000000] + * *[ STAT 0 ] <- [0x00000000] + */ + int bytes_left, bytes_to_send, i, ch_idx; + const int ch_windows = + readl_relaxed_bitfield(&mhuv2->reg.recv->MHU_CFG, NUM_CH); + const size_t round_capacity = ch_windows * MHUV2_STAT_BYTES; + + bytes_left = msg->len; + mhuv2_stat_reg_t *data = msg->data; + + while (bytes_left > 0) { + /* Note: Each entry of this loop indicates a new ROUND */ + if (*(u32 *)data == 0) { + dev_err(mhuv2->dev, + "values in *data aligned on NUM_STAT boundaries must not be zero to ensure that receiver interrupt is triggered\n", + ch_windows); + return -EINVAL; + } + + const int bytes_in_round = bytes_left > round_capacity ? + round_capacity : + bytes_left; + + for (i = (ch_windows - 1); i >= 0; i--) { + ch_idx = ch_windows - 1 - i; + /* + * Check whether data should be transmitted in register + * of index 'ch'. + */ + if (bytes_in_round > (i * MHUV2_STAT_BYTES)) { + mhuv2_stat_reg_t word = data[i]; + + bytes_to_send = __mhuv2_mw_bytes_to_send( + bytes_in_round, bytes_left); + + if (bytes_to_send != MHUV2_STAT_BYTES) { + word &= LSB_MASK(bytes_to_send * + __CHAR_BIT__); + } + while (readl_relaxed( + &mhuv2->reg.send->channel[ch_idx] + .STAT) != 0) + continue; + + writel_relaxed( + word, + &mhuv2->reg.send->channel[ch_idx].STAT_SET); + bytes_left -= bytes_to_send; + } + } + + data += ch_windows; + + for (ch_idx = 0; ch_idx < ch_windows; ch_idx++) { + while (readl_relaxed( + &mhuv2->reg.send->channel[ch_idx].STAT) != 0) + continue; + } + } + return 0; +} + + +static inline int mhuv2_last_tx_done_multi_word(struct arm_mhuv2 *mhuv2, + struct mbox_chan *chan) +{ + int ch_idx; + bool tx_done = true; + + for (ch_idx = 0; + ch_idx < readl_relaxed_bitfield(&mhuv2->reg.send->MHU_CFG, NUM_CH); + ch_idx++) { + tx_done &= readl_relaxed( + &mhuv2->reg.send->channel[ch_idx].STAT) == 0; + } + return tx_done; +} + +static inline int mhuv2_setup_multi_word(struct arm_mhuv2 *mhuv2) +{ + int ret, i; + + const u32 channel_windows = + readl_relaxed_bitfield(mhuv2->frame == RECEIVER_FRAME ? + &mhuv2->reg.recv->MHU_CFG : + &mhuv2->reg.send->MHU_CFG, + NUM_CH); + if (channel_windows < 2) { + dev_err(mhuv2->dev, + "Error: at least 2 MHU channel windows are required for using the multi-word transfer protocol"); + return -ENODEV; + } + + if (mhuv2->frame == RECEIVER_FRAME) { + /* + * The multi-word transport protocol mandates that all but + * the last status register must be masked. + */ + for (i = 0; i < (channel_windows - 1); i++) { + writel_relaxed(-1, + &mhuv2->reg.recv->channel[i].MASK_SET); + } + } + + mhuv2->mbox.num_chans = 1; + mhuv2->mbox.chans = + devm_kzalloc(mhuv2->dev, + mhuv2->mbox.num_chans * sizeof(struct mbox_chan), + GFP_KERNEL); + + return 0; +} + +static inline struct mbox_chan * + mhuv2_get_active_mbox_chan_multi_word(struct arm_mhuv2 *mhuv2) +{ + return &mhuv2->mbox.chans[0]; +} + +static const struct mhuv2_ops mhuv2_multi_word_ops = { + .read_data = mhuv2_read_data_multi_word, + .clear_data = mhuv2_clear_data_multi_word, + .send_data = mhuv2_send_data_multi_word, + .setup = mhuv2_setup_multi_word, + .last_tx_done = mhuv2_last_tx_done_multi_word, + .get_active_mbox_chan = mhuv2_get_active_mbox_chan_multi_word, +}; +/* ========================================================================== */ + /* =================== Doorbell transport protocol operations =============== */ static inline int mhuv2_read_data_doorbell(struct arm_mhuv2 *mhuv2, @@ -740,6 +962,9 @@ static int mhuv2_probe(struct amba_device *adev, const struct amba_id *id) /* Assign transport protocol-specific operations */ switch (mhuv2->protocol) { + case MULTI_WORD: + mhuv2->ops = &mhuv2_multi_word_ops; + break; case SINGLE_WORD: mhuv2->ops = &mhuv2_single_word_ops; break;