storeEntityValue(XML_Parser parser, const ENCODING *enc,
                 const char *entityTextPtr, const char *entityTextEnd,
                 enum XML_Account account) {
  DTD *const dtd = parser->m_dtd; /* save one level of indirection */
  STRING_POOL *pool = &(dtd->entityValuePool);
  enum XML_Error result = XML_ERROR_NONE;
#ifdef XML_DTD
  int oldInEntityValue = parser->m_prologState.inEntityValue;
  parser->m_prologState.inEntityValue = 1;
#else
  UNUSED_P(account);
#endif /* XML_DTD */
  /* never return Null for the value argument in EntityDeclHandler,
     since this would indicate an external entity; therefore we
     have to make sure that entityValuePool.start is not null */
  if (! pool->blocks) {
    if (! poolGrow(pool))
      return XML_ERROR_NO_MEMORY;
  }

  for (;;) {
    const char *next
        = entityTextPtr; /* XmlEntityValueTok doesn't always set the last arg */
    int tok = XmlEntityValueTok(enc, entityTextPtr, entityTextEnd, &next);

#ifdef XML_DTD
    if (! accountingDiffTolerated(parser, tok, entityTextPtr, next, __LINE__,
                                  account)) {
      accountingOnAbort(parser);
      result = XML_ERROR_AMPLIFICATION_LIMIT_BREACH;
      goto endEntityValue;
    }
#endif

    switch (tok) {
    case XML_TOK_PARAM_ENTITY_REF:
#ifdef XML_DTD
      if (parser->m_isParamEntity || enc != parser->m_encoding) {
        const XML_Char *name;
        ENTITY *entity;
        name = poolStoreString(&parser->m_tempPool, enc,
                               entityTextPtr + enc->minBytesPerChar,
                               next - enc->minBytesPerChar);
        if (! name) {
          result = XML_ERROR_NO_MEMORY;
          goto endEntityValue;
        }
        entity = (ENTITY *)lookup(parser, &dtd->paramEntities, name, 0);
        poolDiscard(&parser->m_tempPool);
        if (! entity) {
          /* not a well-formedness error - see XML 1.0: WFC Entity Declared */
          /* cannot report skipped entity here - see comments on
             parser->m_skippedEntityHandler
          if (parser->m_skippedEntityHandler)
            parser->m_skippedEntityHandler(parser->m_handlerArg, name, 0);
          */
          dtd->keepProcessing = dtd->standalone;
          goto endEntityValue;
        }
        if (entity->open) {
          if (enc == parser->m_encoding)
            parser->m_eventPtr = entityTextPtr;
          result = XML_ERROR_RECURSIVE_ENTITY_REF;
          goto endEntityValue;
        }
        if (entity->systemId) {
          if (parser->m_externalEntityRefHandler) {
            dtd->paramEntityRead = XML_FALSE;
            entity->open = XML_TRUE;
            entityTrackingOnOpen(parser, entity, __LINE__);
            if (! parser->m_externalEntityRefHandler(
                    parser->m_externalEntityRefHandlerArg, 0, entity->base,
                    entity->systemId, entity->publicId)) {
              entityTrackingOnClose(parser, entity, __LINE__);
              entity->open = XML_FALSE;
              result = XML_ERROR_EXTERNAL_ENTITY_HANDLING;
              goto endEntityValue;
            }
            entityTrackingOnClose(parser, entity, __LINE__);
            entity->open = XML_FALSE;
            if (! dtd->paramEntityRead)
              dtd->keepProcessing = dtd->standalone;
          } else
            dtd->keepProcessing = dtd->standalone;
        } else {
          entity->open = XML_TRUE;
          entityTrackingOnOpen(parser, entity, __LINE__);
          result = storeEntityValue(
              parser, parser->m_internalEncoding, (const char *)entity->textPtr,
              (const char *)(entity->textPtr + entity->textLen),
              XML_ACCOUNT_ENTITY_EXPANSION);
          entityTrackingOnClose(parser, entity, __LINE__);
          entity->open = XML_FALSE;
          if (result)
            goto endEntityValue;
        }
        break;
      }
#endif /* XML_DTD */
      /* In the internal subset, PE references are not legal
         within markup declarations, e.g entity values in this case. */
      parser->m_eventPtr = entityTextPtr;
      result = XML_ERROR_PARAM_ENTITY_REF;
      goto endEntityValue;
    case XML_TOK_NONE:
      result = XML_ERROR_NONE;
      goto endEntityValue;
    case XML_TOK_ENTITY_REF:
    case XML_TOK_DATA_CHARS:
      if (! poolAppend(pool, enc, entityTextPtr, next)) {
        result = XML_ERROR_NO_MEMORY;
        goto endEntityValue;
      }
      break;
    case XML_TOK_TRAILING_CR:
      next = entityTextPtr + enc->minBytesPerChar;
      /* fall through */
    case XML_TOK_DATA_NEWLINE:
      if (pool->end == pool->ptr && ! poolGrow(pool)) {
        result = XML_ERROR_NO_MEMORY;
        goto endEntityValue;
      }
      *(pool->ptr)++ = 0xA;
      break;
    case XML_TOK_CHAR_REF: {
      XML_Char buf[XML_ENCODE_MAX];
      int i;
      int n = XmlCharRefNumber(enc, entityTextPtr);
      if (n < 0) {
        if (enc == parser->m_encoding)
          parser->m_eventPtr = entityTextPtr;
        result = XML_ERROR_BAD_CHAR_REF;
        goto endEntityValue;
      }
      n = XmlEncode(n, (ICHAR *)buf);
      /* The XmlEncode() functions can never return 0 here.  That
       * error return happens if the code point passed in is either
       * negative or greater than or equal to 0x110000.  The
       * XmlCharRefNumber() functions will all return a number
       * strictly less than 0x110000 or a negative value if an error
       * occurred.  The negative value is intercepted above, so
       * XmlEncode() is never passed a value it might return an
       * error for.
       */
      for (i = 0; i < n; i++) {
        if (pool->end == pool->ptr && ! poolGrow(pool)) {
          result = XML_ERROR_NO_MEMORY;
          goto endEntityValue;
        }
        *(pool->ptr)++ = buf[i];
      }
    } break;
    case XML_TOK_PARTIAL:
      if (enc == parser->m_encoding)
        parser->m_eventPtr = entityTextPtr;
      result = XML_ERROR_INVALID_TOKEN;
      goto endEntityValue;
    case XML_TOK_INVALID:
      if (enc == parser->m_encoding)
        parser->m_eventPtr = next;
      result = XML_ERROR_INVALID_TOKEN;
      goto endEntityValue;
    default:
      /* This default case should be unnecessary -- all the tokens
       * that XmlEntityValueTok() can return have their own explicit
       * cases -- but should be retained for safety.  We do however
       * exclude it from the coverage statistics.
       *
       * LCOV_EXCL_START
       */
      if (enc == parser->m_encoding)
        parser->m_eventPtr = entityTextPtr;
      result = XML_ERROR_UNEXPECTED_STATE;
      goto endEntityValue;
      /* LCOV_EXCL_STOP */
    }
    entityTextPtr = next;
  }
endEntityValue:
#ifdef XML_DTD
  parser->m_prologState.inEntityValue = oldInEntityValue;
#endif /* XML_DTD */
  return result;
}


internalEntityProcessor(XML_Parser parser, const char *s, const char *end,
                        const char **nextPtr) {
  ENTITY *entity;
  const char *textStart, *textEnd;
  const char *next;
  enum XML_Error result;
  OPEN_INTERNAL_ENTITY *openEntity = parser->m_openInternalEntities;
  if (! openEntity)
    return XML_ERROR_UNEXPECTED_STATE;

  entity = openEntity->entity;
  textStart = ((const char *)entity->textPtr) + entity->processed;
  textEnd = (const char *)(entity->textPtr + entity->textLen);
  /* Set a safe default value in case 'next' does not get set */
  next = textStart;

#ifdef XML_DTD
  if (entity->is_param) {
    int tok
        = XmlPrologTok(parser->m_internalEncoding, textStart, textEnd, &next);
    result = doProlog(parser, parser->m_internalEncoding, textStart, textEnd,
                      tok, next, &next, XML_FALSE, XML_TRUE,
                      XML_ACCOUNT_ENTITY_EXPANSION);
  } else
#endif /* XML_DTD */
    result = doContent(parser, openEntity->startTagLevel,
                       parser->m_internalEncoding, textStart, textEnd, &next,
                       XML_FALSE, XML_ACCOUNT_ENTITY_EXPANSION);

  if (result != XML_ERROR_NONE)
    return result;
  else if (textEnd != next
           && parser->m_parsingStatus.parsing == XML_SUSPENDED) {
    entity->processed = (int)(next - (const char *)entity->textPtr);
    return result;
  } else {
#ifdef XML_DTD
    entityTrackingOnClose(parser, entity, __LINE__);
#endif
    entity->open = XML_FALSE;
    parser->m_openInternalEntities = openEntity->next;
    /* put openEntity back in list of free instances */
    openEntity->next = parser->m_freeInternalEntities;
    parser->m_freeInternalEntities = openEntity;
  }

#ifdef XML_DTD
  if (entity->is_param) {
    int tok;
    parser->m_processor = prologProcessor;
    tok = XmlPrologTok(parser->m_encoding, s, end, &next);
    return doProlog(parser, parser->m_encoding, s, end, tok, next, nextPtr,
                    (XML_Bool)! parser->m_parsingStatus.finalBuffer, XML_TRUE,
                    XML_ACCOUNT_DIRECT);
  } else
#endif /* XML_DTD */
  {
    parser->m_processor = contentProcessor;
    /* see externalEntityContentProcessor vs contentProcessor */
    return doContent(parser, parser->m_parentParser ? 1 : 0, parser->m_encoding,
                     s, end, nextPtr,
                     (XML_Bool)! parser->m_parsingStatus.finalBuffer,
                     XML_ACCOUNT_DIRECT);
  }
}


storeAttributeValue(XML_Parser parser, const ENCODING *enc, XML_Bool isCdata,
                    const char *ptr, const char *end, STRING_POOL *pool,
                    enum XML_Account account) {
  enum XML_Error result
      = appendAttributeValue(parser, enc, isCdata, ptr, end, pool, account);
  if (result)
    return result;
  if (! isCdata && poolLength(pool) && poolLastChar(pool) == 0x20)
    poolChop(pool);
  if (! poolAppendChar(pool, XML_T('\0')))
    return XML_ERROR_NO_MEMORY;
  return XML_ERROR_NONE;
}


copyString(const XML_Char *s, const XML_Memory_Handling_Suite *memsuite) {
  size_t charsRequired = 0;
  XML_Char *result;

  /* First determine how long the string is */
  while (s[charsRequired] != 0) {
    charsRequired++;
  }
  /* Include the terminator */
  charsRequired++;

  /* Now allocate space for the copy */
  result = memsuite->malloc_fcn(charsRequired * sizeof(XML_Char));
  if (result == NULL)
    return NULL;
  /* Copy the original into place */
  memcpy(result, s, charsRequired * sizeof(XML_Char));
  return result;
}


storeRawNames(XML_Parser parser) {
  TAG *tag = parser->m_tagStack;
  while (tag) {
    int bufSize;
    int nameLen = sizeof(XML_Char) * (tag->name.strLen + 1);
    size_t rawNameLen;
    char *rawNameBuf = tag->buf + nameLen;
    /* Stop if already stored.  Since m_tagStack is a stack, we can stop
       at the first entry that has already been copied; everything
       below it in the stack is already been accounted for in a
       previous call to this function.
    */
    if (tag->rawName == rawNameBuf)
      break;
    /* For re-use purposes we need to ensure that the
       size of tag->buf is a multiple of sizeof(XML_Char).
    */
    rawNameLen = ROUND_UP(tag->rawNameLength, sizeof(XML_Char));
    /* Detect and prevent integer overflow. */
    if (rawNameLen > (size_t)INT_MAX - nameLen)
      return XML_FALSE;
    bufSize = nameLen + (int)rawNameLen;
    if (bufSize > tag->bufEnd - tag->buf) {
      char *temp = (char *)REALLOC(parser, tag->buf, bufSize);
      if (temp == NULL)
        return XML_FALSE;
      /* if tag->name.str points to tag->buf (only when namespace
         processing is off) then we have to update it
      */
      if (tag->name.str == (XML_Char *)tag->buf)
        tag->name.str = (XML_Char *)temp;
      /* if tag->name.localPart is set (when namespace processing is on)
         then update it as well, since it will always point into tag->buf
      */
      if (tag->name.localPart)
        tag->name.localPart
            = (XML_Char *)temp + (tag->name.localPart - (XML_Char *)tag->buf);
      tag->buf = temp;
      tag->bufEnd = temp + bufSize;
      rawNameBuf = temp + nameLen;
    }
    memcpy(rawNameBuf, tag->rawName, tag->rawNameLength);
    tag->rawName = rawNameBuf;
    tag = tag->parent;
  }
  return XML_TRUE;
}


PREFIX(scanDecl)(const ENCODING *enc, const char *ptr, const char *end,
                 const char **nextTokPtr) {
  REQUIRE_CHAR(enc, ptr, end);
  switch (BYTE_TYPE(enc, ptr)) {
  case BT_MINUS:
    return PREFIX(scanComment)(enc, ptr + MINBPC(enc), end, nextTokPtr);
  case BT_LSQB:
    *nextTokPtr = ptr + MINBPC(enc);
    return XML_TOK_COND_SECT_OPEN;
  case BT_NMSTRT:
  case BT_HEX:
    ptr += MINBPC(enc);
    break;
  default:
    *nextTokPtr = ptr;
    return XML_TOK_INVALID;
  }
  while (HAS_CHAR(enc, ptr, end)) {
    switch (BYTE_TYPE(enc, ptr)) {
    case BT_PERCNT:
      REQUIRE_CHARS(enc, ptr, end, 2);
      /* don't allow <!ENTITY% foo "whatever"> */
      switch (BYTE_TYPE(enc, ptr + MINBPC(enc))) {
      case BT_S:
      case BT_CR:
      case BT_LF:
      case BT_PERCNT:
        *nextTokPtr = ptr;
        return XML_TOK_INVALID;
      }
      /* fall through */
    case BT_S:
    case BT_CR:
    case BT_LF:
      *nextTokPtr = ptr;
      return XML_TOK_DECL_OPEN;
    case BT_NMSTRT:
    case BT_HEX:
      ptr += MINBPC(enc);
      break;
    default:
      *nextTokPtr = ptr;
      return XML_TOK_INVALID;
    }
  }
  return XML_TOK_PARTIAL;
}


