d62bc4badc1c1f1549c961cfb8b420e650e1272byz/*
d62bc4badc1c1f1549c961cfb8b420e650e1272byz * CDDL HEADER START
d62bc4badc1c1f1549c961cfb8b420e650e1272byz *
d62bc4badc1c1f1549c961cfb8b420e650e1272byz * The contents of this file are subject to the terms of the
d62bc4badc1c1f1549c961cfb8b420e650e1272byz * Common Development and Distribution License (the "License").
d62bc4badc1c1f1549c961cfb8b420e650e1272byz * You may not use this file except in compliance with the License.
d62bc4badc1c1f1549c961cfb8b420e650e1272byz *
d62bc4badc1c1f1549c961cfb8b420e650e1272byz * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
d62bc4badc1c1f1549c961cfb8b420e650e1272byz * or http://www.opensolaris.org/os/licensing.
d62bc4badc1c1f1549c961cfb8b420e650e1272byz * See the License for the specific language governing permissions
d62bc4badc1c1f1549c961cfb8b420e650e1272byz * and limitations under the License.
d62bc4badc1c1f1549c961cfb8b420e650e1272byz *
d62bc4badc1c1f1549c961cfb8b420e650e1272byz * When distributing Covered Code, include this CDDL HEADER in each
d62bc4badc1c1f1549c961cfb8b420e650e1272byz * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
d62bc4badc1c1f1549c961cfb8b420e650e1272byz * If applicable, add the following below this CDDL HEADER, with the
d62bc4badc1c1f1549c961cfb8b420e650e1272byz * fields enclosed by brackets "[]" replaced with your own identifying
d62bc4badc1c1f1549c961cfb8b420e650e1272byz * information: Portions Copyright [yyyy] [name of copyright owner]
d62bc4badc1c1f1549c961cfb8b420e650e1272byz *
d62bc4badc1c1f1549c961cfb8b420e650e1272byz * CDDL HEADER END
d62bc4badc1c1f1549c961cfb8b420e650e1272byz */
d62bc4badc1c1f1549c961cfb8b420e650e1272byz/*
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
d62bc4badc1c1f1549c961cfb8b420e650e1272byz * Use is subject to license terms.
d62bc4badc1c1f1549c961cfb8b420e650e1272byz */
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz#include <sys/strsubr.h>
d62bc4badc1c1f1549c961cfb8b420e650e1272byz#include <inet/led.h>
d62bc4badc1c1f1549c961cfb8b420e650e1272byz#include <sys/softmac_impl.h>
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byzmblk_t *
d62bc4badc1c1f1549c961cfb8b420e650e1272byzsoftmac_m_tx(void *arg, mblk_t *mp)
d62bc4badc1c1f1549c961cfb8b420e650e1272byz{
d62bc4badc1c1f1549c961cfb8b420e650e1272byz queue_t *wq = ((softmac_t *)arg)->smac_lower->sl_wq;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz /*
d62bc4badc1c1f1549c961cfb8b420e650e1272byz * Optimize for the most common case.
d62bc4badc1c1f1549c961cfb8b420e650e1272byz */
d81b850f296ee36f8a9ecba637e8c8e2996eaaeeyz if (mp->b_next == NULL) {
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou if (!SOFTMAC_CANPUTNEXT(wq))
d62bc4badc1c1f1549c961cfb8b420e650e1272byz return (mp);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz mp->b_flag |= MSGNOLOOP;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz putnext(wq, mp);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz return (NULL);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz }
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz while (mp != NULL) {
d62bc4badc1c1f1549c961cfb8b420e650e1272byz mblk_t *next = mp->b_next;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou if (!SOFTMAC_CANPUTNEXT(wq))
d62bc4badc1c1f1549c961cfb8b420e650e1272byz break;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz mp->b_next = NULL;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz mp->b_flag |= MSGNOLOOP;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz putnext(wq, mp);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz mp = next;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz }
d62bc4badc1c1f1549c961cfb8b420e650e1272byz return (mp);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz}
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byzvoid
d62bc4badc1c1f1549c961cfb8b420e650e1272byzsoftmac_rput_process_data(softmac_lower_t *slp, mblk_t *mp)
d62bc4badc1c1f1549c961cfb8b420e650e1272byz{
d62bc4badc1c1f1549c961cfb8b420e650e1272byz /*
d62bc4badc1c1f1549c961cfb8b420e650e1272byz * When packets arrive, the softmac might not be fully started.
d62bc4badc1c1f1549c961cfb8b420e650e1272byz */
d62bc4badc1c1f1549c961cfb8b420e650e1272byz ASSERT((slp->sl_softmac != NULL));
d62bc4badc1c1f1549c961cfb8b420e650e1272byz ASSERT((mp->b_next == NULL) && (mp->b_prev == NULL));
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz if (DB_REF(mp) > 1) {
d62bc4badc1c1f1549c961cfb8b420e650e1272byz mblk_t *tmp;
10972dde7ca84b20374a9b03e1aa514b454e974bCathy Zhou uint32_t start, stuff, end, value, flags;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz if ((tmp = copymsg(mp)) == NULL) {
d62bc4badc1c1f1549c961cfb8b420e650e1272byz cmn_err(CE_WARN, "softmac_rput_process_data: "
d62bc4badc1c1f1549c961cfb8b420e650e1272byz "copymsg failed");
d62bc4badc1c1f1549c961cfb8b420e650e1272byz goto failed;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz }
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer mac_hcksum_get(mp, &start, &stuff, &end, &value, &flags);
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer mac_hcksum_set(tmp, start, stuff, end, value, flags);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz freemsg(mp);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz mp = tmp;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz }
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng mac_rx(slp->sl_softmac->smac_mh, NULL, mp);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz return;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byzfailed:
d62bc4badc1c1f1549c961cfb8b420e650e1272byz freemsg(mp);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz}
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz#define ACKTIMEOUT (10 * hz)
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byzstatic int
d62bc4badc1c1f1549c961cfb8b420e650e1272byzdlpi_get_errno(t_uscalar_t error, t_uscalar_t unix_errno)
d62bc4badc1c1f1549c961cfb8b420e650e1272byz{
d62bc4badc1c1f1549c961cfb8b420e650e1272byz return (error == DL_SYSERR ? unix_errno : EINVAL);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz}
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhouint
d62bc4badc1c1f1549c961cfb8b420e650e1272byzsoftmac_output(softmac_lower_t *slp, mblk_t *mp, t_uscalar_t dl_prim,
d62bc4badc1c1f1549c961cfb8b420e650e1272byz t_uscalar_t ack, mblk_t **mpp)
d62bc4badc1c1f1549c961cfb8b420e650e1272byz{
d62bc4badc1c1f1549c961cfb8b420e650e1272byz union DL_primitives *dlp;
f1956ffef55a0f859d3974677c90c728e3fc32f5Cathy Zhou mac_perim_handle_t mph;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz int err = 0;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
f1956ffef55a0f859d3974677c90c728e3fc32f5Cathy Zhou mac_perim_enter_by_mh(slp->sl_softmac->smac_mh, &mph);
f1956ffef55a0f859d3974677c90c728e3fc32f5Cathy Zhou
f1956ffef55a0f859d3974677c90c728e3fc32f5Cathy Zhou ASSERT(!slp->sl_pending_ioctl);
f1956ffef55a0f859d3974677c90c728e3fc32f5Cathy Zhou ASSERT(slp->sl_pending_prim == DL_PRIM_INVAL);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz /*
d62bc4badc1c1f1549c961cfb8b420e650e1272byz * Record the pending DLPI primitive.
d62bc4badc1c1f1549c961cfb8b420e650e1272byz */
d62bc4badc1c1f1549c961cfb8b420e650e1272byz mutex_enter(&slp->sl_mutex);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz slp->sl_pending_prim = dl_prim;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz mutex_exit(&slp->sl_mutex);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz putnext(slp->sl_wq, mp);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz mutex_enter(&slp->sl_mutex);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz while (slp->sl_pending_prim != DL_PRIM_INVAL) {
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni if (cv_reltimedwait(&slp->sl_cv, &slp->sl_mutex, ACKTIMEOUT,
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni TR_CLOCK_TICK) == -1)
d62bc4badc1c1f1549c961cfb8b420e650e1272byz break;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz }
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz mp = slp->sl_ack_mp;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz slp->sl_ack_mp = NULL;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz /*
d62bc4badc1c1f1549c961cfb8b420e650e1272byz * If we timed out, sl_ack_mp will still be NULL, but sl_pending_prim
d62bc4badc1c1f1549c961cfb8b420e650e1272byz * won't be set to DL_PRIM_INVAL.
d62bc4badc1c1f1549c961cfb8b420e650e1272byz */
d62bc4badc1c1f1549c961cfb8b420e650e1272byz ASSERT(mp != NULL || slp->sl_pending_prim != DL_PRIM_INVAL);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz slp->sl_pending_prim = DL_PRIM_INVAL;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz mutex_exit(&slp->sl_mutex);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz if (mp != NULL) {
d62bc4badc1c1f1549c961cfb8b420e650e1272byz dlp = (union DL_primitives *)mp->b_rptr;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz if (dlp->dl_primitive == DL_ERROR_ACK) {
d62bc4badc1c1f1549c961cfb8b420e650e1272byz err = dlpi_get_errno(dlp->error_ack.dl_errno,
d62bc4badc1c1f1549c961cfb8b420e650e1272byz dlp->error_ack.dl_unix_errno);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz } else {
d62bc4badc1c1f1549c961cfb8b420e650e1272byz ASSERT(dlp->dl_primitive == ack);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz }
d62bc4badc1c1f1549c961cfb8b420e650e1272byz } else {
d62bc4badc1c1f1549c961cfb8b420e650e1272byz err = ENOMSG;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz }
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz if (mpp != NULL)
d62bc4badc1c1f1549c961cfb8b420e650e1272byz *mpp = mp;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz else
d62bc4badc1c1f1549c961cfb8b420e650e1272byz freemsg(mp);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
f1956ffef55a0f859d3974677c90c728e3fc32f5Cathy Zhou mac_perim_exit(mph);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz return (err);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz}
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byzvoid
d62bc4badc1c1f1549c961cfb8b420e650e1272byzsoftmac_ioctl_tx(softmac_lower_t *slp, mblk_t *mp, mblk_t **mpp)
d62bc4badc1c1f1549c961cfb8b420e650e1272byz{
f1956ffef55a0f859d3974677c90c728e3fc32f5Cathy Zhou mac_perim_handle_t mph;
f1956ffef55a0f859d3974677c90c728e3fc32f5Cathy Zhou
f1956ffef55a0f859d3974677c90c728e3fc32f5Cathy Zhou mac_perim_enter_by_mh(slp->sl_softmac->smac_mh, &mph);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz /*
d62bc4badc1c1f1549c961cfb8b420e650e1272byz * Record that ioctl processing is currently in progress.
d62bc4badc1c1f1549c961cfb8b420e650e1272byz */
d62bc4badc1c1f1549c961cfb8b420e650e1272byz mutex_enter(&slp->sl_mutex);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz slp->sl_pending_ioctl = B_TRUE;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz mutex_exit(&slp->sl_mutex);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz putnext(slp->sl_wq, mp);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz mutex_enter(&slp->sl_mutex);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz while (slp->sl_pending_ioctl)
d62bc4badc1c1f1549c961cfb8b420e650e1272byz cv_wait(&slp->sl_cv, &slp->sl_mutex);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz mp = slp->sl_ack_mp;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz slp->sl_ack_mp = NULL;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz mutex_exit(&slp->sl_mutex);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz ASSERT(mpp != NULL && mp != NULL);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz *mpp = mp;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
f1956ffef55a0f859d3974677c90c728e3fc32f5Cathy Zhou mac_perim_exit(mph);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz}
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhouint
d62bc4badc1c1f1549c961cfb8b420e650e1272byzsoftmac_mexchange_error_ack(mblk_t **mpp, t_uscalar_t error_primitive,
d62bc4badc1c1f1549c961cfb8b420e650e1272byz t_uscalar_t error, t_uscalar_t unix_errno)
d62bc4badc1c1f1549c961cfb8b420e650e1272byz{
d62bc4badc1c1f1549c961cfb8b420e650e1272byz union DL_primitives *dlp;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz if ((*mpp = mexchange(NULL, *mpp, sizeof (dl_error_ack_t), M_PCPROTO,
d62bc4badc1c1f1549c961cfb8b420e650e1272byz DL_ERROR_ACK)) == NULL)
d62bc4badc1c1f1549c961cfb8b420e650e1272byz return (ENOMEM);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz dlp = (union DL_primitives *)(*mpp)->b_rptr;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz dlp->error_ack.dl_error_primitive = error_primitive;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz dlp->error_ack.dl_errno = error;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz dlp->error_ack.dl_unix_errno = unix_errno;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz return (0);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz}
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byzint
d62bc4badc1c1f1549c961cfb8b420e650e1272byzsoftmac_proto_tx(softmac_lower_t *slp, mblk_t *mp, mblk_t **mpp)
d62bc4badc1c1f1549c961cfb8b420e650e1272byz{
d62bc4badc1c1f1549c961cfb8b420e650e1272byz int err = 0;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz t_uscalar_t dl_prim;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz dl_prim = ((union DL_primitives *)mp->b_rptr)->dl_primitive;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz ASSERT(slp->sl_softmac != NULL);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz switch (dl_prim) {
d62bc4badc1c1f1549c961cfb8b420e650e1272byz case DL_ENABMULTI_REQ:
d62bc4badc1c1f1549c961cfb8b420e650e1272byz case DL_DISABMULTI_REQ:
d62bc4badc1c1f1549c961cfb8b420e650e1272byz case DL_SET_PHYS_ADDR_REQ:
d62bc4badc1c1f1549c961cfb8b420e650e1272byz case DL_UNBIND_REQ:
d62bc4badc1c1f1549c961cfb8b420e650e1272byz case DL_UDQOS_REQ:
d62bc4badc1c1f1549c961cfb8b420e650e1272byz case DL_PROMISCON_REQ:
d62bc4badc1c1f1549c961cfb8b420e650e1272byz case DL_PROMISCOFF_REQ:
d62bc4badc1c1f1549c961cfb8b420e650e1272byz err = softmac_output(slp, mp, dl_prim, DL_OK_ACK, mpp);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz break;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz case DL_BIND_REQ:
d62bc4badc1c1f1549c961cfb8b420e650e1272byz err = softmac_output(slp, mp, dl_prim, DL_BIND_ACK, mpp);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz break;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz case DL_NOTIFY_REQ:
d62bc4badc1c1f1549c961cfb8b420e650e1272byz err = softmac_output(slp, mp, dl_prim, DL_NOTIFY_ACK, mpp);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz break;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz case DL_CONTROL_REQ:
d62bc4badc1c1f1549c961cfb8b420e650e1272byz err = softmac_output(slp, mp, dl_prim, DL_CONTROL_ACK, mpp);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz break;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz case DL_CAPABILITY_REQ:
d62bc4badc1c1f1549c961cfb8b420e650e1272byz err = softmac_output(slp, mp, dl_prim, DL_CAPABILITY_ACK, mpp);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz break;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz default:
d62bc4badc1c1f1549c961cfb8b420e650e1272byz if (mpp != NULL) {
d62bc4badc1c1f1549c961cfb8b420e650e1272byz *mpp = mp;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz err = softmac_mexchange_error_ack(mpp, dl_prim,
d62bc4badc1c1f1549c961cfb8b420e650e1272byz DL_UNSUPPORTED, 0);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz }
d62bc4badc1c1f1549c961cfb8b420e650e1272byz break;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz }
d62bc4badc1c1f1549c961cfb8b420e650e1272byz return (err);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz}