Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Linux/drivers/net/ethernet/netronome/nfp/   (Open Source Betriebssystem Version 6.17.9©)  Datei vom 24.10.2025 mit Größe 4 kB image not shown  

Quelle  ccm.c   Sprache: C

 
// SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
/* Copyright (C) 2016-2019 Netronome Systems, Inc. */

#include <linux/bitops.h>

#include "ccm.h"
#include "nfp_app.h"
#include "nfp_net.h"

#define ccm_warn(app, msg...) nn_dp_warn(&(app)->ctrl->dp, msg)

#define NFP_CCM_TAG_ALLOC_SPAN (U16_MAX / 4)

static bool nfp_ccm_all_tags_busy(struct nfp_ccm *ccm)
{
 u16 used_tags;

 used_tags = ccm->tag_alloc_next - ccm->tag_alloc_last;

 return used_tags > NFP_CCM_TAG_ALLOC_SPAN;
}

static int nfp_ccm_alloc_tag(struct nfp_ccm *ccm)
{
 /* CCM is for FW communication which is request-reply.  To make sure
 * we don't reuse the message ID too early after timeout - limit the
 * number of requests in flight.
 */

 if (unlikely(nfp_ccm_all_tags_busy(ccm))) {
  ccm_warn(ccm->app, "all FW request contexts busy!\n");
  return -EAGAIN;
 }

 WARN_ON(__test_and_set_bit(ccm->tag_alloc_next, ccm->tag_allocator));
 return ccm->tag_alloc_next++;
}

static void nfp_ccm_free_tag(struct nfp_ccm *ccm, u16 tag)
{
 WARN_ON(!__test_and_clear_bit(tag, ccm->tag_allocator));

 while (!test_bit(ccm->tag_alloc_last, ccm->tag_allocator) &&
        ccm->tag_alloc_last != ccm->tag_alloc_next)
  ccm->tag_alloc_last++;
}

static struct sk_buff *__nfp_ccm_reply(struct nfp_ccm *ccm, u16 tag)
{
 unsigned int msg_tag;
 struct sk_buff *skb;

 skb_queue_walk(&ccm->replies, skb) {
  msg_tag = nfp_ccm_get_tag(skb);
  if (msg_tag == tag) {
   nfp_ccm_free_tag(ccm, tag);
   __skb_unlink(skb, &ccm->replies);
   return skb;
  }
 }

 return NULL;
}

static struct sk_buff *
nfp_ccm_reply(struct nfp_ccm *ccm, struct nfp_app *app, u16 tag)
{
 struct sk_buff *skb;

 nfp_ctrl_lock(app->ctrl);
 skb = __nfp_ccm_reply(ccm, tag);
 nfp_ctrl_unlock(app->ctrl);

 return skb;
}

static struct sk_buff *
nfp_ccm_reply_drop_tag(struct nfp_ccm *ccm, struct nfp_app *app, u16 tag)
{
 struct sk_buff *skb;

 nfp_ctrl_lock(app->ctrl);
 skb = __nfp_ccm_reply(ccm, tag);
 if (!skb)
  nfp_ccm_free_tag(ccm, tag);
 nfp_ctrl_unlock(app->ctrl);

 return skb;
}

static struct sk_buff *
nfp_ccm_wait_reply(struct nfp_ccm *ccm, struct nfp_app *app,
     enum nfp_ccm_type type, int tag)
{
 struct sk_buff *skb;
 int i, err;

 for (i = 0; i < 50; i++) {
  udelay(4);
  skb = nfp_ccm_reply(ccm, app, tag);
  if (skb)
   return skb;
 }

 err = wait_event_interruptible_timeout(ccm->wq,
            skb = nfp_ccm_reply(ccm, app,
           tag),
            msecs_to_jiffies(5000));
 /* We didn't get a response - try last time and atomically drop
 * the tag even if no response is matched.
 */

 if (!skb)
  skb = nfp_ccm_reply_drop_tag(ccm, app, tag);
 if (err < 0) {
  ccm_warn(app, "%s waiting for response to 0x%02x: %d\n",
    err == ERESTARTSYS ? "interrupted" : "error",
    type, err);
  return ERR_PTR(err);
 }
 if (!skb) {
  ccm_warn(app, "timeout waiting for response to 0x%02x\n", type);
  return ERR_PTR(-ETIMEDOUT);
 }

 return skb;
}

struct sk_buff *
nfp_ccm_communicate(struct nfp_ccm *ccm, struct sk_buff *skb,
      enum nfp_ccm_type type, unsigned int reply_size)
{
 struct nfp_app *app = ccm->app;
 struct nfp_ccm_hdr *hdr;
 int reply_type, tag;

 nfp_ctrl_lock(app->ctrl);
 tag = nfp_ccm_alloc_tag(ccm);
 if (tag < 0) {
  nfp_ctrl_unlock(app->ctrl);
  dev_kfree_skb_any(skb);
  return ERR_PTR(tag);
 }

 hdr = (void *)skb->data;
 hdr->ver = NFP_CCM_ABI_VERSION;
 hdr->type = type;
 hdr->tag = cpu_to_be16(tag);

 __nfp_app_ctrl_tx(app, skb);

 nfp_ctrl_unlock(app->ctrl);

 skb = nfp_ccm_wait_reply(ccm, app, type, tag);
 if (IS_ERR(skb))
  return skb;

 reply_type = nfp_ccm_get_type(skb);
 if (reply_type != __NFP_CCM_REPLY(type)) {
  ccm_warn(app, "cmsg drop - wrong type 0x%02x != 0x%02lx!\n",
    reply_type, __NFP_CCM_REPLY(type));
  goto err_free;
 }
 /* 0 reply_size means caller will do the validation */
 if (reply_size && skb->len != reply_size) {
  ccm_warn(app, "cmsg drop - type 0x%02x wrong size %d != %d!\n",
    type, skb->len, reply_size);
  goto err_free;
 }

 return skb;
err_free:
 dev_kfree_skb_any(skb);
 return ERR_PTR(-EIO);
}

void nfp_ccm_rx(struct nfp_ccm *ccm, struct sk_buff *skb)
{
 struct nfp_app *app = ccm->app;
 unsigned int tag;

 if (unlikely(skb->len < sizeof(struct nfp_ccm_hdr))) {
  ccm_warn(app, "cmsg drop - too short %d!\n", skb->len);
  goto err_free;
 }

 nfp_ctrl_lock(app->ctrl);

 tag = nfp_ccm_get_tag(skb);
 if (unlikely(!test_bit(tag, ccm->tag_allocator))) {
  ccm_warn(app, "cmsg drop - no one is waiting for tag %u!\n",
    tag);
  goto err_unlock;
 }

 __skb_queue_tail(&ccm->replies, skb);
 wake_up_interruptible_all(&ccm->wq);

 nfp_ctrl_unlock(app->ctrl);
 return;

err_unlock:
 nfp_ctrl_unlock(app->ctrl);
err_free:
 dev_kfree_skb_any(skb);
}

int nfp_ccm_init(struct nfp_ccm *ccm, struct nfp_app *app)
{
 ccm->app = app;
 skb_queue_head_init(&ccm->replies);
 init_waitqueue_head(&ccm->wq);
 return 0;
}

void nfp_ccm_clean(struct nfp_ccm *ccm)
{
 WARN_ON(!skb_queue_empty(&ccm->replies));
}

Messung V0.5
C=94 H=96 G=94

¤ Dauer der Verarbeitung: 0.11 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.