PREFIX(scanComment)(const ENCODING *enc, const char *ptr, const char *end,
                    const char **nextTokPtr) {
  if (HAS_CHAR(enc, ptr, end)) {
    if (! CHAR_MATCHES(enc, ptr, ASCII_MINUS)) {
      *nextTokPtr = ptr;
      return XML_TOK_INVALID;
    }
    ptr += MINBPC(enc);
    while (HAS_CHAR(enc, ptr, end)) {
      switch (BYTE_TYPE(enc, ptr)) {
        INVALID_CASES(ptr, nextTokPtr)
      case BT_MINUS:
        ptr += MINBPC(enc);
        REQUIRE_CHAR(enc, ptr, end);
        if (CHAR_MATCHES(enc, ptr, ASCII_MINUS)) {
          ptr += MINBPC(enc);
          REQUIRE_CHAR(enc, ptr, end);
          if (! CHAR_MATCHES(enc, ptr, ASCII_GT)) {
            *nextTokPtr = ptr;
            return XML_TOK_INVALID;
          }
          *nextTokPtr = ptr + MINBPC(enc);
          return XML_TOK_COMMENT;
        }
        break;
      default:
        ptr += MINBPC(enc);
        break;
      }
    }
  }
  return XML_TOK_PARTIAL;
}


XML_ParserCreateNS(const XML_Char *encodingName, XML_Char nsSep) {
  XML_Char tmp[2] = {nsSep, 0};
  return XML_ParserCreate_MM(encodingName, NULL, tmp);
}


static void mkiss_close(struct tty_struct *tty)
{
	struct mkiss *ax;

	write_lock_irq(&disc_data_lock);
	ax = tty->disc_data;
	tty->disc_data = NULL;
	write_unlock_irq(&disc_data_lock);

	if (!ax)
		return;

	/*
	 * We have now ensured that nobody can start using ap from now on, but
	 * we have to wait for all existing users to finish.
	 */
	if (!refcount_dec_and_test(&ax->refcnt))
		wait_for_completion(&ax->dead);
	/*
	 * Halt the transmit queue so that a new transmit cannot scribble
	 * on our buffers
	 */
	netif_stop_queue(ax->dev);

	unregister_netdev(ax->dev);

	/* Free all AX25 frame buffers after unreg. */
	kfree(ax->rbuff);
	kfree(ax->xbuff);

	ax->tty = NULL;

	free_netdev(ax->dev);
}


static int mkiss_ioctl(struct tty_struct *tty, struct file *file,
	unsigned int cmd, unsigned long arg)
{
	struct mkiss *ax = mkiss_get(tty);
	struct net_device *dev;
	unsigned int tmp, err;

	/* First make sure we're connected. */
	if (ax == NULL)
		return -ENXIO;
	dev = ax->dev;

	switch (cmd) {
	case SIOCGIFNAME:
		err = copy_to_user((void __user *) arg, ax->dev->name,
		                   strlen(ax->dev->name) + 1) ? -EFAULT : 0;
		break;

	case SIOCGIFENCAP:
		err = put_user(4, (int __user *) arg);
		break;

	case SIOCSIFENCAP:
		if (get_user(tmp, (int __user *) arg)) {
			err = -EFAULT;
			break;
		}

		ax->mode = tmp;
		dev->addr_len        = AX25_ADDR_LEN;
		dev->hard_header_len = AX25_KISS_HEADER_LEN +
		                       AX25_MAX_HEADER_LEN + 3;
		dev->type            = ARPHRD_AX25;

		err = 0;
		break;

	case SIOCSIFHWADDR: {
		char addr[AX25_ADDR_LEN];

		if (copy_from_user(&addr,
		                   (void __user *) arg, AX25_ADDR_LEN)) {
			err = -EFAULT;
			break;
		}

		netif_tx_lock_bh(dev);
		__dev_addr_set(dev, addr, AX25_ADDR_LEN);
		netif_tx_unlock_bh(dev);

		err = 0;
		break;
	}
	default:
		err = -ENOIOCTLCMD;
	}

	mkiss_put(ax);

	return err;
}


static void __exit nft_fwd_netdev_module_exit(void)
{
	nft_unregister_expr(&nft_fwd_netdev_type);
}


static void __exit nft_dup_netdev_module_exit(void)
{
	nft_unregister_expr(&nft_dup_netdev_type);
}


static void nft_flow_rule_transfer_vlan(struct nft_offload_ctx *ctx,
					struct nft_flow_rule *flow)
{
	struct nft_flow_match *match = &flow->match;
	struct nft_offload_ethertype ethertype = {
		.value	= match->key.basic.n_proto,
		.mask	= match->mask.basic.n_proto,
	};

	if (match->dissector.used_keys & BIT(FLOW_DISSECTOR_KEY_VLAN) &&
	    (match->key.vlan.vlan_tpid == htons(ETH_P_8021Q) ||
	     match->key.vlan.vlan_tpid == htons(ETH_P_8021AD))) {
		match->key.basic.n_proto = match->key.cvlan.vlan_tpid;
		match->mask.basic.n_proto = match->mask.cvlan.vlan_tpid;
		match->key.cvlan.vlan_tpid = match->key.vlan.vlan_tpid;
		match->mask.cvlan.vlan_tpid = match->mask.vlan.vlan_tpid;
		match->key.vlan.vlan_tpid = ethertype.value;
		match->mask.vlan.vlan_tpid = ethertype.mask;
		match->dissector.offset[FLOW_DISSECTOR_KEY_CVLAN] =
			offsetof(struct nft_flow_key, cvlan);
		match->dissector.used_keys |= BIT(FLOW_DISSECTOR_KEY_CVLAN);
	} else if (match->dissector.used_keys & BIT(FLOW_DISSECTOR_KEY_BASIC) &&
		   (match->key.basic.n_proto == htons(ETH_P_8021Q) ||
		    match->key.basic.n_proto == htons(ETH_P_8021AD))) {
		match->key.basic.n_proto = match->key.vlan.vlan_tpid;
		match->mask.basic.n_proto = match->mask.vlan.vlan_tpid;
		match->key.vlan.vlan_tpid = ethertype.value;
		match->mask.vlan.vlan_tpid = ethertype.mask;
		match->dissector.offset[FLOW_DISSECTOR_KEY_VLAN] =
			offsetof(struct nft_flow_key, vlan);
		match->dissector.used_keys |= BIT(FLOW_DISSECTOR_KEY_VLAN);
	}
}


void nft_flow_rule_set_addr_type(struct nft_flow_rule *flow,
				 enum flow_dissector_key_id addr_type)
{
	struct nft_flow_match *match = &flow->match;
	struct nft_flow_key *mask = &match->mask;
	struct nft_flow_key *key = &match->key;

	if (match->dissector.used_keys & BIT(FLOW_DISSECTOR_KEY_CONTROL))
		return;

	key->control.addr_type = addr_type;
	mask->control.addr_type = 0xffff;
	match->dissector.used_keys |= BIT(FLOW_DISSECTOR_KEY_CONTROL);
	match->dissector.offset[FLOW_DISSECTOR_KEY_CONTROL] =
		offsetof(struct nft_flow_key, control);
}


int nft_chain_offload_priority(struct nft_base_chain *basechain)
{
	if (basechain->ops.priority <= 0 ||
	    basechain->ops.priority > USHRT_MAX)
		return -1;

	return 0;
}


static void nft_flow_rule_offload_abort(struct net *net,
					struct nft_trans *trans)
{
	struct nftables_pernet *nft_net = nft_pernet(net);
	int err = 0;

	list_for_each_entry_continue_reverse(trans, &nft_net->commit_list, list) {
		if (trans->ctx.family != NFPROTO_NETDEV)
			continue;

		switch (trans->msg_type) {
		case NFT_MSG_NEWCHAIN:
			if (!(trans->ctx.chain->flags & NFT_CHAIN_HW_OFFLOAD) ||
			    nft_trans_chain_update(trans))
				continue;

			err = nft_flow_offload_chain(trans->ctx.chain, NULL,
						     FLOW_BLOCK_UNBIND);
			break;
		case NFT_MSG_DELCHAIN:
			if (!(trans->ctx.chain->flags & NFT_CHAIN_HW_OFFLOAD))
				continue;

			err = nft_flow_offload_chain(trans->ctx.chain, NULL,
						     FLOW_BLOCK_BIND);
			break;
		case NFT_MSG_NEWRULE:
			if (!(trans->ctx.chain->flags & NFT_CHAIN_HW_OFFLOAD))
				continue;

			err = nft_flow_offload_rule(trans->ctx.chain,
						    nft_trans_rule(trans),
						    NULL, FLOW_CLS_DESTROY);
			break;
		case NFT_MSG_DELRULE:
			if (!(trans->ctx.chain->flags & NFT_CHAIN_HW_OFFLOAD))
				continue;

			err = nft_flow_offload_rule(trans->ctx.chain,
						    nft_trans_rule(trans),
						    nft_trans_flow_rule(trans),
						    FLOW_CLS_REPLACE);
			break;
		}

		if (WARN_ON_ONCE(err))
			break;
	}
}


static int nft_flow_offload_cmd(const struct nft_chain *chain,
				const struct nft_rule *rule,
				struct nft_flow_rule *flow,
				enum flow_cls_command command,
				struct flow_cls_offload *cls_flow)
{
	struct netlink_ext_ack extack = {};
	struct nft_base_chain *basechain;

	if (!nft_is_base_chain(chain))
		return -EOPNOTSUPP;

	basechain = nft_base_chain(chain);
	nft_flow_cls_offload_setup(cls_flow, basechain, rule, flow, &extack,
				   command);

	return nft_setup_cb_call(TC_SETUP_CLSFLOWER, cls_flow,
				 &basechain->flow_block.cb_list);
}


static int nft_flow_offload_unbind(struct flow_block_offload *bo,
				   struct nft_base_chain *basechain)
{
	struct flow_block_cb *block_cb, *next;
	struct flow_cls_offload cls_flow;
	struct netlink_ext_ack extack;
	struct nft_chain *chain;
	struct nft_rule *rule;

	chain = &basechain->chain;
	list_for_each_entry(rule, &chain->rules, list) {
		memset(&extack, 0, sizeof(extack));
		nft_flow_cls_offload_setup(&cls_flow, basechain, rule, NULL,
					   &extack, FLOW_CLS_DESTROY);
		nft_setup_cb_call(TC_SETUP_CLSFLOWER, &cls_flow, &bo->cb_list);
	}

	list_for_each_entry_safe(block_cb, next, &bo->cb_list, list) {
		list_del(&block_cb->list);
		flow_block_cb_free(block_cb);
	}

	return 0;
}


uint32_t evaluate_fixed_subframe_(
	FLAC__StreamEncoder *encoder,
	const FLAC__int32 signal[],
	FLAC__int32 residual[],
	FLAC__uint64 abs_residual_partition_sums[],
	uint32_t raw_bits_per_partition[],
	uint32_t blocksize,
	uint32_t subframe_bps,
	uint32_t order,
	uint32_t rice_parameter,
	uint32_t rice_parameter_limit,
	uint32_t min_partition_order,
	uint32_t max_partition_order,
	FLAC__bool do_escape_coding,
	uint32_t rice_parameter_search_dist,
	FLAC__Subframe *subframe,
	FLAC__EntropyCodingMethod_PartitionedRiceContents *partitioned_rice_contents
)
{
	uint32_t i, residual_bits, estimate;
	const uint32_t residual_samples = blocksize - order;

	FLAC__fixed_compute_residual(signal+order, residual_samples, order, residual);

	subframe->type = FLAC__SUBFRAME_TYPE_FIXED;

	subframe->data.fixed.entropy_coding_method.type = FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE;
	subframe->data.fixed.entropy_coding_method.data.partitioned_rice.contents = partitioned_rice_contents;
	subframe->data.fixed.residual = residual;

	residual_bits =
		find_best_partition_order_(
			encoder->private_,
			residual,
			abs_residual_partition_sums,
			raw_bits_per_partition,
			residual_samples,
			order,
			rice_parameter,
			rice_parameter_limit,
			min_partition_order,
			max_partition_order,
			subframe_bps,
			do_escape_coding,
			rice_parameter_search_dist,
			&subframe->data.fixed.entropy_coding_method
		);

	subframe->data.fixed.order = order;
	for(i = 0; i < order; i++)
		subframe->data.fixed.warmup[i] = signal[i];

	estimate = FLAC__SUBFRAME_ZERO_PAD_LEN + FLAC__SUBFRAME_TYPE_LEN + FLAC__SUBFRAME_WASTED_BITS_FLAG_LEN + subframe->wasted_bits + (order * subframe_bps) + residual_bits;

#if SPOTCHECK_ESTIMATE
	spotcheck_subframe_estimate_(encoder, blocksize, subframe_bps, subframe, estimate);
#endif

	return estimate;
}


void precompute_partition_info_sums_(
	const FLAC__int32 residual[],
	FLAC__uint64 abs_residual_partition_sums[],
	uint32_t residual_samples,
	uint32_t predictor_order,
	uint32_t min_partition_order,
	uint32_t max_partition_order,
	uint32_t bps
)
{
	const uint32_t default_partition_samples = (residual_samples + predictor_order) >> max_partition_order;
	uint32_t partitions = 1u << max_partition_order;

	FLAC__ASSERT(default_partition_samples > predictor_order);

	/* first do max_partition_order */
	{
		const uint32_t threshold = 32 - FLAC__bitmath_ilog2(default_partition_samples);
		uint32_t partition, residual_sample, end = (uint32_t)(-(int)predictor_order);
		/* WATCHOUT: "bps + FLAC__MAX_EXTRA_RESIDUAL_BPS" is the maximum assumed size of the average residual magnitude */
		if(bps + FLAC__MAX_EXTRA_RESIDUAL_BPS < threshold) {
			for(partition = residual_sample = 0; partition < partitions; partition++) {
				FLAC__uint32 abs_residual_partition_sum = 0;
				end += default_partition_samples;
				for( ; residual_sample < end; residual_sample++)
					abs_residual_partition_sum += abs(residual[residual_sample]); /* abs(INT_MIN) is undefined, but if the residual is INT_MIN we have bigger problems */
				abs_residual_partition_sums[partition] = abs_residual_partition_sum;
			}
		}
		else { /* have to pessimistically use 64 bits for accumulator */
			for(partition = residual_sample = 0; partition < partitions; partition++) {
				FLAC__uint64 abs_residual_partition_sum64 = 0;
				end += default_partition_samples;
				for( ; residual_sample < end; residual_sample++)
					abs_residual_partition_sum64 += abs(residual[residual_sample]); /* abs(INT_MIN) is undefined, but if the residual is INT_MIN we have bigger problems */
				abs_residual_partition_sums[partition] = abs_residual_partition_sum64;
			}
		}
	}

	/* now merge partitions for lower orders */
	{
		uint32_t from_partition = 0, to_partition = partitions;
		int partition_order;
		for(partition_order = (int)max_partition_order - 1; partition_order >= (int)min_partition_order; partition_order--) {
			uint32_t i;
			partitions >>= 1;
			for(i = 0; i < partitions; i++) {
				abs_residual_partition_sums[to_partition++] =
					abs_residual_partition_sums[from_partition  ] +
					abs_residual_partition_sums[from_partition+1];
				from_partition += 2;
			}
		}
	}
}


void precompute_partition_info_escapes_(
	const FLAC__int32 residual[],
	uint32_t raw_bits_per_partition[],
	uint32_t residual_samples,
	uint32_t predictor_order,
	uint32_t min_partition_order,
	uint32_t max_partition_order
)
{
	int partition_order;
	uint32_t from_partition, to_partition = 0;
	const uint32_t blocksize = residual_samples + predictor_order;

	/* first do max_partition_order */
	for(partition_order = (int)max_partition_order; partition_order >= 0; partition_order--) {
		FLAC__int32 r;
		FLAC__uint32 rmax;
		uint32_t partition, partition_sample, partition_samples, residual_sample;
		const uint32_t partitions = 1u << partition_order;
		const uint32_t default_partition_samples = blocksize >> partition_order;

		FLAC__ASSERT(default_partition_samples > predictor_order);

		for(partition = residual_sample = 0; partition < partitions; partition++) {
			partition_samples = default_partition_samples;
			if(partition == 0)
				partition_samples -= predictor_order;
			rmax = 0;
			for(partition_sample = 0; partition_sample < partition_samples; partition_sample++) {
				r = residual[residual_sample++];
				/* OPT: maybe faster: rmax |= r ^ (r>>31) */
				if(r < 0)
					rmax |= ~r;
				else
					rmax |= r;
			}
			/* now we know all residual values are in the range [-rmax-1,rmax] */
			raw_bits_per_partition[partition] = rmax? FLAC__bitmath_ilog2(rmax) + 2 : 1;
		}
		to_partition = partitions;
		break; /*@@@ yuck, should remove the 'for' loop instead */
	}

	/* now merge partitions for lower orders */
	for(from_partition = 0, --partition_order; partition_order >= (int)min_partition_order; partition_order--) {
		uint32_t m;
		uint32_t i;
		const uint32_t partitions = 1u << partition_order;
		for(i = 0; i < partitions; i++) {
			m = raw_bits_per_partition[from_partition];
			from_partition++;
			raw_bits_per_partition[to_partition] = flac_max(m, raw_bits_per_partition[from_partition]);
			from_partition++;
			to_partition++;
		}
	}
}


FLAC_API uint32_t FLAC__stream_encoder_get_bits_per_sample(const FLAC__StreamEncoder *encoder)
{
	FLAC__ASSERT(0 != encoder);
	FLAC__ASSERT(0 != encoder->private_);
	FLAC__ASSERT(0 != encoder->protected_);
	return encoder->protected_->bits_per_sample;
}


FLAC_API FLAC__bool FLAC__stream_encoder_set_qlp_coeff_precision(FLAC__StreamEncoder *encoder, uint32_t value)
{
	FLAC__ASSERT(0 != encoder);
	FLAC__ASSERT(0 != encoder->private_);
	FLAC__ASSERT(0 != encoder->protected_);
	if(encoder->protected_->state != FLAC__STREAM_ENCODER_UNINITIALIZED)
		return false;
	encoder->protected_->qlp_coeff_precision = value;
	return true;
}


FLAC_API FLAC__bool FLAC__stream_encoder_set_max_residual_partition_order(FLAC__StreamEncoder *encoder, uint32_t value)
{
	FLAC__ASSERT(0 != encoder);
	FLAC__ASSERT(0 != encoder->private_);
	FLAC__ASSERT(0 != encoder->protected_);
	if(encoder->protected_->state != FLAC__STREAM_ENCODER_UNINITIALIZED)
		return false;
	encoder->protected_->max_residual_partition_order = value;
	return true;
}


static void swiotlb_bounce(struct device *dev, phys_addr_t tlb_addr, size_t size,
			   enum dma_data_direction dir)
{
	struct io_tlb_mem *mem = dev->dma_io_tlb_mem;
	int index = (tlb_addr - mem->start) >> IO_TLB_SHIFT;
	phys_addr_t orig_addr = mem->slots[index].orig_addr;
	size_t alloc_size = mem->slots[index].alloc_size;
	unsigned long pfn = PFN_DOWN(orig_addr);
	unsigned char *vaddr = mem->vaddr + tlb_addr - mem->start;
	unsigned int tlb_offset, orig_addr_offset;

	if (orig_addr == INVALID_PHYS_ADDR)
		return;

	tlb_offset = tlb_addr & (IO_TLB_SIZE - 1);
	orig_addr_offset = swiotlb_align_offset(dev, orig_addr);
	if (tlb_offset < orig_addr_offset) {
		dev_WARN_ONCE(dev, 1,
			"Access before mapping start detected. orig offset %u, requested offset %u.\n",
			orig_addr_offset, tlb_offset);
		return;
	}

	tlb_offset -= orig_addr_offset;
	if (tlb_offset > alloc_size) {
		dev_WARN_ONCE(dev, 1,
			"Buffer overflow detected. Allocation size: %zu. Mapping size: %zu+%u.\n",
			alloc_size, size, tlb_offset);
		return;
	}

	orig_addr += tlb_offset;
	alloc_size -= tlb_offset;

	if (size > alloc_size) {
		dev_WARN_ONCE(dev, 1,
			"Buffer overflow detected. Allocation size: %zu. Mapping size: %zu.\n",
			alloc_size, size);
		size = alloc_size;
	}

	if (PageHighMem(pfn_to_page(pfn))) {
		/* The buffer does not have a mapping.  Map it in and copy */
		unsigned int offset = orig_addr & ~PAGE_MASK;
		char *buffer;
		unsigned int sz = 0;
		unsigned long flags;

		while (size) {
			sz = min_t(size_t, PAGE_SIZE - offset, size);

			local_irq_save(flags);
			buffer = kmap_atomic(pfn_to_page(pfn));
			if (dir == DMA_TO_DEVICE)
				memcpy(vaddr, buffer + offset, sz);
			else
				memcpy(buffer + offset, vaddr, sz);
			kunmap_atomic(buffer);
			local_irq_restore(flags);

			size -= sz;
			pfn++;
			vaddr += sz;
			offset = 0;
		}
	} else if (dir == DMA_TO_DEVICE) {
		memcpy(vaddr, phys_to_virt(orig_addr), size);
	} else {
		memcpy(phys_to_virt(orig_addr), vaddr, size);
	}
}


static unsigned int swiotlb_align_offset(struct device *dev, u64 addr)
{
	return addr & dma_get_min_align_mask(dev) & (IO_TLB_SIZE - 1);
}


int64_t yang_dnode_get_int64(const struct lyd_node *dnode,
			     const char *xpath_fmt, ...)
{
	const struct lyd_value *dvalue;
	dvalue = YANG_DNODE_XPATH_GET_VALUE(dnode, xpath_fmt);
	assert(dvalue->realtype->basetype == LY_TYPE_INT64);
	return dvalue->int64;
}


void isis_notif_area_mismatch(const struct isis_circuit *circuit,
			      const char *raw_pdu, size_t raw_pdu_len)
{
	const char *xpath = "/frr-isisd:area-mismatch";
	struct list *arguments = yang_data_list_new();
	char xpath_arg[XPATH_MAXLEN];
	struct yang_data *data;
	struct isis_area *area = circuit->area;

	notif_prep_instance_hdr(xpath, area, "default", arguments);
	notif_prepr_iface_hdr(xpath, circuit, arguments);
	snprintf(xpath_arg, sizeof(xpath_arg), "%s/raw-pdu", xpath);
	data = yang_data_new_binary(xpath_arg, raw_pdu, raw_pdu_len);
	listnode_add(arguments, data);

	hook_call(isis_hook_area_mismatch, circuit, raw_pdu, raw_pdu_len);

	nb_notification_send(xpath, arguments);
}


const char *yang_dnode_get_string(const struct lyd_node *dnode,
				  const char *xpath_fmt, ...)
{
	return YANG_DNODE_XPATH_GET_CANON(dnode, xpath_fmt);
}


void yang_str2ipv6p(const char *value, union prefixptr prefix)
{
	struct prefix_ipv6 *prefix6 = prefix.p6;

	(void)str2prefix_ipv6(value, prefix6);
	apply_mask_ipv6(prefix6);
}


void yang_get_default_ipv6p(union prefixptr var, const char *xpath_fmt, ...)
{
	char xpath[XPATH_MAXLEN];
	const char *value;
	va_list ap;

	va_start(ap, xpath_fmt);
	vsnprintf(xpath, sizeof(xpath), xpath_fmt, ap);
	va_end(ap);

	value = yang_get_default_value(xpath);
	yang_str2ipv6p(value, var);
}


void isis_notif_version_skew(const struct isis_circuit *circuit,
			     uint8_t version, const char *raw_pdu,
			     size_t raw_pdu_len)
{
	const char *xpath = "/frr-isisd:version-skew";
	struct list *arguments = yang_data_list_new();
	char xpath_arg[XPATH_MAXLEN];
	struct yang_data *data;
	struct isis_area *area = circuit->area;

	notif_prep_instance_hdr(xpath, area, "default", arguments);
	notif_prepr_iface_hdr(xpath, circuit, arguments);
	snprintf(xpath_arg, sizeof(xpath_arg), "%s/protocol-version", xpath);
	data = yang_data_new_uint8(xpath_arg, version);
	listnode_add(arguments, data);
	snprintf(xpath_arg, sizeof(xpath_arg), "%s/raw-pdu", xpath);
	data = yang_data_new_binary(xpath_arg, raw_pdu, raw_pdu_len);
	listnode_add(arguments, data);

	hook_call(isis_hook_version_skew, circuit, version, raw_pdu,
		  raw_pdu_len);

	nb_notification_send(xpath, arguments);
}


unsigned long iov_iter_gap_alignment(const struct iov_iter *i)
{
	unsigned long res = 0;
	unsigned long v = 0;
	size_t size = i->count;
	unsigned k;

	if (WARN_ON(!iter_is_iovec(i)))
		return ~0U;

	for (k = 0; k < i->nr_segs; k++) {
		if (i->iov[k].iov_len) {
			unsigned long base = (unsigned long)i->iov[k].iov_base;
			if (v) // if not the first one
				res |= base | v; // this start | previous end
			v = base + i->iov[k].iov_len;
			if (size <= i->iov[k].iov_len)
				break;
			size -= i->iov[k].iov_len;
		}
	}
	return res;
}


static size_t copy_page_to_iter_iovec(struct page *page, size_t offset, size_t bytes,
			 struct iov_iter *i)
{
	size_t skip, copy, left, wanted;
	const struct iovec *iov;
	char __user *buf;
	void *kaddr, *from;

	if (unlikely(bytes > i->count))
		bytes = i->count;

	if (unlikely(!bytes))
		return 0;

	might_fault();
	wanted = bytes;
	iov = i->iov;
	skip = i->iov_offset;
	buf = iov->iov_base + skip;
	copy = min(bytes, iov->iov_len - skip);

	if (IS_ENABLED(CONFIG_HIGHMEM) && !fault_in_writeable(buf, copy)) {
		kaddr = kmap_atomic(page);
		from = kaddr + offset;

		/* first chunk, usually the only one */
		left = copyout(buf, from, copy);
		copy -= left;
		skip += copy;
		from += copy;
		bytes -= copy;

		while (unlikely(!left && bytes)) {
			iov++;
			buf = iov->iov_base;
			copy = min(bytes, iov->iov_len);
			left = copyout(buf, from, copy);
			copy -= left;
			skip = copy;
			from += copy;
			bytes -= copy;
		}
		if (likely(!bytes)) {
			kunmap_atomic(kaddr);
			goto done;
		}
		offset = from - kaddr;
		buf += copy;
		kunmap_atomic(kaddr);
		copy = min(bytes, iov->iov_len - skip);
	}
	/* Too bad - revert to non-atomic kmap */

	kaddr = kmap(page);
	from = kaddr + offset;
	left = copyout(buf, from, copy);
	copy -= left;
	skip += copy;
	from += copy;
	bytes -= copy;
	while (unlikely(!left && bytes)) {
		iov++;
		buf = iov->iov_base;
		copy = min(bytes, iov->iov_len);
		left = copyout(buf, from, copy);
		copy -= left;
		skip = copy;
		from += copy;
		bytes -= copy;
	}
	kunmap(page);

done:
	if (skip == iov->iov_len) {
		iov++;
		skip = 0;
	}
	i->count -= wanted - bytes;
	i->nr_segs -= iov - i->iov;
	i->iov = iov;
	i->iov_offset = skip;
	return wanted - bytes;
}


static bool sanity(const struct iov_iter *i)
{
	struct pipe_inode_info *pipe = i->pipe;
	unsigned int p_head = pipe->head;
	unsigned int p_tail = pipe->tail;
	unsigned int p_mask = pipe->ring_size - 1;
	unsigned int p_occupancy = pipe_occupancy(p_head, p_tail);
	unsigned int i_head = i->head;
	unsigned int idx;

	if (i->iov_offset) {
		struct pipe_buffer *p;
		if (unlikely(p_occupancy == 0))
			goto Bad;	// pipe must be non-empty
		if (unlikely(i_head != p_head - 1))
			goto Bad;	// must be at the last buffer...

		p = &pipe->bufs[i_head & p_mask];
		if (unlikely(p->offset + p->len != i->iov_offset))
			goto Bad;	// ... at the end of segment
	} else {
		if (i_head != p_head)
			goto Bad;	// must be right after the last buffer
	}
	return true;
Bad:
	printk(KERN_ERR "idx = %d, offset = %zd\n", i_head, i->iov_offset);
	printk(KERN_ERR "head = %d, tail = %d, buffers = %d\n",
			p_head, p_tail, pipe->ring_size);
	for (idx = 0; idx < pipe->ring_size; idx++)
		printk(KERN_ERR "[%p %p %d %d]\n",
			pipe->bufs[idx].ops,
			pipe->bufs[idx].page,
			pipe->bufs[idx].offset,
			pipe->bufs[idx].len);
	WARN_ON(1);
	return false;
}


static inline void pipe_truncate(struct iov_iter *i)
{
	struct pipe_inode_info *pipe = i->pipe;
	unsigned int p_tail = pipe->tail;
	unsigned int p_head = pipe->head;
	unsigned int p_mask = pipe->ring_size - 1;

	if (!pipe_empty(p_head, p_tail)) {
		struct pipe_buffer *buf;
		unsigned int i_head = i->head;
		size_t off = i->iov_offset;

		if (off) {
			buf = &pipe->bufs[i_head & p_mask];
			buf->len = off - buf->offset;
			i_head++;
		}
		while (p_head != i_head) {
			p_head--;
			pipe_buf_release(pipe, &pipe->bufs[p_head & p_mask]);
		}

		pipe->head = p_head;
	}
}


static inline void data_start(const struct iov_iter *i,
			      unsigned int *iter_headp, size_t *offp)
{
	unsigned int p_mask = i->pipe->ring_size - 1;
	unsigned int iter_head = i->head;
	size_t off = i->iov_offset;

	if (off && (!allocated(&i->pipe->bufs[iter_head & p_mask]) ||
		    off == PAGE_SIZE)) {
		iter_head++;
		off = 0;
	}
	*iter_headp = iter_head;
	*offp = off;
}


size_t iov_iter_single_seg_count(const struct iov_iter *i)
{
	if (i->nr_segs > 1) {
		if (likely(iter_is_iovec(i) || iov_iter_is_kvec(i)))
			return min(i->count, i->iov->iov_len - i->iov_offset);
		if (iov_iter_is_bvec(i))
			return min(i->count, i->bvec->bv_len - i->iov_offset);
	}
	return i->count;
}


static inline ssize_t __pipe_get_pages(struct iov_iter *i,
				size_t maxsize,
				struct page **pages,
				int iter_head,
				size_t *start)
{
	struct pipe_inode_info *pipe = i->pipe;
	unsigned int p_mask = pipe->ring_size - 1;
	ssize_t n = push_pipe(i, maxsize, &iter_head, start);
	if (!n)
		return -EFAULT;

	maxsize = n;
	n += *start;
	while (n > 0) {
		get_page(*pages++ = pipe->bufs[iter_head & p_mask].page);
		iter_head++;
		n -= PAGE_SIZE;
	}

	return maxsize;
}


static int iov_npages(const struct iov_iter *i, int maxpages)
{
	size_t skip = i->iov_offset, size = i->count;
	const struct iovec *p;
	int npages = 0;

	for (p = i->iov; size; skip = 0, p++) {
		unsigned offs = offset_in_page(p->iov_base + skip);
		size_t len = min(p->iov_len - skip, size);

		if (len) {
			size -= len;
			npages += DIV_ROUND_UP(offs + len, PAGE_SIZE);
			if (unlikely(npages > maxpages))
				return maxpages;
		}
	}
	return npages;
}


static void sr_mdio_write(struct net_device *netdev, int phy_id, int loc,
			  int val)
{
	struct usbnet *dev = netdev_priv(netdev);
	__le16 res = cpu_to_le16(val);

	if (phy_id) {
		netdev_dbg(netdev, "Only internal phy supported\n");
		return;
	}

	netdev_dbg(netdev, "sr_mdio_write() phy_id=0x%02x, loc=0x%02x, val=0x%04x\n",
		   phy_id, loc, val);

	sr_share_write_word(dev, 1, loc, res);
}


static int sr9700_set_mac_address(struct net_device *netdev, void *p)
{
	struct usbnet *dev = netdev_priv(netdev);
	struct sockaddr *addr = p;

	if (!is_valid_ether_addr(addr->sa_data)) {
		netdev_err(netdev, "not setting invalid mac address %pM\n",
			   addr->sa_data);
		return -EINVAL;
	}

	eth_hw_addr_set(netdev, addr->sa_data);
	sr_write_async(dev, SR_PAR, 6, netdev->dev_addr);

	return 0;
}


static void sr9700_set_multicast(struct net_device *netdev)
{
	struct usbnet *dev = netdev_priv(netdev);
	/* We use the 20 byte dev->data for our 8 byte filter buffer
	 * to avoid allocating memory that is tricky to free later
	 */
	u8 *hashes = (u8 *)&dev->data;
	/* rx_ctl setting : enable, disable_long, disable_crc */
	u8 rx_ctl = RCR_RXEN | RCR_DIS_CRC | RCR_DIS_LONG;

	memset(hashes, 0x00, SR_MCAST_SIZE);
	/* broadcast address */
	hashes[SR_MCAST_SIZE - 1] |= SR_MCAST_ADDR_FLAG;
	if (netdev->flags & IFF_PROMISC) {
		rx_ctl |= RCR_PRMSC;
	} else if (netdev->flags & IFF_ALLMULTI ||
		   netdev_mc_count(netdev) > SR_MCAST_MAX) {
		rx_ctl |= RCR_RUNT;
	} else if (!netdev_mc_empty(netdev)) {
		struct netdev_hw_addr *ha;

		netdev_for_each_mc_addr(ha, netdev) {
			u32 crc = ether_crc(ETH_ALEN, ha->addr) >> 26;
			hashes[crc >> 3] |= 1 << (crc & 0x7);
		}
	}

	sr_write_async(dev, SR_MAR, SR_MCAST_SIZE, hashes);
	sr_write_reg_async(dev, SR_RCR, rx_ctl);
}


static void sr_write_async(struct usbnet *dev, u8 reg, u16 length,
			   const void *data)
{
	usbnet_write_cmd_async(dev, SR_WR_REGS, SR_REQ_WR_REG,
			       0, reg, data, length);
}


static int sr_mdio_read(struct net_device *netdev, int phy_id, int loc)
{
	struct usbnet *dev = netdev_priv(netdev);
	__le16 res;
	int rc = 0;

	if (phy_id) {
		netdev_dbg(netdev, "Only internal phy supported\n");
		return 0;
	}

	/* Access NSR_LINKST bit for link status instead of MII_BMSR */
	if (loc == MII_BMSR) {
		u8 value;

		sr_read_reg(dev, SR_NSR, &value);
		if (value & NSR_LINKST)
			rc = 1;
	}
	sr_share_read_word(dev, 1, loc, &res);
	if (rc == 1)
		res = le16_to_cpu(res) | BMSR_LSTATUS;
	else
		res = le16_to_cpu(res) & ~BMSR_LSTATUS;

	netdev_dbg(netdev, "sr_mdio_read() phy_id=0x%02x, loc=0x%02x, returns=0x%04x\n",
		   phy_id, loc, res);

	return res;
}


nwfilterDriverRemoveDBusMatches(void)
{
    GDBusConnection *sysbus;

    sysbus = virGDBusGetSystemBus();
    if (sysbus) {
        g_dbus_connection_signal_unsubscribe(sysbus, restartID);
        g_dbus_connection_signal_unsubscribe(sysbus, reloadID);
    }
}


nwfilterFirewalldDBusSignalCallback(GDBusConnection *connection G_GNUC_UNUSED,
                                    const char *senderName G_GNUC_UNUSED,
                                    const char *objectPath G_GNUC_UNUSED,
                                    const char *interfaceName G_GNUC_UNUSED,
                                    const char *signalName G_GNUC_UNUSED,
                                    GVariant *parameters G_GNUC_UNUSED,
                                    gpointer user_data G_GNUC_UNUSED)
{
    nwfilterStateReload();
}


static int virtbt_setup_realtek(struct hci_dev *hdev)
{
	struct sk_buff *skb;

	/* Read ROM Version */
	skb = __hci_cmd_sync(hdev, 0xfc6d, 0, NULL, HCI_INIT_TIMEOUT);
	if (IS_ERR(skb))
		return PTR_ERR(skb);

	bt_dev_info(hdev, "ROM version %u", *((__u8 *) (skb->data + 1)));

	kfree_skb(skb);
	return 0;
}


static int remove_free_dqentry(struct qtree_mem_dqinfo *info, char *buf,
			       uint blk)
{
	char *tmpbuf = kmalloc(info->dqi_usable_bs, GFP_NOFS);
	struct qt_disk_dqdbheader *dh = (struct qt_disk_dqdbheader *)buf;
	uint nextblk = le32_to_cpu(dh->dqdh_next_free);
	uint prevblk = le32_to_cpu(dh->dqdh_prev_free);
	int err;

	if (!tmpbuf)
		return -ENOMEM;
	if (nextblk) {
		err = read_blk(info, nextblk, tmpbuf);
		if (err < 0)
			goto out_buf;
		((struct qt_disk_dqdbheader *)tmpbuf)->dqdh_prev_free =
							dh->dqdh_prev_free;
		err = write_blk(info, nextblk, tmpbuf);
		if (err < 0)
			goto out_buf;
	}
	if (prevblk) {
		err = read_blk(info, prevblk, tmpbuf);
		if (err < 0)
			goto out_buf;
		((struct qt_disk_dqdbheader *)tmpbuf)->dqdh_next_free =
							dh->dqdh_next_free;
		err = write_blk(info, prevblk, tmpbuf);
		if (err < 0)
			goto out_buf;
	} else {
		info->dqi_free_entry = nextblk;
		mark_info_dirty(info->dqi_sb, info->dqi_type);
	}
	kfree(tmpbuf);
	dh->dqdh_next_free = dh->dqdh_prev_free = cpu_to_le32(0);
	/* No matter whether write succeeds block is out of list */
	if (write_blk(info, blk, buf) < 0)
		quota_error(info->dqi_sb, "Can't write block (%u) "
			    "with free entries", blk);
	return 0;
out_buf:
	kfree(tmpbuf);
	return err;
}


int qtree_get_next_id(struct qtree_mem_dqinfo *info, struct kqid *qid)
{
	qid_t id = from_kqid(&init_user_ns, *qid);
	int ret;

	ret = find_next_id(info, &id, QT_TREEOFF, 0);
	if (ret < 0)
		return ret;
	*qid = make_kqid(&init_user_ns, qid->type, id);
	return 0;
}


static int remove_tree(struct qtree_mem_dqinfo *info, struct dquot *dquot,
		       uint *blk, int depth)
{
	char *buf = kmalloc(info->dqi_usable_bs, GFP_NOFS);
	int ret = 0;
	uint newblk;
	__le32 *ref = (__le32 *)buf;

	if (!buf)
		return -ENOMEM;
	ret = read_blk(info, *blk, buf);
	if (ret < 0) {
		quota_error(dquot->dq_sb, "Can't read quota data block %u",
			    *blk);
		goto out_buf;
	}
	newblk = le32_to_cpu(ref[get_index(info, dquot->dq_id, depth)]);
	if (newblk < QT_TREEOFF || newblk >= info->dqi_blocks) {
		quota_error(dquot->dq_sb, "Getting block too big (%u >= %u)",
			    newblk, info->dqi_blocks);
		ret = -EUCLEAN;
		goto out_buf;
	}

	if (depth == info->dqi_qtree_depth - 1) {
		ret = free_dqentry(info, dquot, newblk);
		newblk = 0;
	} else {
		ret = remove_tree(info, dquot, &newblk, depth+1);
	}
	if (ret >= 0 && !newblk) {
		int i;
		ref[get_index(info, dquot->dq_id, depth)] = cpu_to_le32(0);
		/* Block got empty? */
		for (i = 0; i < (info->dqi_usable_bs >> 2) && !ref[i]; i++)
			;
		/* Don't put the root block into the free block list */
		if (i == (info->dqi_usable_bs >> 2)
		    && *blk != QT_TREEOFF) {
			put_free_dqblk(info, buf, *blk);
			*blk = 0;
		} else {
			ret = write_blk(info, *blk, buf);
			if (ret < 0)
				quota_error(dquot->dq_sb,
					    "Can't write quota tree block %u",
					    *blk);
		}
	}
out_buf:
	kfree(buf);
	return ret;
}


static int put_free_dqblk(struct qtree_mem_dqinfo *info, char *buf, uint blk)
{
	struct qt_disk_dqdbheader *dh = (struct qt_disk_dqdbheader *)buf;
	int err;

	dh->dqdh_next_free = cpu_to_le32(info->dqi_free_blk);
	dh->dqdh_prev_free = cpu_to_le32(0);
	dh->dqdh_entries = cpu_to_le16(0);
	err = write_blk(info, blk, buf);
	if (err < 0)
		return err;
	info->dqi_free_blk = blk;
	mark_info_dirty(info->dqi_sb, info->dqi_type);
	return 0;
}


char get_next_file(int imageno, dircnt_t *dirptr, img_fol_t *img_fol,
                   opj_decompress_parameters *parameters)
{
    char image_filename[OPJ_PATH_LEN], infilename[OPJ_PATH_LEN],
         outfilename[OPJ_PATH_LEN], temp_ofname[OPJ_PATH_LEN];
    char *temp_p, temp1[OPJ_PATH_LEN] = "";

    strcpy(image_filename, dirptr->filename[imageno]);
    fprintf(stderr, "File Number %d \"%s\"\n", imageno, image_filename);
    if (strlen(img_fol->imgdirpath) + strlen(path_separator) + strlen(
                image_filename) + 1 > sizeof(infilename)) {
        return 1;
    }
    strcpy(infilename, img_fol->imgdirpath);
    strcat(infilename, path_separator);
    strcat(infilename, image_filename);
    parameters->decod_format = infile_format(infilename);
    if (parameters->decod_format == -1) {
        return 1;
    }
    if (opj_strcpy_s(parameters->infile, sizeof(parameters->infile),
                     infilename) != 0) {
        return 1;
    }

    /*Set output file*/
    strcpy(temp_ofname, strtok(image_filename, "."));
    while ((temp_p = strtok(NULL, ".")) != NULL) {
        strcat(temp_ofname, temp1);
        sprintf(temp1, ".%s", temp_p);
    }
    if (img_fol->set_out_format == 1) {
        if (strlen(img_fol->imgdirpath) + 1 + strlen(temp_ofname) + 1 + strlen(
                    img_fol->out_format) + 1 > sizeof(outfilename)) {
            return 1;
        }
        strcpy(outfilename, img_fol->imgdirpath);
        strcat(outfilename, "/");
        strcat(outfilename, temp_ofname);
        strcat(outfilename, ".");
        strcat(outfilename, img_fol->out_format);
        if (opj_strcpy_s(parameters->outfile, sizeof(parameters->outfile),
                         outfilename) != 0) {
            return 1;
        }
    }
    return 0;
}


static int ax88179_convert_old_led(struct usbnet *dev, u16 *ledvalue)
{
	u16 led;

	/* Loaded the old eFuse LED Mode */
	if (ax88179_read_cmd(dev, AX_ACCESS_EEPROM, 0x3C, 1, 2, &led) < 0)
		return -EINVAL;

	led >>= 8;
	switch (led) {
	case 0xFF:
		led = LED0_ACTIVE | LED1_LINK_10 | LED1_LINK_100 |
		      LED1_LINK_1000 | LED2_ACTIVE | LED2_LINK_10 |
		      LED2_LINK_100 | LED2_LINK_1000 | LED_VALID;
		break;
	case 0xFE:
		led = LED0_ACTIVE | LED1_LINK_1000 | LED2_LINK_100 | LED_VALID;
		break;
	case 0xFD:
		led = LED0_ACTIVE | LED1_LINK_1000 | LED2_LINK_100 |
		      LED2_LINK_10 | LED_VALID;
		break;
	case 0xFC:
		led = LED0_ACTIVE | LED1_ACTIVE | LED1_LINK_1000 | LED2_ACTIVE |
		      LED2_LINK_100 | LED2_LINK_10 | LED_VALID;
		break;
	default:
		led = LED0_ACTIVE | LED1_LINK_10 | LED1_LINK_100 |
		      LED1_LINK_1000 | LED2_ACTIVE | LED2_LINK_10 |
		      LED2_LINK_100 | LED2_LINK_1000 | LED_VALID;
		break;
	}

	*ledvalue = led;

	return 0;
}


ax88179_rx_checksum(struct sk_buff *skb, u32 *pkt_hdr)
{
	skb->ip_summed = CHECKSUM_NONE;

	/* checksum error bit is set */
	if ((*pkt_hdr & AX_RXHDR_L3CSUM_ERR) ||
	    (*pkt_hdr & AX_RXHDR_L4CSUM_ERR))
		return;

	/* It must be a TCP or UDP packet with a valid checksum */
	if (((*pkt_hdr & AX_RXHDR_L4_TYPE_MASK) == AX_RXHDR_L4_TYPE_TCP) ||
	    ((*pkt_hdr & AX_RXHDR_L4_TYPE_MASK) == AX_RXHDR_L4_TYPE_UDP))
		skb->ip_summed = CHECKSUM_UNNECESSARY;
}


ax88179_set_wol(struct net_device *net, struct ethtool_wolinfo *wolinfo)
{
	struct usbnet *dev = netdev_priv(net);
	u8 opt = 0;

	if (wolinfo->wolopts & ~(WAKE_PHY | WAKE_MAGIC))
		return -EINVAL;

	if (wolinfo->wolopts & WAKE_PHY)
		opt |= AX_MONITOR_MODE_RWLC;
	if (wolinfo->wolopts & WAKE_MAGIC)
		opt |= AX_MONITOR_MODE_RWMP;

	if (ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_MONITOR_MOD,
			      1, 1, &opt) < 0)
		return -EINVAL;

	return 0;
}


static int ax88179_set_link_ksettings(struct net_device *net,
				      const struct ethtool_link_ksettings *cmd)
{
	struct usbnet *dev = netdev_priv(net);
	return mii_ethtool_set_link_ksettings(&dev->mii, cmd);
}


void ixgbe_restore_vf_multicasts(struct ixgbe_adapter *adapter)
{
	struct ixgbe_hw *hw = &adapter->hw;
	struct vf_data_storage *vfinfo;
	int i, j;
	u32 vector_bit;
	u32 vector_reg;
	u32 mta_reg;

	for (i = 0; i < adapter->num_vfs; i++) {
		u32 vmolr = IXGBE_READ_REG(hw, IXGBE_VMOLR(i));
		vfinfo = &adapter->vfinfo[i];
		for (j = 0; j < vfinfo->num_vf_mc_hashes; j++) {
			hw->addr_ctrl.mta_in_use++;
			vector_reg = (vfinfo->vf_mc_hashes[j] >> 5) & 0x7F;
			vector_bit = vfinfo->vf_mc_hashes[j] & 0x1F;
			mta_reg = IXGBE_READ_REG(hw, IXGBE_MTA(vector_reg));
			mta_reg |= BIT(vector_bit);
			IXGBE_WRITE_REG(hw, IXGBE_MTA(vector_reg), mta_reg);
		}

		if (vfinfo->num_vf_mc_hashes)
			vmolr |= IXGBE_VMOLR_ROMPE;
		else
			vmolr &= ~IXGBE_VMOLR_ROMPE;
		IXGBE_WRITE_REG(hw, IXGBE_VMOLR(i), vmolr);
	}

	/* Restore any VF macvlans */
	ixgbe_full_sync_mac_table(adapter);
}


static int ixgbe_pci_sriov_disable(struct pci_dev *dev)
{
	struct ixgbe_adapter *adapter = pci_get_drvdata(dev);
	int err;
#ifdef CONFIG_PCI_IOV
	u32 current_flags = adapter->flags;
	int prev_num_vf = pci_num_vf(dev);
#endif

	err = ixgbe_disable_sriov(adapter);

	/* Only reinit if no error and state changed */
#ifdef CONFIG_PCI_IOV
	if (!err && (current_flags != adapter->flags ||
		     prev_num_vf != pci_num_vf(dev)))
		ixgbe_sriov_reinit(adapter);
#endif

	return err;
}


int ixgbe_disable_sriov(struct ixgbe_adapter *adapter)
{
	unsigned int num_vfs = adapter->num_vfs, vf;
	int rss;

	/* set num VFs to 0 to prevent access to vfinfo */
	adapter->num_vfs = 0;

	/* put the reference to all of the vf devices */
	for (vf = 0; vf < num_vfs; ++vf) {
		struct pci_dev *vfdev = adapter->vfinfo[vf].vfdev;

		if (!vfdev)
			continue;
		adapter->vfinfo[vf].vfdev = NULL;
		pci_dev_put(vfdev);
	}

	/* free VF control structures */
	kfree(adapter->vfinfo);
	adapter->vfinfo = NULL;

	/* free macvlan list */
	kfree(adapter->mv_list);
	adapter->mv_list = NULL;

	/* if SR-IOV is already disabled then there is nothing to do */
	if (!(adapter->flags & IXGBE_FLAG_SRIOV_ENABLED))
		return 0;

#ifdef CONFIG_PCI_IOV
	/*
	 * If our VFs are assigned we cannot shut down SR-IOV
	 * without causing issues, so just leave the hardware
	 * available but disabled
	 */
	if (pci_vfs_assigned(adapter->pdev)) {
		e_dev_warn("Unloading driver while VFs are assigned - VFs will not be deallocated\n");
		return -EPERM;
	}
	/* disable iov and allow time for transactions to clear */
	pci_disable_sriov(adapter->pdev);
#endif

	/* Disable VMDq flag so device will be set in VM mode */
	if (bitmap_weight(adapter->fwd_bitmask, adapter->num_rx_pools) == 1) {
		adapter->flags &= ~IXGBE_FLAG_VMDQ_ENABLED;
		adapter->flags &= ~IXGBE_FLAG_SRIOV_ENABLED;
		rss = min_t(int, ixgbe_max_rss_indices(adapter),
			    num_online_cpus());
	} else {
		rss = min_t(int, IXGBE_MAX_L2A_QUEUES, num_online_cpus());
	}

	adapter->ring_feature[RING_F_VMDQ].offset = 0;
	adapter->ring_feature[RING_F_RSS].limit = rss;

	/* take a breather then clean up driver data */
	msleep(100);
	return 0;
}


void ixgbe_enable_sriov(struct ixgbe_adapter *adapter, unsigned int max_vfs)
{
	int pre_existing_vfs = 0;
	unsigned int num_vfs;

	pre_existing_vfs = pci_num_vf(adapter->pdev);
	if (!pre_existing_vfs && !max_vfs)
		return;

	/* If there are pre-existing VFs then we have to force
	 * use of that many - over ride any module parameter value.
	 * This may result from the user unloading the PF driver
	 * while VFs were assigned to guest VMs or because the VFs
	 * have been created via the new PCI SR-IOV sysfs interface.
	 */
	if (pre_existing_vfs) {
		num_vfs = pre_existing_vfs;
		dev_warn(&adapter->pdev->dev,
			 "Virtual Functions already enabled for this device - Please reload all VF drivers to avoid spoofed packet errors\n");
	} else {
		int err;
		/*
		 * The 82599 supports up to 64 VFs per physical function
		 * but this implementation limits allocation to 63 so that
		 * basic networking resources are still available to the
		 * physical function.  If the user requests greater than
		 * 63 VFs then it is an error - reset to default of zero.
		 */
		num_vfs = min_t(unsigned int, max_vfs, IXGBE_MAX_VFS_DRV_LIMIT);

		err = pci_enable_sriov(adapter->pdev, num_vfs);
		if (err) {
			e_err(probe, "Failed to enable PCI sriov: %d\n", err);
			return;
		}
	}

	if (!__ixgbe_enable_sriov(adapter, num_vfs)) {
		ixgbe_get_vfs(adapter);
		return;
	}

	/* If we have gotten to this point then there is no memory available
	 * to manage the VF devices - print message and bail.
	 */
	e_err(probe, "Unable to allocate memory for VF Data Storage - "
	      "SRIOV disabled\n");
	ixgbe_disable_sriov(adapter);
}


static int ixgbe_set_vf_multicasts(struct ixgbe_adapter *adapter,
				   u32 *msgbuf, u32 vf)
{
	int entries = (msgbuf[0] & IXGBE_VT_MSGINFO_MASK)
		       >> IXGBE_VT_MSGINFO_SHIFT;
	u16 *hash_list = (u16 *)&msgbuf[1];
	struct vf_data_storage *vfinfo = &adapter->vfinfo[vf];
	struct ixgbe_hw *hw = &adapter->hw;
	int i;
	u32 vector_bit;
	u32 vector_reg;
	u32 mta_reg;
	u32 vmolr = IXGBE_READ_REG(hw, IXGBE_VMOLR(vf));

	/* only so many hash values supported */
	entries = min(entries, IXGBE_MAX_VF_MC_ENTRIES);

	/*
	 * salt away the number of multi cast addresses assigned
	 * to this VF for later use to restore when the PF multi cast
	 * list changes
	 */
	vfinfo->num_vf_mc_hashes = entries;

	/*
	 * VFs are limited to using the MTA hash table for their multicast
	 * addresses
	 */
	for (i = 0; i < entries; i++) {
		vfinfo->vf_mc_hashes[i] = hash_list[i];
	}

	for (i = 0; i < vfinfo->num_vf_mc_hashes; i++) {
		vector_reg = (vfinfo->vf_mc_hashes[i] >> 5) & 0x7F;
		vector_bit = vfinfo->vf_mc_hashes[i] & 0x1F;
		mta_reg = IXGBE_READ_REG(hw, IXGBE_MTA(vector_reg));
		mta_reg |= BIT(vector_bit);
		IXGBE_WRITE_REG(hw, IXGBE_MTA(vector_reg), mta_reg);
	}
	vmolr |= IXGBE_VMOLR_ROMPE;
	IXGBE_WRITE_REG(hw, IXGBE_VMOLR(vf), vmolr);

	return 0;
}


static int ixgbe_set_vf_vlan(struct ixgbe_adapter *adapter, int add, int vid,
			     u32 vf)
{
	struct ixgbe_hw *hw = &adapter->hw;
	int err;

	/* If VLAN overlaps with one the PF is currently monitoring make
	 * sure that we are able to allocate a VLVF entry.  This may be
	 * redundant but it guarantees PF will maintain visibility to
	 * the VLAN.
	 */
	if (add && test_bit(vid, adapter->active_vlans)) {
		err = hw->mac.ops.set_vfta(hw, vid, VMDQ_P(0), true, false);
		if (err)
			return err;
	}

	err = hw->mac.ops.set_vfta(hw, vid, vf, !!add, false);

	if (add && !err)
		return err;

	/* If we failed to add the VF VLAN or we are removing the VF VLAN
	 * we may need to drop the PF pool bit in order to allow us to free
	 * up the VLVF resources.
	 */
	if (test_bit(vid, adapter->active_vlans) ||
	    (adapter->flags2 & IXGBE_FLAG2_VLAN_PROMISC))
		ixgbe_update_pf_promisc_vlvf(adapter, vid);

	return err;
}


static bool kvm_hv_is_syndbg_enabled(struct kvm_vcpu *vcpu)
{
	struct kvm_vcpu_hv *hv_vcpu = to_hv_vcpu(vcpu);

	return hv_vcpu->cpuid_cache.syndbg_cap_eax &
		HV_X64_SYNDBG_CAP_ALLOW_KERNEL_DEBUGGING;
}


static u64 kvm_get_sparse_vp_set(struct kvm *kvm, struct kvm_hv_hcall *hc,
				 int consumed_xmm_halves,
				 u64 *sparse_banks, gpa_t offset)
{
	u16 var_cnt;
	int i;

	if (hc->var_cnt > 64)
		return -EINVAL;

	/* Ignore banks that cannot possibly contain a legal VP index. */
	var_cnt = min_t(u16, hc->var_cnt, KVM_HV_MAX_SPARSE_VCPU_SET_BITS);

	if (hc->fast) {
		/*
		 * Each XMM holds two sparse banks, but do not count halves that
		 * have already been consumed for hypercall parameters.
		 */
		if (hc->var_cnt > 2 * HV_HYPERCALL_MAX_XMM_REGISTERS - consumed_xmm_halves)
			return HV_STATUS_INVALID_HYPERCALL_INPUT;
		for (i = 0; i < var_cnt; i++) {
			int j = i + consumed_xmm_halves;
			if (j % 2)
				sparse_banks[i] = sse128_hi(hc->xmm[j / 2]);
			else
				sparse_banks[i] = sse128_lo(hc->xmm[j / 2]);
		}
		return 0;
	}

	return kvm_read_guest(kvm, hc->ingpa + offset, sparse_banks,
			      var_cnt * sizeof(*sparse_banks));
}


static void synic_update_vector(struct kvm_vcpu_hv_synic *synic,
				int vector)
{
	struct kvm_vcpu *vcpu = hv_synic_to_vcpu(synic);
	struct kvm_hv *hv = to_kvm_hv(vcpu->kvm);
	int auto_eoi_old, auto_eoi_new;

	if (vector < HV_SYNIC_FIRST_VALID_VECTOR)
		return;

	if (synic_has_vector_connected(synic, vector))
		__set_bit(vector, synic->vec_bitmap);
	else
		__clear_bit(vector, synic->vec_bitmap);

	auto_eoi_old = bitmap_weight(synic->auto_eoi_bitmap, 256);

	if (synic_has_vector_auto_eoi(synic, vector))
		__set_bit(vector, synic->auto_eoi_bitmap);
	else
		__clear_bit(vector, synic->auto_eoi_bitmap);

	auto_eoi_new = bitmap_weight(synic->auto_eoi_bitmap, 256);

	if (!!auto_eoi_old == !!auto_eoi_new)
		return;

	if (!enable_apicv)
		return;

	down_write(&vcpu->kvm->arch.apicv_update_lock);

	if (auto_eoi_new)
		hv->synic_auto_eoi_used++;
	else
		hv->synic_auto_eoi_used--;

	__kvm_request_apicv_update(vcpu->kvm,
				   !hv->synic_auto_eoi_used,
				   APICV_INHIBIT_REASON_HYPERV);

	up_write(&vcpu->kvm->arch.apicv_update_lock);
}


void kvm_hv_invalidate_tsc_page(struct kvm *kvm)
{
	struct kvm_hv *hv = to_kvm_hv(kvm);
	u64 gfn;
	int idx;

	if (hv->hv_tsc_page_status == HV_TSC_PAGE_BROKEN ||
	    hv->hv_tsc_page_status == HV_TSC_PAGE_UNSET ||
	    tsc_page_update_unsafe(hv))
		return;

	mutex_lock(&hv->hv_lock);

	if (!(hv->hv_tsc_page & HV_X64_MSR_TSC_REFERENCE_ENABLE))
		goto out_unlock;

	/* Preserve HV_TSC_PAGE_GUEST_CHANGED/HV_TSC_PAGE_HOST_CHANGED states */
	if (hv->hv_tsc_page_status == HV_TSC_PAGE_SET)
		hv->hv_tsc_page_status = HV_TSC_PAGE_UPDATING;

	gfn = hv->hv_tsc_page >> HV_X64_MSR_TSC_REFERENCE_ADDRESS_SHIFT;

	hv->tsc_ref.tsc_sequence = 0;

	/*
	 * Take the srcu lock as memslots will be accessed to check the gfn
	 * cache generation against the memslots generation.
	 */
	idx = srcu_read_lock(&kvm->srcu);
	if (kvm_write_guest(kvm, gfn_to_gpa(gfn),
			    &hv->tsc_ref, sizeof(hv->tsc_ref.tsc_sequence)))
		hv->hv_tsc_page_status = HV_TSC_PAGE_BROKEN;
	srcu_read_unlock(&kvm->srcu, idx);

out_unlock:
	mutex_unlock(&hv->hv_lock);
}


static inline void apic_set_isr(int vec, struct kvm_lapic *apic)
{
	struct kvm_vcpu *vcpu;

	if (__apic_test_and_set_vector(vec, apic->regs + APIC_ISR))
		return;

	vcpu = apic->vcpu;

	/*
	 * With APIC virtualization enabled, all caching is disabled
	 * because the processor can modify ISR under the hood.  Instead
	 * just set SVI.
	 */
	if (unlikely(vcpu->arch.apicv_active))
		static_call_cond(kvm_x86_hwapic_isr_update)(vcpu, vec);
	else {
		++apic->isr_count;
		BUG_ON(apic->isr_count > MAX_APIC_VECTOR);
		/*
		 * ISR (in service register) bit is set when injecting an interrupt.
		 * The highest vector is injected. Thus the latest bit set matches
		 * the highest bit in ISR.
		 */
		apic->highest_isr_cache = vec;
	}
}


int kvm_hv_vapic_msr_read(struct kvm_vcpu *vcpu, u32 reg, u64 *data)
{
	if (!lapic_in_kernel(vcpu))
		return 1;

	return kvm_lapic_msr_read(vcpu->arch.apic, reg, data);
}


void kvm_lapic_exit(void)
{
	static_key_deferred_flush(&apic_hw_disabled);
	WARN_ON(static_branch_unlikely(&apic_hw_disabled.key));
	static_key_deferred_flush(&apic_sw_disabled);
	WARN_ON(static_branch_unlikely(&apic_sw_disabled.key));
}


static int kvm_lapic_msr_read(struct kvm_lapic *apic, u32 reg, u64 *data)
{
	u32 low;

	if (reg == APIC_ICR) {
		*data = kvm_lapic_get_reg64(apic, APIC_ICR);
		return 0;
	}

	if (kvm_lapic_reg_read(apic, reg, 4, &low))
		return 1;

	*data = low;

	return 0;
}


void kvm_lapic_set_tpr(struct kvm_vcpu *vcpu, unsigned long cr8)
{
	apic_set_tpr(vcpu->arch.apic, (cr8 & 0x0f) << 4);
}


static __always_inline void kvm_lapic_set_reg64(struct kvm_lapic *apic,
						int reg, u64 val)
{
	__kvm_lapic_set_reg64(apic->regs, reg, val);
}


static __always_inline u64 kvm_lapic_get_reg64(struct kvm_lapic *apic, int reg)
{
	return __kvm_lapic_get_reg64(apic->regs, reg);
}


int tcf_qevent_init(struct tcf_qevent *qe, struct Qdisc *sch,
		    enum flow_block_binder_type binder_type,
		    struct nlattr *block_index_attr,
		    struct netlink_ext_ack *extack)
{
	u32 block_index;
	int err;

	if (!block_index_attr)
		return 0;

	err = tcf_qevent_parse_block_index(block_index_attr, &block_index, extack);
	if (err)
		return err;

	if (!block_index)
		return 0;

	qe->info.binder_type = binder_type;
	qe->info.chain_head_change = tcf_chain_head_change_dflt;
	qe->info.chain_head_change_priv = &qe->filter_chain;
	qe->info.block_index = block_index;

	return tcf_block_get_ext(&qe->block, sch, &qe->info, extack);
}


unsigned int tcf_exts_num_actions(struct tcf_exts *exts)
{
	unsigned int num_acts = 0;
	struct tc_action *act;
	int i;

	tcf_exts_for_each_action(i, act, exts) {
		if (is_tcf_pedit(act))
			num_acts += tcf_pedit_nkeys(act);
		else
			num_acts++;
	}
	return num_acts;
}


static void tcf_block_refcnt_put(struct tcf_block *block, bool rtnl_held)
{
	__tcf_block_put(block, NULL, NULL, rtnl_held);
}


static struct tcf_proto *tcf_chain_tp_insert_unique(struct tcf_chain *chain,
						    struct tcf_proto *tp_new,
						    u32 protocol, u32 prio,
						    bool rtnl_held)
{
	struct tcf_chain_info chain_info;
	struct tcf_proto *tp;
	int err = 0;

	mutex_lock(&chain->filter_chain_lock);

	if (tcf_proto_exists_destroying(chain, tp_new)) {
		mutex_unlock(&chain->filter_chain_lock);
		tcf_proto_destroy(tp_new, rtnl_held, false, NULL);
		return ERR_PTR(-EAGAIN);
	}

	tp = tcf_chain_tp_find(chain, &chain_info,
			       protocol, prio, false);
	if (!tp)
		err = tcf_chain_tp_insert(chain, &chain_info, tp_new);
	mutex_unlock(&chain->filter_chain_lock);

	if (tp) {
		tcf_proto_destroy(tp_new, rtnl_held, false, NULL);
		tp_new = tp;
	} else if (err) {
		tcf_proto_destroy(tp_new, rtnl_held, false, NULL);
		tp_new = ERR_PTR(err);
	}

	return tp_new;
}


static void tcf_proto_put(struct tcf_proto *tp, bool rtnl_held,
			  struct netlink_ext_ack *extack)
{
	if (refcount_dec_and_test(&tp->refcnt))
		tcf_proto_destroy(tp, rtnl_held, true, extack);
}


static void __tcf_block_put(struct tcf_block *block, struct Qdisc *q,
			    struct tcf_block_ext_info *ei, bool rtnl_held)
{
	if (refcount_dec_and_mutex_lock(&block->refcnt, &block->lock)) {
		/* Flushing/putting all chains will cause the block to be
		 * deallocated when last chain is freed. However, if chain_list
		 * is empty, block has to be manually deallocated. After block
		 * reference counter reached 0, it is no longer possible to
		 * increment it or add new chains to block.
		 */
		bool free_block = list_empty(&block->chain_list);

		mutex_unlock(&block->lock);
		if (tcf_block_shared(block))
			tcf_block_remove(block, block->net);

		if (q)
			tcf_block_offload_unbind(block, q, ei);

		if (free_block)
			tcf_block_destroy(block);
		else
			tcf_block_flush_all_chains(block, rtnl_held);
	} else if (q) {
		tcf_block_offload_unbind(block, q, ei);
	}
}


int tcf_classify(struct sk_buff *skb,
		 const struct tcf_block *block,
		 const struct tcf_proto *tp,
		 struct tcf_result *res, bool compat_mode)
{
#if !IS_ENABLED(CONFIG_NET_TC_SKB_EXT)
	u32 last_executed_chain = 0;

	return __tcf_classify(skb, tp, tp, res, compat_mode,
			      &last_executed_chain);
#else
	u32 last_executed_chain = tp ? tp->chain->index : 0;
	const struct tcf_proto *orig_tp = tp;
	struct tc_skb_ext *ext;
	int ret;

	if (block) {
		ext = skb_ext_find(skb, TC_SKB_EXT);

		if (ext && ext->chain) {
			struct tcf_chain *fchain;

			fchain = tcf_chain_lookup_rcu(block, ext->chain);
			if (!fchain)
				return TC_ACT_SHOT;

			/* Consume, so cloned/redirect skbs won't inherit ext */
			skb_ext_del(skb, TC_SKB_EXT);

			tp = rcu_dereference_bh(fchain->filter_chain);
			last_executed_chain = fchain->index;
		}
	}

	ret = __tcf_classify(skb, tp, orig_tp, res, compat_mode,
			     &last_executed_chain);

	/* If we missed on some chain */
	if (ret == TC_ACT_UNSPEC && last_executed_chain) {
		struct tc_skb_cb *cb = tc_skb_cb(skb);

		ext = tc_skb_ext_alloc(skb);
		if (WARN_ON_ONCE(!ext))
			return TC_ACT_SHOT;
		ext->chain = last_executed_chain;
		ext->mru = cb->mru;
		ext->post_ct = cb->post_ct;
		ext->post_ct_snat = cb->post_ct_snat;
		ext->post_ct_dnat = cb->post_ct_dnat;
		ext->zone = cb->zone;
	}

	return ret;
#endif
}


int tc_setup_cb_add(struct tcf_block *block, struct tcf_proto *tp,
		    enum tc_setup_type type, void *type_data, bool err_stop,
		    u32 *flags, unsigned int *in_hw_count, bool rtnl_held)
{
	bool take_rtnl = READ_ONCE(block->lockeddevcnt) && !rtnl_held;
	int ok_count;

retry:
	if (take_rtnl)
		rtnl_lock();
	down_read(&block->cb_lock);
	/* Need to obtain rtnl lock if block is bound to devs that require it.
	 * In block bind code cb_lock is obtained while holding rtnl, so we must
	 * obtain the locks in same order here.
	 */
	if (!rtnl_held && !take_rtnl && block->lockeddevcnt) {
		up_read(&block->cb_lock);
		take_rtnl = true;
		goto retry;
	}

	/* Make sure all netdevs sharing this block are offload-capable. */
	if (block->nooffloaddevcnt && err_stop) {
		ok_count = -EOPNOTSUPP;
		goto err_unlock;
	}

	ok_count = __tc_setup_cb_call(block, type, type_data, err_stop);
	if (ok_count < 0)
		goto err_unlock;

	if (tp->ops->hw_add)
		tp->ops->hw_add(tp, type_data);
	if (ok_count > 0)
		tc_cls_offload_cnt_update(block, tp, in_hw_count, flags,
					  ok_count, true);
err_unlock:
	up_read(&block->cb_lock);
	if (take_rtnl)
		rtnl_unlock();
	return min(ok_count, 0);
}


void ax25_calculate_rtt(ax25_cb *ax25)
{
	if (ax25->backoff == 0)
		return;

	if (ax25_t1timer_running(ax25) && ax25->n2count == 0)
		ax25->rtt = (9 * ax25->rtt + ax25->t1 - ax25_display_timer(&ax25->t1timer)) / 10;

	if (ax25->rtt < AX25_T1CLAMPLO)
		ax25->rtt = AX25_T1CLAMPLO;

	if (ax25->rtt > AX25_T1CLAMPHI)
		ax25->rtt = AX25_T1CLAMPHI;
}


int ax25_decode(ax25_cb *ax25, struct sk_buff *skb, int *ns, int *nr, int *pf)
{
	unsigned char *frame;
	int frametype = AX25_ILLEGAL;

	frame = skb->data;
	*ns = *nr = *pf = 0;

	if (ax25->modulus == AX25_MODULUS) {
		if ((frame[0] & AX25_S) == 0) {
			frametype = AX25_I;			/* I frame - carries NR/NS/PF */
			*ns = (frame[0] >> 1) & 0x07;
			*nr = (frame[0] >> 5) & 0x07;
			*pf = frame[0] & AX25_PF;
		} else if ((frame[0] & AX25_U) == 1) { 	/* S frame - take out PF/NR */
			frametype = frame[0] & 0x0F;
			*nr = (frame[0] >> 5) & 0x07;
			*pf = frame[0] & AX25_PF;
		} else if ((frame[0] & AX25_U) == 3) { 	/* U frame - take out PF */
			frametype = frame[0] & ~AX25_PF;
			*pf = frame[0] & AX25_PF;
		}
		skb_pull(skb, 1);
	} else {
		if ((frame[0] & AX25_S) == 0) {
			frametype = AX25_I;			/* I frame - carries NR/NS/PF */
			*ns = (frame[0] >> 1) & 0x7F;
			*nr = (frame[1] >> 1) & 0x7F;
			*pf = frame[1] & AX25_EPF;
			skb_pull(skb, 2);
		} else if ((frame[0] & AX25_U) == 1) { 	/* S frame - take out PF/NR */
			frametype = frame[0] & 0x0F;
			*nr = (frame[1] >> 1) & 0x7F;
			*pf = frame[1] & AX25_EPF;
			skb_pull(skb, 2);
		} else if ((frame[0] & AX25_U) == 3) { 	/* U frame - take out PF */
			frametype = frame[0] & ~AX25_PF;
			*pf = frame[0] & AX25_PF;
			skb_pull(skb, 1);
		}
	}

	return frametype;
}


	__acquires(ax25_route_lock)
{
	struct ax25_route *ax25_rt;
	int i = 1;

	read_lock(&ax25_route_lock);
	if (*pos == 0)
		return SEQ_START_TOKEN;

	for (ax25_rt = ax25_route_list; ax25_rt != NULL; ax25_rt = ax25_rt->next) {
		if (i == *pos)
			return ax25_rt;
		++i;
	}

	return NULL;
}


static inline void ax25_unregister_dev_sysctl(ax25_dev *ax25_dev) {}


static void *ax25_rt_seq_next(struct seq_file *seq, void *v, loff_t *pos)
{
	++*pos;
	return (v == SEQ_START_TOKEN) ? ax25_route_list :
		((struct ax25_route *) v)->next;
}


zip_read_data_deflate(struct archive_read *a, const void **buff,
    size_t *size, int64_t *offset)
{
	struct zip *zip;
	ssize_t bytes_avail;
	const void *compressed_buff, *sp;
	int r;

	(void)offset; /* UNUSED */

	zip = (struct zip *)(a->format->data);

	/* If the buffer hasn't been allocated, allocate it now. */
	if (zip->uncompressed_buffer == NULL) {
		zip->uncompressed_buffer_size = 256 * 1024;
		zip->uncompressed_buffer
		    = (unsigned char *)malloc(zip->uncompressed_buffer_size);
		if (zip->uncompressed_buffer == NULL) {
			archive_set_error(&a->archive, ENOMEM,
			    "No memory for ZIP decompression");
			return (ARCHIVE_FATAL);
		}
	}

	r = zip_deflate_init(a, zip);
	if (r != ARCHIVE_OK)
		return (r);

	/*
	 * Note: '1' here is a performance optimization.
	 * Recall that the decompression layer returns a count of
	 * available bytes; asking for more than that forces the
	 * decompressor to combine reads by copying data.
	 */
	compressed_buff = sp = __archive_read_ahead(a, 1, &bytes_avail);
	if (0 == (zip->entry->zip_flags & ZIP_LENGTH_AT_END)
	    && bytes_avail > zip->entry_bytes_remaining) {
		bytes_avail = (ssize_t)zip->entry_bytes_remaining;
	}
	if (bytes_avail < 0) {
		archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
		    "Truncated ZIP file body");
		return (ARCHIVE_FATAL);
	}

	if (zip->tctx_valid || zip->cctx_valid) {
		if (zip->decrypted_bytes_remaining < (size_t)bytes_avail) {
			size_t buff_remaining =
			    (zip->decrypted_buffer +
			    zip->decrypted_buffer_size)
			    - (zip->decrypted_ptr +
			    zip->decrypted_bytes_remaining);

			if (buff_remaining > (size_t)bytes_avail)
				buff_remaining = (size_t)bytes_avail;

			if (0 == (zip->entry->zip_flags & ZIP_LENGTH_AT_END) &&
			      zip->entry_bytes_remaining > 0) {
				if ((int64_t)(zip->decrypted_bytes_remaining
				    + buff_remaining)
				      > zip->entry_bytes_remaining) {
					if (zip->entry_bytes_remaining <
					    (int64_t)zip->decrypted_bytes_remaining)
						buff_remaining = 0;
					else
						buff_remaining =
						    (size_t)zip->entry_bytes_remaining
						    - zip->decrypted_bytes_remaining;
				}
			}
			if (buff_remaining > 0) {
				if (zip->tctx_valid) {
					trad_enc_decrypt_update(&zip->tctx,
					    compressed_buff, buff_remaining,
					    zip->decrypted_ptr
					      + zip->decrypted_bytes_remaining,
					    buff_remaining);
				} else {
					size_t dsize = buff_remaining;
					archive_decrypto_aes_ctr_update(
					    &zip->cctx,
					    compressed_buff, buff_remaining,
					    zip->decrypted_ptr
					      + zip->decrypted_bytes_remaining,
					    &dsize);
				}
				zip->decrypted_bytes_remaining +=
				    buff_remaining;
			}
		}
		bytes_avail = zip->decrypted_bytes_remaining;
		compressed_buff = (const char *)zip->decrypted_ptr;
	}

	/*
	 * A bug in zlib.h: stream.next_in should be marked 'const'
	 * but isn't (the library never alters data through the
	 * next_in pointer, only reads it).  The result: this ugly
	 * cast to remove 'const'.
	 */
	zip->stream.next_in = (Bytef *)(uintptr_t)(const void *)compressed_buff;
	zip->stream.avail_in = (uInt)bytes_avail;
	zip->stream.total_in = 0;
	zip->stream.next_out = zip->uncompressed_buffer;
	zip->stream.avail_out = (uInt)zip->uncompressed_buffer_size;
	zip->stream.total_out = 0;

	r = inflate(&zip->stream, 0);
	switch (r) {
	case Z_OK:
		break;
	case Z_STREAM_END:
		zip->end_of_entry = 1;
		break;
	case Z_MEM_ERROR:
		archive_set_error(&a->archive, ENOMEM,
		    "Out of memory for ZIP decompression");
		return (ARCHIVE_FATAL);
	default:
		archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
		    "ZIP decompression failed (%d)", r);
		return (ARCHIVE_FATAL);
	}

	/* Consume as much as the compressor actually used. */
	bytes_avail = zip->stream.total_in;
	if (zip->tctx_valid || zip->cctx_valid) {
		zip->decrypted_bytes_remaining -= bytes_avail;
		if (zip->decrypted_bytes_remaining == 0)
			zip->decrypted_ptr = zip->decrypted_buffer;
		else
			zip->decrypted_ptr += bytes_avail;
	}
	/* Calculate compressed data as much as we used.*/
	if (zip->hctx_valid)
		archive_hmac_sha1_update(&zip->hctx, sp, bytes_avail);
	__archive_read_consume(a, bytes_avail);
	zip->entry_bytes_remaining -= bytes_avail;
	zip->entry_compressed_bytes_read += bytes_avail;

	*size = zip->stream.total_out;
	zip->entry_uncompressed_bytes_read += zip->stream.total_out;
	*buff = zip->uncompressed_buffer;

	if (zip->end_of_entry && zip->hctx_valid) {
		r = check_authentication_code(a, NULL);
		if (r != ARCHIVE_OK)
			return (r);
	}

	r = consume_optional_marker(a, zip);
	if (r != ARCHIVE_OK)
		return (r);

	return (ARCHIVE_OK);
}


slurp_central_directory(struct archive_read *a, struct archive_entry* entry,
    struct zip *zip)
{
	ssize_t i;
	unsigned found;
	int64_t correction;
	ssize_t bytes_avail;
	const char *p;

	/*
	 * Find the start of the central directory.  The end-of-CD
	 * record has our starting point, but there are lots of
	 * Zip archives which have had other data prepended to the
	 * file, which makes the recorded offsets all too small.
	 * So we search forward from the specified offset until we
	 * find the real start of the central directory.  Then we
	 * know the correction we need to apply to account for leading
	 * padding.
	 */
	if (__archive_read_seek(a, zip->central_directory_offset_adjusted, SEEK_SET)
		< 0)
		return ARCHIVE_FATAL;

	found = 0;
	while (!found) {
		if ((p = __archive_read_ahead(a, 20, &bytes_avail)) == NULL)
			return ARCHIVE_FATAL;
		for (found = 0, i = 0; !found && i < bytes_avail - 4;) {
			switch (p[i + 3]) {
			case 'P': i += 3; break;
			case 'K': i += 2; break;
			case 001: i += 1; break;
			case 002:
				if (memcmp(p + i, "PK\001\002", 4) == 0) {
					p += i;
					found = 1;
				} else
					i += 4;
				break;
			case 005: i += 1; break;
			case 006:
				if (memcmp(p + i, "PK\005\006", 4) == 0) {
					p += i;
					found = 1;
				} else if (memcmp(p + i, "PK\006\006", 4) == 0) {
					p += i;
					found = 1;
				} else
					i += 1;
				break;
			default: i += 4; break;
			}
		}
		__archive_read_consume(a, i);
	}
	correction = archive_filter_bytes(&a->archive, 0)
			- zip->central_directory_offset;

	__archive_rb_tree_init(&zip->tree, &rb_ops);
	__archive_rb_tree_init(&zip->tree_rsrc, &rb_rsrc_ops);

	zip->central_directory_entries_total = 0;
	while (1) {
		struct zip_entry *zip_entry;
		size_t filename_length, extra_length, comment_length;
		uint32_t external_attributes;
		const char *name, *r;

		if ((p = __archive_read_ahead(a, 4, NULL)) == NULL)
			return ARCHIVE_FATAL;
		if (memcmp(p, "PK\006\006", 4) == 0
		    || memcmp(p, "PK\005\006", 4) == 0) {
			break;
		} else if (memcmp(p, "PK\001\002", 4) != 0) {
			archive_set_error(&a->archive,
			    -1, "Invalid central directory signature");
			return ARCHIVE_FATAL;
		}
		if ((p = __archive_read_ahead(a, 46, NULL)) == NULL)
			return ARCHIVE_FATAL;

		zip_entry = calloc(1, sizeof(struct zip_entry));
		if (zip_entry == NULL) {
			archive_set_error(&a->archive, ENOMEM,
				"Can't allocate zip entry");
			return ARCHIVE_FATAL;
		}
		zip_entry->next = zip->zip_entries;
		zip_entry->flags |= LA_FROM_CENTRAL_DIRECTORY;
		zip->zip_entries = zip_entry;
		zip->central_directory_entries_total++;

		/* version = p[4]; */
		zip_entry->system = p[5];
		/* version_required = archive_le16dec(p + 6); */
		zip_entry->zip_flags = archive_le16dec(p + 8);
		if (zip_entry->zip_flags
		      & (ZIP_ENCRYPTED | ZIP_STRONG_ENCRYPTED)){
			zip->has_encrypted_entries = 1;
		}
		zip_entry->compression = (char)archive_le16dec(p + 10);
		zip_entry->mtime = zip_time(p + 12);
		zip_entry->crc32 = archive_le32dec(p + 16);
		if (zip_entry->zip_flags & ZIP_LENGTH_AT_END)
			zip_entry->decdat = p[13];
		else
			zip_entry->decdat = p[19];
		zip_entry->compressed_size = archive_le32dec(p + 20);
		zip_entry->uncompressed_size = archive_le32dec(p + 24);
		filename_length = archive_le16dec(p + 28);
		extra_length = archive_le16dec(p + 30);
		comment_length = archive_le16dec(p + 32);
		/* disk_start = archive_le16dec(p + 34);
		 *   Better be zero.
		 * internal_attributes = archive_le16dec(p + 36);
		 *   text bit */
		external_attributes = archive_le32dec(p + 38);
		zip_entry->local_header_offset =
		    archive_le32dec(p + 42) + correction;

		/* If we can't guess the mode, leave it zero here;
		   when we read the local file header we might get
		   more information. */
		if (zip_entry->system == 3) {
			zip_entry->mode = external_attributes >> 16;
		} else if (zip_entry->system == 0) {
			// Interpret MSDOS directory bit
			if (0x10 == (external_attributes & 0x10)) {
				zip_entry->mode = AE_IFDIR | 0775;
			} else {
				zip_entry->mode = AE_IFREG | 0664;
			}
			if (0x01 == (external_attributes & 0x01)) {
				// Read-only bit; strip write permissions
				zip_entry->mode &= 0555;
			}
		} else {
			zip_entry->mode = 0;
		}

		/* We're done with the regular data; get the filename and
		 * extra data. */
		__archive_read_consume(a, 46);
		p = __archive_read_ahead(a, filename_length + extra_length,
			NULL);
		if (p == NULL) {
			archive_set_error(&a->archive,
			    ARCHIVE_ERRNO_FILE_FORMAT,
			    "Truncated ZIP file header");
			return ARCHIVE_FATAL;
		}
		if (ARCHIVE_OK != process_extra(a, entry, p + filename_length,
		    extra_length, zip_entry)) {
			return ARCHIVE_FATAL;
		}

		/*
		 * Mac resource fork files are stored under the
		 * "__MACOSX/" directory, so we should check if
		 * it is.
		 */
		if (!zip->process_mac_extensions) {
			/* Treat every entry as a regular entry. */
			__archive_rb_tree_insert_node(&zip->tree,
			    &zip_entry->node);
		} else {
			name = p;
			r = rsrc_basename(name, filename_length);
			if (filename_length >= 9 &&
			    strncmp("__MACOSX/", name, 9) == 0) {
				/* If this file is not a resource fork nor
				 * a directory. We should treat it as a non
				 * resource fork file to expose it. */
				if (name[filename_length-1] != '/' &&
				    (r - name < 3 || r[0] != '.' ||
				     r[1] != '_')) {
					__archive_rb_tree_insert_node(
					    &zip->tree, &zip_entry->node);
					/* Expose its parent directories. */
					expose_parent_dirs(zip, name,
					    filename_length);
				} else {
					/* This file is a resource fork file or
					 * a directory. */
					archive_strncpy(&(zip_entry->rsrcname),
					     name, filename_length);
					__archive_rb_tree_insert_node(
					    &zip->tree_rsrc, &zip_entry->node);
				}
			} else {
				/* Generate resource fork name to find its
				 * resource file at zip->tree_rsrc. */
				archive_strcpy(&(zip_entry->rsrcname),
				    "__MACOSX/");
				archive_strncat(&(zip_entry->rsrcname),
				    name, r - name);
				archive_strcat(&(zip_entry->rsrcname), "._");
				archive_strncat(&(zip_entry->rsrcname),
				    name + (r - name),
				    filename_length - (r - name));
				/* Register an entry to RB tree to sort it by
				 * file offset. */
				__archive_rb_tree_insert_node(&zip->tree,
				    &zip_entry->node);
			}
		}

		/* Skip the comment too ... */
		__archive_read_consume(a,
		    filename_length + extra_length + comment_length);
	}

	return ARCHIVE_OK;
}


    Tfloat cubic_atX(const float fx, const int y, const int z, const int c, const T& out_value) const {
      const int
        x = (int)fx - (fx>=0?0:1), px = x - 1, nx = x + 1, ax = x + 2;
      const float
        dx = fx - x;
      const Tfloat
        Ip = (Tfloat)atX(px,y,z,c,out_value), Ic = (Tfloat)atX(x,y,z,c,out_value),
        In = (Tfloat)atX(nx,y,z,c,out_value), Ia = (Tfloat)atX(ax,y,z,c,out_value);
      return Ic + 0.5f*(dx*(-Ip + In) + dx*dx*(2*Ip - 5*Ic + 4*In - Ia) + dx*dx*dx*(-Ip + 3*Ic - 3*In + Ia));
    }


      static double mp_self_decrement(_cimg_math_parser& mp) {
        return --_mp_arg(1);
      }


      static double mp_erf(_cimg_math_parser& mp) {
        return std::erf(_mp_arg(2));
      }


    bool operator==(const t value) const {
      if (is_empty()) return false;
      typedef _cimg_Tt Tt;
      bool is_equal = true;
      for (T *ptrd = _data + size(); is_equal && ptrd>_data; is_equal = ((Tt)*(--ptrd)==(Tt)value)) {}
      return is_equal;
    }


    CImg<T> get_fill(const T& val0, const T& val1) const {
      return CImg<T>(_width,_height,_depth,_spectrum).fill(val0,val1);
    }


    static float _cimg_lanczos(const float x) {
      if (x<=-2 || x>=2) return 0;
      const float a = (float)cimg::PI*x, b = 0.5f*a;
      return (float)(x?std::sin(a)*std::sin(b)/(a*b):1);
    }


    CImg<floatT> get_object3dtoCImg3d(const bool full_check=true) const {
      CImgList<T> opacities, colors;
      CImgList<uintT> primitives(width(),1,1,1,1);
      cimglist_for(primitives,p) primitives(p,0) = p;
      return get_object3dtoCImg3d(primitives,colors,opacities,full_check);
    }


    const CImg<T> get_shared_points(const unsigned int x0, const unsigned int x1,
                                    const unsigned int y0=0, const unsigned int z0=0, const unsigned int c0=0) const {
      const ulongT
        beg = (ulongT)offset(x0,y0,z0,c0),
        end = (ulongT)offset(x1,y0,z0,c0);
      if (beg>end || beg>=size() || end>=size())
        throw CImgArgumentException(_cimg_instance
                                    "get_shared_points(): Invalid request of a shared-memory subset (%u->%u,%u,%u,%u).",
                                    cimg_instance,
                                    x0,x1,y0,z0,c0);
      return CImg<T>(_data + beg,x1 - x0 + 1,1,1,1,true);
    }


      static bool is_finite(const half val) {
#ifdef isfinite
        return (bool)isfinite(val);
#else
        return !is_nan(val) && !is_inf(val);
#endif
      }


    Tfloat _linear_atXY(const float fx, const float fy, const int z=0, const int c=0) const {
      const float
        nfx = cimg::cut(fx,0,width() - 1),
        nfy = cimg::cut(fy,0,height() - 1);
      const unsigned int
        x = (unsigned int)nfx,
        y = (unsigned int)nfy;
      const float
        dx = nfx - x,
        dy = nfy - y;
      const unsigned int
        nx = dx>0?x + 1:x,
        ny = dy>0?y + 1:y;
      const Tfloat
        Icc = (Tfloat)(*this)(x,y,z,c),  Inc = (Tfloat)(*this)(nx,y,z,c),
        Icn = (Tfloat)(*this)(x,ny,z,c), Inn = (Tfloat)(*this)(nx,ny,z,c);
      return Icc + (Inc - Icc + (Icc + Inn - Icn - Inc)*dy)*dx + (Icn - Icc)*dy;
    }


    }

    template<typename t>
    inline CImg<typename cimg::superset<double,t>::type> eval(const char *const expression, const CImg<t>& xyzc) {


    CImgList<T> get_split(const char axis, const int nb=-1) const {
      CImgList<T> res;
      if (is_empty()) return res;
      const char _axis = cimg::lowercase(axis);

      if (nb<0) { // Split by bloc size
        const unsigned int dp = (unsigned int)(nb?-nb:1);
        switch (_axis) {
        case 'x': {
          if (_width>dp) {
            res.assign(_width/dp + (_width%dp?1:0),1,1);
            const unsigned int pe = _width - dp;
            cimg_pragma_openmp(parallel for cimg_openmp_if(res._width>=(cimg_openmp_sizefactor)*128 &&
                                                           _height*_depth*_spectrum>=128))
            for (int p = 0; p<(int)pe; p+=dp)
              get_crop(p,0,0,0,p + dp - 1,_height - 1,_depth - 1,_spectrum - 1).move_to(res[p/dp]);
            get_crop((res._width - 1)*dp,0,0,0,_width - 1,_height - 1,_depth - 1,_spectrum - 1).move_to(res.back());
          } else res.assign(*this);
        } break;
        case 'y': {
          if (_height>dp) {
            res.assign(_height/dp + (_height%dp?1:0),1,1);
            const unsigned int pe = _height - dp;
            cimg_pragma_openmp(parallel for cimg_openmp_if(res._width>=(cimg_openmp_sizefactor)*128 &&
                                                           _width*_depth*_spectrum>=128))
            for (int p = 0; p<(int)pe; p+=dp)
              get_crop(0,p,0,0,_width - 1,p + dp - 1,_depth - 1,_spectrum - 1).move_to(res[p/dp]);
            get_crop(0,(res._width - 1)*dp,0,0,_width - 1,_height - 1,_depth - 1,_spectrum - 1).move_to(res.back());
          } else res.assign(*this);
        } break;
        case 'z': {
          if (_depth>dp) {
            res.assign(_depth/dp + (_depth%dp?1:0),1,1);
            const unsigned int pe = _depth - dp;
            cimg_pragma_openmp(parallel for cimg_openmp_if(res._width>=(cimg_openmp_sizefactor)*128 &&
                                                           _width*_height*_spectrum>=128))
            for (int p = 0; p<(int)pe; p+=dp)
              get_crop(0,0,p,0,_width - 1,_height - 1,p + dp - 1,_spectrum - 1).move_to(res[p/dp]);
            get_crop(0,0,(res._width - 1)*dp,0,_width - 1,_height - 1,_depth - 1,_spectrum - 1).move_to(res.back());
          } else res.assign(*this);
        } break;
        case 'c' : {
          if (_spectrum>dp) {
            res.assign(_spectrum/dp + (_spectrum%dp?1:0),1,1);
            const unsigned int pe = _spectrum - dp;
            cimg_pragma_openmp(parallel for cimg_openmp_if(res._width>=(cimg_openmp_sizefactor)*128 &&
                                                           _width*_height*_depth>=128))
            for (int p = 0; p<(int)pe; p+=dp)
              get_crop(0,0,0,p,_width - 1,_height - 1,_depth - 1,p + dp - 1).move_to(res[p/dp]);
            get_crop(0,0,0,(res._width - 1)*dp,_width - 1,_height - 1,_depth - 1,_spectrum - 1).move_to(res.back());
          } else res.assign(*this);
        }
        }
      } else if (nb>0) { // Split by number of (non-homogeneous) blocs
        const unsigned int siz = _axis=='x'?_width:_axis=='y'?_height:_axis=='z'?_depth:_axis=='c'?_spectrum:0;
        if ((unsigned int)nb>siz)
          throw CImgArgumentException(_cimg_instance
                                      "get_split(): Instance cannot be split along %c-axis into %u blocs.",
                                      cimg_instance,
                                      axis,nb);
        if (nb==1) res.assign(*this);
        else {
          int err = (int)siz;
          unsigned int _p = 0;
          switch (_axis) {
          case 'x' : {
            cimg_forX(*this,p) if ((err-=nb)<=0) {
              get_crop(_p,0,0,0,p,_height - 1,_depth - 1,_spectrum - 1).move_to(res);
              err+=(int)siz;
              _p = p + 1U;
            }
          } break;
          case 'y' : {
            cimg_forY(*this,p) if ((err-=nb)<=0) {
              get_crop(0,_p,0,0,_width - 1,p,_depth - 1,_spectrum - 1).move_to(res);
              err+=(int)siz;
              _p = p + 1U;
            }
          } break;
          case 'z' : {
            cimg_forZ(*this,p) if ((err-=nb)<=0) {
              get_crop(0,0,_p,0,_width - 1,_height - 1,p,_spectrum - 1).move_to(res);
              err+=(int)siz;
              _p = p + 1U;
            }
          } break;
          case 'c' : {
            cimg_forC(*this,p) if ((err-=nb)<=0) {
              get_crop(0,0,0,_p,_width - 1,_height - 1,_depth - 1,p).move_to(res);
              err+=(int)siz;
              _p = p + 1U;
            }
          }
          }
        }
      } else { // Split by equal values according to specified axis
        T current = *_data;
        switch (_axis) {
        case 'x' : {
          int i0 = 0;
          cimg_forX(*this,i)
            if ((*this)(i)!=current) { get_columns(i0,i - 1).move_to(res); i0 = i; current = (*this)(i); }
          get_columns(i0,width() - 1).move_to(res);
        } break;
        case 'y' : {
          int i0 = 0;
          cimg_forY(*this,i)
            if ((*this)(0,i)!=current) { get_rows(i0,i - 1).move_to(res); i0 = i; current = (*this)(0,i); }
          get_rows(i0,height() - 1).move_to(res);
        } break;
        case 'z' : {
          int i0 = 0;
          cimg_forZ(*this,i)
            if ((*this)(0,0,i)!=current) { get_slices(i0,i - 1).move_to(res); i0 = i; current = (*this)(0,0,i); }
          get_slices(i0,depth() - 1).move_to(res);
        } break;
        case 'c' : {
          int i0 = 0;
          cimg_forC(*this,i)
            if ((*this)(0,0,0,i)!=current) { get_channels(i0,i - 1).move_to(res); i0 = i; current = (*this)(0,0,0,i); }
          get_channels(i0,spectrum() - 1).move_to(res);
        } break;
        default : {
          longT i0 = 0;
          cimg_foroff(*this,i)
            if ((*this)[i]!=current) {
              CImg<T>(_data + i0,1,(unsigned int)(i - i0)).move_to(res);
              i0 = (longT)i; current = (*this)[i];
            }
          CImg<T>(_data + i0,1,(unsigned int)(size() - i0)).move_to(res);
        }
        }
      }
      return res;
    }


    CImg<Tuchar> get_CMYKtoRGB() const {
      return CImg<Tuchar>(*this,false).CMYKtoRGB();
    }


        \param is_shared Tells if the inserted image is a shared copy of \c img or not.
    **/
    template<typename t>
    CImgList<T>& insert(const CImg<t>& img, const unsigned int pos=~0U, const bool is_shared=false) {
      const unsigned int npos = pos==~0U?_width:pos;
      if (npos>_width)
        throw CImgArgumentException(_cimglist_instance
                                    "insert(): Invalid insertion request of specified image (%u,%u,%u,%u,%p) "
                                    "at position %u.",
                                    cimglist_instance,
                                    img._width,img._height,img._depth,img._spectrum,img._data,npos);
      if (is_shared)
        throw CImgArgumentException(_cimglist_instance
                                    "insert(): Invalid insertion request of specified shared image "
                                    "CImg<%s>(%u,%u,%u,%u,%p) at position %u (pixel types are different).",
                                    cimglist_instance,
                                    img.pixel_type(),img._width,img._height,img._depth,img._spectrum,img._data,npos);

      CImg<T> *const new_data = (++_width>_allocated_width)?new CImg<T>[_allocated_width?(_allocated_width<<=1):
                                                                        (_allocated_width=16)]:0;
      if (!_data) { // Insert new element into empty list
        _data = new_data;
        *_data = img;
      } else {
        if (new_data) { // Insert with re-allocation
          if (npos) std::memcpy((void*)new_data,(void*)_data,sizeof(CImg<T>)*npos);
          if (npos!=_width - 1)
            std::memcpy((void*)(new_data + npos + 1),(void*)(_data + npos),sizeof(CImg<T>)*(_width - 1 - npos));
          std::memset((void*)_data,0,sizeof(CImg<T>)*(_width - 1));
          delete[] _data;
          _data = new_data;
        } else if (npos!=_width - 1) // Insert without re-allocation
          std::memmove((void*)(_data + npos + 1),(void*)(_data + npos),sizeof(CImg<T>)*(_width - 1 - npos));
        _data[npos]._width = _data[npos]._height = _data[npos]._depth = _data[npos]._spectrum = 0;
        _data[npos]._data = 0;
        _data[npos] = img;


    static CImg<T> get_load_yuv(std::FILE *const file,
                                const unsigned int size_x, const unsigned int size_y=1,
                                const unsigned int chroma_subsampling=444,
                                const unsigned int first_frame=0, const unsigned int last_frame=~0U,
                                const unsigned int step_frame=1, const bool yuv2rgb=true, const char axis='z') {
      return CImgList<T>().load_yuv(file,size_x,size_y,chroma_subsampling,
                                    first_frame,last_frame,step_frame,yuv2rgb).get_append(axis);
    }


    static CImg<T> get_load_parrec(const char *const filename, const char axis='c', const float align=0) {
      return CImg<T>().load_parrec(filename,axis,align);
    }


    inline void lowercase(char *const str) {
      if (str) for (char *ptr = str; *ptr; ++ptr) *ptr = lowercase(*ptr);
    }


      static double mp_matrix_invert(_cimg_math_parser& mp) {
        double *const ptrd = &_mp_arg(1) + 1;
        const double *const ptr1 = &_mp_arg(2) + 1;
        const unsigned int k = (unsigned int)mp.opcode[3];
        const bool use_LU = (bool)_mp_arg(4);
        CImg<doubleT>(ptrd,k,k,1,1,true) = CImg<doubleT>(ptr1,k,k,1,1,true).get_invert(use_LU);
        return cimg::type<double>::nan();
      }


    explicit CImg(const unsigned int size_x, const unsigned int size_y=1,
                  const unsigned int size_z=1, const unsigned int size_c=1):
      _is_shared(false) {
      const size_t siz = safe_size(size_x,size_y,size_z,size_c);
      if (siz) {
        _width = size_x; _height = size_y; _depth = size_z; _spectrum = size_c;
        try { _data = new T[siz]; } catch (...) {
          _width = _height = _depth = _spectrum = 0; _data = 0;
          throw CImgInstanceException(_cimg_instance
                                      "CImg(): Failed to allocate memory (%s) for image (%u,%u,%u,%u).",
                                      cimg_instance,
                                      cimg::strbuffersize(sizeof(T)*size_x*size_y*size_z*size_c),
                                      size_x,size_y,size_z,size_c);
        }
      } else { _width = _height = _depth = _spectrum = 0; _data = 0; }
    }


      float operator()(const float x, const float y, const float z, const unsigned int c) const {
        return (float)ref((int)x,(int)y,(int)z,c);
      }


    CImg<T>& div(const CImg<t>& img) {
      const ulongT siz = size(), isiz = img.size();
      if (siz && isiz) {
        if (is_overlapped(img)) return div(+img);
        T *ptrd = _data, *const ptre = _data + siz;
        if (siz>isiz) for (ulongT n = siz/isiz; n; --n)
          for (const t *ptrs = img._data, *ptrs_end = ptrs + isiz; ptrs<ptrs_end; ++ptrd)
            *ptrd = (T)(*ptrd / *(ptrs++));
        for (const t *ptrs = img._data; ptrd<ptre; ++ptrd) *ptrd = (T)(*ptrd / *(ptrs++));
      }
      return *this;
    }


    const CImg<T>& operator()(const unsigned int pos) const {
      return const_cast<CImgList<T>*>(this)->operator()(pos);
    }


    static float ___draw_object3d(const CImg<t>& opacities, const unsigned int n_primitive) {
      return n_primitive<opacities._width?(float)opacities[n_primitive]:1.f;
    }


    CImg<T>& cut(const T& min_value, const T& max_value) {
      if (is_empty()) return *this;
      const T a = min_value<max_value?min_value:max_value, b = min_value<max_value?max_value:min_value;
      cimg_openmp_for(*this,cimg::cut(*ptr,a,b),32768);
      return *this;
    }


    CImg<T>& draw_ellipse(const int x0, const int y0, const CImg<t> &tensor,
                          const tc *const color, const float opacity=1) {
      CImgList<t> eig = tensor.get_symmetric_eigen();
      const CImg<t> &val = eig[0], &vec = eig[1];
      return draw_ellipse(x0,y0,std::sqrt(val(0)),std::sqrt(val(1)),
                          std::atan2(vec(0,1),vec(0,0))*180/cimg::PI,
                          color,opacity);
    }


    CImg<T>& mirror(const char *const axes) {
      for (const char *s = axes; *s; ++s) mirror(*s);
      return *this;
    }


      static double mp_debug(_cimg_math_parser& mp) {
        CImg<charT> expr(mp.opcode[2] - 4);
        {
          const ulongT *ptrs = mp.opcode._data + 4;
          cimg_for(expr,ptrd,char) *ptrd = (char)*(ptrs++);
        }
        cimg::strellipsize(expr);
        const ulongT g_target = mp.opcode[1];

#if cimg_use_openmp==0
        const unsigned int n_thread = 0;
#else
        const unsigned int n_thread = omp_get_thread_num();
#endif
        cimg_pragma_openmp(critical(mp_debug))
        {
          std::fprintf(cimg::output(),
                       "\n[" cimg_appname "_math_parser] %p[thread #%u]:%*c"
                       "Start debugging expression '%s', code length %u -> mem[%u] (memsize: %u)",
                       (void*)&mp,n_thread,mp.debug_indent,' ',
                       expr._data,(unsigned int)mp.opcode[3],(unsigned int)g_target,mp.mem._width);
          std::fflush(cimg::output());
          mp.debug_indent+=3;
        }
        const CImg<ulongT> *const p_end = ++mp.p_code + mp.opcode[3];
        CImg<ulongT> _op;
        for ( ; mp.p_code<p_end; ++mp.p_code) {
          const CImg<ulongT> &op = *mp.p_code;
          mp.opcode._data = op._data;

          _op.assign(1,op._height - 1);
          const ulongT *ptrs = op._data + 1;
          for (ulongT *ptrd = _op._data, *const ptrde = _op._data + _op._height; ptrd<ptrde; ++ptrd)
            *ptrd = *(ptrs++);

          const ulongT target = mp.opcode[1];
          mp.mem[target] = _cimg_mp_defunc(mp);
          cimg_pragma_openmp(critical(mp_debug))
          {
            std::fprintf(cimg::output(),
                         "\n[" cimg_appname "_math_parser] %p[thread #%u]:%*c"
                         "Opcode %p = [ %p,%s ] -> mem[%u] = %.17g",
                         (void*)&mp,n_thread,mp.debug_indent,' ',
                         (void*)mp.opcode._data,(void*)*mp.opcode,_op.value_string().data(),
                         (unsigned int)target,mp.mem[target]);
            std::fflush(cimg::output());
          }
        }
        cimg_pragma_openmp(critical(mp_debug))
        {
          mp.debug_indent-=3;
          std::fprintf(cimg::output(),
            "\n[" cimg_appname "_math_parser] %p[thread #%u]:%*c"
            "End debugging expression '%s' -> mem[%u] = %.17g (memsize: %u)",
            (void*)&mp,n_thread,mp.debug_indent,' ',
            expr._data,(unsigned int)g_target,mp.mem[g_target],mp.mem._width);
          std::fflush(cimg::output());
        }
        --mp.p_code;
        return mp.mem[g_target];
      }