summaryrefslogtreecommitdiffstats
path: root/linux/drivers/soc/fsl/qbman/bman.c
diff options
context:
space:
mode:
authorSebastian Huber <sebastian.huber@embedded-brains.de>2017-05-05 08:47:39 +0200
committerSebastian Huber <sebastian.huber@embedded-brains.de>2017-10-23 09:23:59 +0200
commitcd089b9e05aad31244059ba88988afbe1db02e5e (patch)
tree81d344bb292ff39e60f74ac4df5f1621eca77c05 /linux/drivers/soc/fsl/qbman/bman.c
parentImport DPAA driver snapshot (diff)
downloadrtems-libbsd-cd089b9e05aad31244059ba88988afbe1db02e5e.tar.bz2
Linux update to 4.11-rc5
Linux baseline a71c9a1c779f2499fb2afc0553e543f18aff6edf (4.11-rc5).
Diffstat (limited to 'linux/drivers/soc/fsl/qbman/bman.c')
-rw-r--r--linux/drivers/soc/fsl/qbman/bman.c1191
1 files changed, 654 insertions, 537 deletions
diff --git a/linux/drivers/soc/fsl/qbman/bman.c b/linux/drivers/soc/fsl/qbman/bman.c
index 35459bc7..2cc7f5c5 100644
--- a/linux/drivers/soc/fsl/qbman/bman.c
+++ b/linux/drivers/soc/fsl/qbman/bman.c
@@ -2,7 +2,7 @@
#include <rtems/bsd/local/opt_dpaa.h>
-/* Copyright (c) 2009 - 2015 Freescale Semiconductor, Inc.
+/* Copyright 2008 - 2016 Freescale Semiconductor, Inc.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
@@ -34,659 +34,776 @@
#include "bman_priv.h"
-/* Last updated for v00.79 of the BG */
-
-struct bman;
-
-/* Register offsets */
-#define REG_POOL_SWDET(n) (0x0000 + ((n) * 0x04))
-#define REG_POOL_HWDET(n) (0x0100 + ((n) * 0x04))
-#define REG_POOL_SWDXT(n) (0x0200 + ((n) * 0x04))
-#define REG_POOL_HWDXT(n) (0x0300 + ((n) * 0x04))
-#define REG_POOL_CONTENT(n) (0x0600 + ((n) * 0x04))
-#define REG_FBPR_FPC 0x0800
-#define REG_ECSR 0x0a00
-#define REG_ECIR 0x0a04
-#define REG_EADR 0x0a08
-#define REG_EDATA(n) (0x0a10 + ((n) * 0x04))
-#define REG_SBEC(n) (0x0a80 + ((n) * 0x04))
-#define REG_IP_REV_1 0x0bf8
-#define REG_IP_REV_2 0x0bfc
-#define REG_FBPR_BARE 0x0c00
-#define REG_FBPR_BAR 0x0c04
-#define REG_FBPR_AR 0x0c10
-#define REG_SRCIDR 0x0d04
-#define REG_LIODNR 0x0d08
-#define REG_ERR_ISR 0x0e00 /* + "enum bm_isr_reg" */
-
-/* Used by all error interrupt registers except 'inhibit' */
-#define BM_EIRQ_IVCI 0x00000010 /* Invalid Command Verb */
-#define BM_EIRQ_FLWI 0x00000008 /* FBPR Low Watermark */
-#define BM_EIRQ_MBEI 0x00000004 /* Multi-bit ECC Error */
-#define BM_EIRQ_SBEI 0x00000002 /* Single-bit ECC Error */
-#define BM_EIRQ_BSCN 0x00000001 /* pool State Change Notification */
-
-/* BMAN_ECIR valid error bit */
-#define PORTAL_ECSR_ERR (BM_EIRQ_IVCI)
-
-union bman_ecir {
- u32 ecir_raw;
- struct {
- u32 __reserved1:4;
- u32 portal_num:4;
- u32 __reserved2:12;
- u32 numb:4;
- u32 __reserved3:2;
- u32 pid:6;
- } __packed info;
-};
+#define IRQNAME "BMan portal %d"
+#define MAX_IRQNAME 16 /* big enough for "BMan portal %d" */
+
+/* Portal register assists */
+
+/* Cache-inhibited register offsets */
+#define BM_REG_RCR_PI_CINH 0x0000
+#define BM_REG_RCR_CI_CINH 0x0004
+#define BM_REG_RCR_ITR 0x0008
+#define BM_REG_CFG 0x0100
+#define BM_REG_SCN(n) (0x0200 + ((n) << 2))
+#define BM_REG_ISR 0x0e00
+#define BM_REG_IER 0x0e04
+#define BM_REG_ISDR 0x0e08
+#define BM_REG_IIR 0x0e0c
+
+/* Cache-enabled register offsets */
+#define BM_CL_CR 0x0000
+#define BM_CL_RR0 0x0100
+#define BM_CL_RR1 0x0140
+#define BM_CL_RCR 0x1000
+#define BM_CL_RCR_PI_CENA 0x3000
+#define BM_CL_RCR_CI_CENA 0x3100
-union bman_eadr {
- u32 eadr_raw;
- struct {
- u32 __reserved1:5;
- u32 memid:3;
- u32 __reserved2:14;
- u32 eadr:10;
- } __packed info;
+/*
+ * Portal modes.
+ * Enum types;
+ * pmode == production mode
+ * cmode == consumption mode,
+ * Enum values use 3 letter codes. First letter matches the portal mode,
+ * remaining two letters indicate;
+ * ci == cache-inhibited portal register
+ * ce == cache-enabled portal register
+ * vb == in-band valid-bit (cache-enabled)
+ */
+enum bm_rcr_pmode { /* matches BCSP_CFG::RPM */
+ bm_rcr_pci = 0, /* PI index, cache-inhibited */
+ bm_rcr_pce = 1, /* PI index, cache-enabled */
+ bm_rcr_pvb = 2 /* valid-bit */
};
-
-struct bman_hwerr_txt {
- u32 mask;
- const char *txt;
+enum bm_rcr_cmode { /* s/w-only */
+ bm_rcr_cci, /* CI index, cache-inhibited */
+ bm_rcr_cce /* CI index, cache-enabled */
};
-#define BMAN_HWE_TXT(a, b) { .mask = BM_EIRQ_##a, .txt = b }
-static const struct bman_hwerr_txt bman_hwerr_txts[] = {
- BMAN_HWE_TXT(IVCI, "Invalid Command Verb"),
- BMAN_HWE_TXT(FLWI, "FBPR Low Watermark"),
- BMAN_HWE_TXT(MBEI, "Multi-bit ECC Error"),
- BMAN_HWE_TXT(SBEI, "Single-bit ECC Error"),
- BMAN_HWE_TXT(BSCN, "Pool State Change Notification"),
+/* --- Portal structures --- */
+
+#define BM_RCR_SIZE 8
+
+/* Release Command */
+struct bm_rcr_entry {
+ union {
+ struct {
+ u8 _ncw_verb; /* writes to this are non-coherent */
+ u8 bpid; /* used with BM_RCR_VERB_CMD_BPID_SINGLE */
+ u8 __reserved1[62];
+ };
+ struct bm_buffer bufs[8];
+ };
+};
+#define BM_RCR_VERB_VBIT 0x80
+#define BM_RCR_VERB_CMD_MASK 0x70 /* one of two values; */
+#define BM_RCR_VERB_CMD_BPID_SINGLE 0x20
+#define BM_RCR_VERB_CMD_BPID_MULTI 0x30
+#define BM_RCR_VERB_BUFCOUNT_MASK 0x0f /* values 1..8 */
+
+struct bm_rcr {
+ struct bm_rcr_entry *ring, *cursor;
+ u8 ci, available, ithresh, vbit;
+#ifdef CONFIG_FSL_DPAA_CHECKING
+ u32 busy;
+ enum bm_rcr_pmode pmode;
+ enum bm_rcr_cmode cmode;
+#endif
};
-#define BMAN_HWE_COUNT (sizeof(bman_hwerr_txts)/sizeof(struct bman_hwerr_txt))
-struct bman_error_info_mdata {
- u16 addr_mask;
- u16 bits;
- const char *txt;
+/* MC (Management Command) command */
+struct bm_mc_command {
+ u8 _ncw_verb; /* writes to this are non-coherent */
+ u8 bpid; /* used by acquire command */
+ u8 __reserved[62];
+};
+#define BM_MCC_VERB_VBIT 0x80
+#define BM_MCC_VERB_CMD_MASK 0x70 /* where the verb contains; */
+#define BM_MCC_VERB_CMD_ACQUIRE 0x10
+#define BM_MCC_VERB_CMD_QUERY 0x40
+#define BM_MCC_VERB_ACQUIRE_BUFCOUNT 0x0f /* values 1..8 go here */
+
+/* MC result, Acquire and Query Response */
+union bm_mc_result {
+ struct {
+ u8 verb;
+ u8 bpid;
+ u8 __reserved[62];
+ };
+ struct bm_buffer bufs[8];
+};
+#define BM_MCR_VERB_VBIT 0x80
+#define BM_MCR_VERB_CMD_MASK BM_MCC_VERB_CMD_MASK
+#define BM_MCR_VERB_CMD_ACQUIRE BM_MCC_VERB_CMD_ACQUIRE
+#define BM_MCR_VERB_CMD_QUERY BM_MCC_VERB_CMD_QUERY
+#define BM_MCR_VERB_CMD_ERR_INVALID 0x60
+#define BM_MCR_VERB_CMD_ERR_ECC 0x70
+#define BM_MCR_VERB_ACQUIRE_BUFCOUNT BM_MCC_VERB_ACQUIRE_BUFCOUNT /* 0..8 */
+#define BM_MCR_TIMEOUT 10000 /* us */
+
+struct bm_mc {
+ struct bm_mc_command *cr;
+ union bm_mc_result *rr;
+ u8 rridx, vbit;
+#ifdef CONFIG_FSL_DPAA_CHECKING
+ enum {
+ /* Can only be _mc_start()ed */
+ mc_idle,
+ /* Can only be _mc_commit()ed or _mc_abort()ed */
+ mc_user,
+ /* Can only be _mc_retry()ed */
+ mc_hw
+ } state;
+#endif
};
-#define BMAN_ERR_MDATA(a, b, c) { .addr_mask = a, .bits = b, .txt = c}
-static const struct bman_error_info_mdata error_mdata[] = {
- BMAN_ERR_MDATA(0x03FF, 192, "Stockpile memory"),
- BMAN_ERR_MDATA(0x00FF, 256, "SW portal ring memory port 1"),
- BMAN_ERR_MDATA(0x00FF, 256, "SW portal ring memory port 2"),
+struct bm_addr {
+ void __iomem *ce; /* cache-enabled */
+ void __iomem *ci; /* cache-inhibited */
};
-#define BMAN_ERR_MDATA_COUNT \
- (sizeof(error_mdata)/sizeof(struct bman_error_info_mdata))
-/* Add this in Kconfig */
-#define BMAN_ERRS_TO_UNENABLE (BM_EIRQ_FLWI)
+struct bm_portal {
+ struct bm_addr addr;
+ struct bm_rcr rcr;
+ struct bm_mc mc;
+} ____cacheline_aligned;
-/**
- * bm_err_isr_<reg>_<verb> - Manipulate global interrupt registers
- * @v: for accessors that write values, this is the 32-bit value
- *
- * Manipulates BMAN_ERR_ISR, BMAN_ERR_IER, BMAN_ERR_ISDR, BMAN_ERR_IIR. All
- * manipulations except bm_err_isr_[un]inhibit() use 32-bit masks composed of
- * the BM_EIRQ_*** definitions. Note that "bm_err_isr_enable_write" means
- * "write the enable register" rather than "enable the write register"!
- */
-#define bm_err_isr_status_read(bm) \
- __bm_err_isr_read(bm, bm_isr_status)
-#define bm_err_isr_status_clear(bm, m) \
- __bm_err_isr_write(bm, bm_isr_status, m)
-#define bm_err_isr_enable_read(bm) \
- __bm_err_isr_read(bm, bm_isr_enable)
-#define bm_err_isr_enable_write(bm, v) \
- __bm_err_isr_write(bm, bm_isr_enable, v)
-#define bm_err_isr_disable_read(bm) \
- __bm_err_isr_read(bm, bm_isr_disable)
-#define bm_err_isr_disable_write(bm, v) \
- __bm_err_isr_write(bm, bm_isr_disable, v)
-#define bm_err_isr_inhibit(bm) \
- __bm_err_isr_write(bm, bm_isr_inhibit, 1)
-#define bm_err_isr_uninhibit(bm) \
- __bm_err_isr_write(bm, bm_isr_inhibit, 0)
+/* Cache-inhibited register access. */
+static inline u32 bm_in(struct bm_portal *p, u32 offset)
+{
+ return be32_to_cpu(__raw_readl(p->addr.ci + offset));
+}
+
+static inline void bm_out(struct bm_portal *p, u32 offset, u32 val)
+{
+ __raw_writel(cpu_to_be32(val), p->addr.ci + offset);
+}
+
+/* Cache Enabled Portal Access */
+static inline void bm_cl_invalidate(struct bm_portal *p, u32 offset)
+{
+ dpaa_invalidate(p->addr.ce + offset);
+}
+
+static inline void bm_cl_touch_ro(struct bm_portal *p, u32 offset)
+{
+ dpaa_touch_ro(p->addr.ce + offset);
+}
+
+static inline u32 bm_ce_in(struct bm_portal *p, u32 offset)
+{
+ return be32_to_cpu(__raw_readl(p->addr.ce + offset));
+}
+
+struct bman_portal {
+ struct bm_portal p;
+ /* interrupt sources processed by portal_isr(), configurable */
+ unsigned long irq_sources;
+ /* probing time config params for cpu-affine portals */
+ const struct bm_portal_config *config;
+ char irqname[MAX_IRQNAME];
+};
#ifndef __rtems__
-static u16 bman_pool_max;
-#else /* __rtems__ */
-/* FIXME */
-extern u16 bman_ip_rev;
-extern u16 bman_pool_max;
+static cpumask_t affine_mask;
+static DEFINE_SPINLOCK(affine_mask_lock);
#endif /* __rtems__ */
+static DEFINE_PER_CPU(struct bman_portal, bman_affine_portal);
+
+static inline struct bman_portal *get_affine_portal(void)
+{
+ return &get_cpu_var(bman_affine_portal);
+}
+
+static inline void put_affine_portal(void)
+{
+ put_cpu_var(bman_affine_portal);
+}
/*
- * TODO: unimplemented registers
- *
- * BMAN_POOLk_SDCNT, BMAN_POOLk_HDCNT, BMAN_FULT,
- * BMAN_VLDPL, BMAN_EECC, BMAN_SBET, BMAN_EINJ
+ * This object type refers to a pool, it isn't *the* pool. There may be
+ * more than one such object per BMan buffer pool, eg. if different users of the
+ * pool are operating via different portals.
*/
+struct bman_pool {
+ /* index of the buffer pool to encapsulate (0-63) */
+ u32 bpid;
+ /* Used for hash-table admin when using depletion notifications. */
+ struct bman_portal *portal;
+ struct bman_pool *next;
+};
-/* Encapsulate "struct bman *" as a cast of the register space address. */
+static u32 poll_portal_slow(struct bman_portal *p, u32 is);
-static struct bman *bm_create(void *regs)
+static irqreturn_t portal_isr(int irq, void *ptr)
{
- return (struct bman *)regs;
+ struct bman_portal *p = ptr;
+ struct bm_portal *portal = &p->p;
+ u32 clear = p->irq_sources;
+ u32 is = bm_in(portal, BM_REG_ISR) & p->irq_sources;
+
+ if (unlikely(!is))
+ return IRQ_NONE;
+
+ clear |= poll_portal_slow(p, is);
+ bm_out(portal, BM_REG_ISR, clear);
+ return IRQ_HANDLED;
}
-static inline u32 __bm_in(struct bman *bm, u32 offset)
+/* --- RCR API --- */
+
+#define RCR_SHIFT ilog2(sizeof(struct bm_rcr_entry))
+#define RCR_CARRY (uintptr_t)(BM_RCR_SIZE << RCR_SHIFT)
+
+/* Bit-wise logic to wrap a ring pointer by clearing the "carry bit" */
+static struct bm_rcr_entry *rcr_carryclear(struct bm_rcr_entry *p)
{
- return ioread32be((void *)bm + offset);
+ uintptr_t addr = (uintptr_t)p;
+
+ addr &= ~RCR_CARRY;
+
+ return (struct bm_rcr_entry *)addr;
}
-static inline void __bm_out(struct bman *bm, u32 offset, u32 val)
+
+#ifdef CONFIG_FSL_DPAA_CHECKING
+/* Bit-wise logic to convert a ring pointer to a ring index */
+static int rcr_ptr2idx(struct bm_rcr_entry *e)
{
- iowrite32be(val, (void*) bm + offset);
+ return ((uintptr_t)e >> RCR_SHIFT) & (BM_RCR_SIZE - 1);
}
-#define bm_in(reg) __bm_in(bm, REG_##reg)
-#define bm_out(reg, val) __bm_out(bm, REG_##reg, val)
+#endif
-static u32 __bm_err_isr_read(struct bman *bm, enum bm_isr_reg n)
+/* Increment the 'cursor' ring pointer, taking 'vbit' into account */
+static inline void rcr_inc(struct bm_rcr *rcr)
{
- return __bm_in(bm, REG_ERR_ISR + (n << 2));
+ /* increment to the next RCR pointer and handle overflow and 'vbit' */
+ struct bm_rcr_entry *partial = rcr->cursor + 1;
+
+ rcr->cursor = rcr_carryclear(partial);
+ if (partial != rcr->cursor)
+ rcr->vbit ^= BM_RCR_VERB_VBIT;
}
-static void __bm_err_isr_write(struct bman *bm, enum bm_isr_reg n, u32 val)
+static int bm_rcr_get_avail(struct bm_portal *portal)
{
- __bm_out(bm, REG_ERR_ISR + (n << 2), val);
+ struct bm_rcr *rcr = &portal->rcr;
+
+ return rcr->available;
}
-static void bm_get_version(struct bman *bm, u16 *id, u8 *major, u8 *minor)
+static int bm_rcr_get_fill(struct bm_portal *portal)
{
- u32 v = bm_in(IP_REV_1);
- *id = (v >> 16);
- *major = (v >> 8) & 0xff;
- *minor = v & 0xff;
+ struct bm_rcr *rcr = &portal->rcr;
+
+ return BM_RCR_SIZE - 1 - rcr->available;
}
-static u32 __generate_thresh(u32 val, int roundup)
+static void bm_rcr_set_ithresh(struct bm_portal *portal, u8 ithresh)
{
- u32 e = 0; /* co-efficient, exponent */
- int oddbit = 0;
+ struct bm_rcr *rcr = &portal->rcr;
- while (val > 0xff) {
- oddbit = val & 1;
- val >>= 1;
- e++;
- if (roundup && oddbit)
- val++;
- }
- DPA_ASSERT(e < 0x10);
- return val | (e << 8);
+ rcr->ithresh = ithresh;
+ bm_out(portal, BM_REG_RCR_ITR, ithresh);
}
-static void bm_set_pool(struct bman *bm, u8 pool, u32 swdet, u32 swdxt,
- u32 hwdet, u32 hwdxt)
+static void bm_rcr_cce_prefetch(struct bm_portal *portal)
{
- DPA_ASSERT(pool < bman_pool_max);
+ __maybe_unused struct bm_rcr *rcr = &portal->rcr;
- bm_out(POOL_SWDET(pool), __generate_thresh(swdet, 0));
- bm_out(POOL_SWDXT(pool), __generate_thresh(swdxt, 1));
- bm_out(POOL_HWDET(pool), __generate_thresh(hwdet, 0));
- bm_out(POOL_HWDXT(pool), __generate_thresh(hwdxt, 1));
+ DPAA_ASSERT(rcr->cmode == bm_rcr_cce);
+ bm_cl_touch_ro(portal, BM_CL_RCR_CI_CENA);
}
-static void bm_set_memory(struct bman *bm, u64 ba, int prio, u32 size)
+static u8 bm_rcr_cce_update(struct bm_portal *portal)
{
- u32 exp = ilog2(size);
- /* choke if size isn't within range */
- DPA_ASSERT((size >= 4096) && (size <= 1073741824) &&
- is_power_of_2(size));
- /* choke if '[e]ba' has lower-alignment than 'size' */
- DPA_ASSERT(!(ba & (size - 1)));
- bm_out(FBPR_BARE, upper_32_bits(ba));
- bm_out(FBPR_BAR, lower_32_bits(ba));
- bm_out(FBPR_AR, (prio ? 0x40000000 : 0) | (exp - 1));
+ struct bm_rcr *rcr = &portal->rcr;
+ u8 diff, old_ci = rcr->ci;
+
+ DPAA_ASSERT(rcr->cmode == bm_rcr_cce);
+ rcr->ci = bm_ce_in(portal, BM_CL_RCR_CI_CENA) & (BM_RCR_SIZE - 1);
+ bm_cl_invalidate(portal, BM_CL_RCR_CI_CENA);
+ diff = dpaa_cyc_diff(BM_RCR_SIZE, old_ci, rcr->ci);
+ rcr->available += diff;
+ return diff;
}
-/*****************/
-/* Config driver */
-/*****************/
+static inline struct bm_rcr_entry *bm_rcr_start(struct bm_portal *portal)
+{
+ struct bm_rcr *rcr = &portal->rcr;
+
+ DPAA_ASSERT(!rcr->busy);
+ if (!rcr->available)
+ return NULL;
+#ifdef CONFIG_FSL_DPAA_CHECKING
+ rcr->busy = 1;
+#endif
+ dpaa_zero(rcr->cursor);
+ return rcr->cursor;
+}
-/* We support only one of these. */
-static struct bman *bm;
+static inline void bm_rcr_pvb_commit(struct bm_portal *portal, u8 myverb)
+{
+ struct bm_rcr *rcr = &portal->rcr;
+ struct bm_rcr_entry *rcursor;
+
+ DPAA_ASSERT(rcr->busy);
+ DPAA_ASSERT(rcr->pmode == bm_rcr_pvb);
+ DPAA_ASSERT(rcr->available >= 1);
+ dma_wmb();
+ rcursor = rcr->cursor;
+ rcursor->_ncw_verb = myverb | rcr->vbit;
+ dpaa_flush(rcursor);
+ rcr_inc(rcr);
+ rcr->available--;
+#ifdef CONFIG_FSL_DPAA_CHECKING
+ rcr->busy = 0;
+#endif
+}
-/* And this state belongs to 'bm' */
-#ifndef __rtems__
-static dma_addr_t fbpr_a;
-static size_t fbpr_sz;
+static int bm_rcr_init(struct bm_portal *portal, enum bm_rcr_pmode pmode,
+ enum bm_rcr_cmode cmode)
+{
+ struct bm_rcr *rcr = &portal->rcr;
+ u32 cfg;
+ u8 pi;
+
+ rcr->ring = portal->addr.ce + BM_CL_RCR;
+ rcr->ci = bm_in(portal, BM_REG_RCR_CI_CINH) & (BM_RCR_SIZE - 1);
+ pi = bm_in(portal, BM_REG_RCR_PI_CINH) & (BM_RCR_SIZE - 1);
+ rcr->cursor = rcr->ring + pi;
+ rcr->vbit = (bm_in(portal, BM_REG_RCR_PI_CINH) & BM_RCR_SIZE) ?
+ BM_RCR_VERB_VBIT : 0;
+ rcr->available = BM_RCR_SIZE - 1
+ - dpaa_cyc_diff(BM_RCR_SIZE, rcr->ci, pi);
+ rcr->ithresh = bm_in(portal, BM_REG_RCR_ITR);
+#ifdef CONFIG_FSL_DPAA_CHECKING
+ rcr->busy = 0;
+ rcr->pmode = pmode;
+ rcr->cmode = cmode;
+#endif
+ cfg = (bm_in(portal, BM_REG_CFG) & 0xffffffe0)
+ | (pmode & 0x3); /* BCSP_CFG::RPM */
+ bm_out(portal, BM_REG_CFG, cfg);
+ return 0;
+}
-static int bman_fbpr(struct reserved_mem *rmem)
+static void bm_rcr_finish(struct bm_portal *portal)
{
- fbpr_a = rmem->base;
- fbpr_sz = rmem->size;
+#ifdef CONFIG_FSL_DPAA_CHECKING
+ struct bm_rcr *rcr = &portal->rcr;
+ int i;
- WARN_ON(!(fbpr_a && fbpr_sz));
+ DPAA_ASSERT(!rcr->busy);
- return 0;
+ i = bm_in(portal, BM_REG_RCR_PI_CINH) & (BM_RCR_SIZE - 1);
+ if (i != rcr_ptr2idx(rcr->cursor))
+ pr_crit("losing uncommitted RCR entries\n");
+
+ i = bm_in(portal, BM_REG_RCR_CI_CINH) & (BM_RCR_SIZE - 1);
+ if (i != rcr->ci)
+ pr_crit("missing existing RCR completions\n");
+ if (rcr->ci != rcr_ptr2idx(rcr->cursor))
+ pr_crit("RCR destroyed unquiesced\n");
+#endif
}
-RESERVEDMEM_OF_DECLARE(bman_fbpr, "fsl,bman-fbpr", bman_fbpr);
-#else /* __rtems__ */
-static DPAA_NOCACHENOLOAD_ALIGNED_REGION(fbpr, 16777216);
-#define fbpr_a ((uintptr_t)&fbpr[0])
-#define fbpr_sz sizeof(fbpr)
-#endif /* __rtems__ */
-int bm_pool_set(u32 bpid, const u32 *thresholds)
+/* --- Management command API --- */
+static int bm_mc_init(struct bm_portal *portal)
{
- if (!bm)
- return -ENODEV;
- bm_set_pool(bm, bpid, thresholds[0], thresholds[1],
- thresholds[2], thresholds[3]);
+ struct bm_mc *mc = &portal->mc;
+
+ mc->cr = portal->addr.ce + BM_CL_CR;
+ mc->rr = portal->addr.ce + BM_CL_RR0;
+ mc->rridx = (__raw_readb(&mc->cr->_ncw_verb) & BM_MCC_VERB_VBIT) ?
+ 0 : 1;
+ mc->vbit = mc->rridx ? BM_MCC_VERB_VBIT : 0;
+#ifdef CONFIG_FSL_DPAA_CHECKING
+ mc->state = mc_idle;
+#endif
return 0;
}
-EXPORT_SYMBOL(bm_pool_set);
-static void log_edata_bits(u32 bit_count)
+static void bm_mc_finish(struct bm_portal *portal)
{
- u32 i, j, mask = 0xffffffff;
+#ifdef CONFIG_FSL_DPAA_CHECKING
+ struct bm_mc *mc = &portal->mc;
- pr_warn("ErrInt, EDATA:\n");
- i = bit_count/32;
- if (bit_count%32) {
- i++;
- mask = ~(mask << bit_count%32);
- }
- j = 16-i;
- pr_warn(" 0x%08x\n", bm_in(EDATA(j)) & mask);
- j++;
- for (; j < 16; j++)
- pr_warn(" 0x%08x\n", bm_in(EDATA(j)));
+ DPAA_ASSERT(mc->state == mc_idle);
+ if (mc->state != mc_idle)
+ pr_crit("Losing incomplete MC command\n");
+#endif
}
-static void log_additional_error_info(u32 isr_val, u32 ecsr_val)
+static inline struct bm_mc_command *bm_mc_start(struct bm_portal *portal)
{
- union bman_ecir ecir_val;
- union bman_eadr eadr_val;
+ struct bm_mc *mc = &portal->mc;
+
+ DPAA_ASSERT(mc->state == mc_idle);
+#ifdef CONFIG_FSL_DPAA_CHECKING
+ mc->state = mc_user;
+#endif
+ dpaa_zero(mc->cr);
+ return mc->cr;
+}
- ecir_val.ecir_raw = bm_in(ECIR);
- /* Is portal info valid */
- if (ecsr_val & PORTAL_ECSR_ERR) {
- pr_warn("ErrInt: SWP id %d, numb %d, pid %d\n",
- ecir_val.info.portal_num, ecir_val.info.numb,
- ecir_val.info.pid);
- }
- if (ecsr_val & (BM_EIRQ_SBEI|BM_EIRQ_MBEI)) {
- eadr_val.eadr_raw = bm_in(EADR);
- pr_warn("ErrInt: EADR Memory: %s, 0x%x\n",
- error_mdata[eadr_val.info.memid].txt,
- error_mdata[eadr_val.info.memid].addr_mask
- & eadr_val.info.eadr);
- log_edata_bits(error_mdata[eadr_val.info.memid].bits);
- }
+static inline void bm_mc_commit(struct bm_portal *portal, u8 myverb)
+{
+ struct bm_mc *mc = &portal->mc;
+ union bm_mc_result *rr = mc->rr + mc->rridx;
+
+ DPAA_ASSERT(mc->state == mc_user);
+ dma_wmb();
+ mc->cr->_ncw_verb = myverb | mc->vbit;
+ dpaa_flush(mc->cr);
+ dpaa_invalidate_touch_ro(rr);
+#ifdef CONFIG_FSL_DPAA_CHECKING
+ mc->state = mc_hw;
+#endif
}
-/* BMan interrupt handler */
-static irqreturn_t bman_isr(int irq, void *ptr)
+static inline union bm_mc_result *bm_mc_result(struct bm_portal *portal)
{
- u32 isr_val, ier_val, ecsr_val, isr_mask, i;
+ struct bm_mc *mc = &portal->mc;
+ union bm_mc_result *rr = mc->rr + mc->rridx;
+
+ DPAA_ASSERT(mc->state == mc_hw);
+ /*
+ * The inactive response register's verb byte always returns zero until
+ * its command is submitted and completed. This includes the valid-bit,
+ * in case you were wondering...
+ */
+ if (!__raw_readb(&rr->verb)) {
+ dpaa_invalidate_touch_ro(rr);
+ return NULL;
+ }
+ mc->rridx ^= 1;
+ mc->vbit ^= BM_MCC_VERB_VBIT;
+#ifdef CONFIG_FSL_DPAA_CHECKING
+ mc->state = mc_idle;
+#endif
+ return rr;
+}
- ier_val = bm_err_isr_enable_read(bm);
- isr_val = bm_err_isr_status_read(bm);
- ecsr_val = bm_in(ECSR);
- isr_mask = isr_val & ier_val;
+static inline int bm_mc_result_timeout(struct bm_portal *portal,
+ union bm_mc_result **mcr)
+{
+ int timeout = BM_MCR_TIMEOUT;
- if (!isr_mask)
- return IRQ_NONE;
+ do {
+ *mcr = bm_mc_result(portal);
+ if (*mcr)
+ break;
+ udelay(1);
+ } while (--timeout);
- for (i = 0; i < BMAN_HWE_COUNT; i++) {
- if (bman_hwerr_txts[i].mask & isr_mask) {
- pr_warn("ErrInt: %s\n", bman_hwerr_txts[i].txt);
- if (bman_hwerr_txts[i].mask & ecsr_val) {
- log_additional_error_info(isr_mask, ecsr_val);
- /* Re-arm error capture registers */
- bm_out(ECSR, ecsr_val);
- }
- if (bman_hwerr_txts[i].mask & BMAN_ERRS_TO_UNENABLE) {
- pr_devel("Un-enabling error 0x%x\n",
- bman_hwerr_txts[i].mask);
- ier_val &= ~bman_hwerr_txts[i].mask;
- bm_err_isr_enable_write(bm, ier_val);
- }
- }
- }
- bm_err_isr_status_clear(bm, isr_val);
-
- return IRQ_HANDLED;
+ return timeout;
}
-u32 bm_pool_free_buffers(u32 bpid)
+/* Disable all BSCN interrupts for the portal */
+static void bm_isr_bscn_disable(struct bm_portal *portal)
{
- return bm_in(POOL_CONTENT(bpid));
+ bm_out(portal, BM_REG_SCN(0), 0);
+ bm_out(portal, BM_REG_SCN(1), 0);
}
-EXPORT_SYMBOL(bm_pool_free_buffers);
-#ifndef __rtems__
-static ssize_t show_fbpr_fpc(struct device *dev,
- struct device_attribute *dev_attr, char *buf)
+static int bman_create_portal(struct bman_portal *portal,
+ const struct bm_portal_config *c)
{
- return snprintf(buf, PAGE_SIZE, "%u\n", bm_in(FBPR_FPC));
-};
+ struct bm_portal *p;
+ int ret;
-static ssize_t show_pool_count(struct device *dev,
- struct device_attribute *dev_attr, char *buf)
-{
- u32 data;
- int i;
+ p = &portal->p;
+ /*
+ * prep the low-level portal struct with the mapped addresses from the
+ * config, everything that follows depends on it and "config" is more
+ * for (de)reference...
+ */
+ p->addr.ce = c->addr_virt[DPAA_PORTAL_CE];
+ p->addr.ci = c->addr_virt[DPAA_PORTAL_CI];
+ if (bm_rcr_init(p, bm_rcr_pvb, bm_rcr_cce)) {
+ dev_err(c->dev, "RCR initialisation failed\n");
+ goto fail_rcr;
+ }
+ if (bm_mc_init(p)) {
+ dev_err(c->dev, "MC initialisation failed\n");
+ goto fail_mc;
+ }
+ /*
+ * Default to all BPIDs disabled, we enable as required at
+ * run-time.
+ */
+ bm_isr_bscn_disable(p);
+
+ /* Write-to-clear any stale interrupt status bits */
+ bm_out(p, BM_REG_ISDR, 0xffffffff);
+ portal->irq_sources = 0;
+ bm_out(p, BM_REG_IER, 0);
+ bm_out(p, BM_REG_ISR, 0xffffffff);
+ snprintf(portal->irqname, MAX_IRQNAME, IRQNAME, c->cpu);
+ if (request_irq(c->irq, portal_isr, 0, portal->irqname, portal)) {
+ dev_err(c->dev, "request_irq() failed\n");
+ goto fail_irq;
+ }
+#ifndef __rtems__
+ if (c->cpu != -1 && irq_can_set_affinity(c->irq) &&
+ irq_set_affinity(c->irq, cpumask_of(c->cpu))) {
+ dev_err(c->dev, "irq_set_affinity() failed\n");
+ goto fail_affinity;
+ }
+#endif /* __rtems__ */
- if (kstrtoint(dev_attr->attr.name, 10, &i))
- return -EINVAL;
- data = bm_in(POOL_CONTENT(i));
- return snprintf(buf, PAGE_SIZE, "%d\n", data);
-};
+ /* Need RCR to be empty before continuing */
+ ret = bm_rcr_get_fill(p);
+ if (ret) {
+ dev_err(c->dev, "RCR unclean\n");
+ goto fail_rcr_empty;
+ }
+ /* Success */
+ portal->config = c;
-static ssize_t show_err_isr(struct device *dev,
- struct device_attribute *dev_attr, char *buf)
-{
- return snprintf(buf, PAGE_SIZE, "0x%08x\n", bm_in(ERR_ISR));
-};
+ bm_out(p, BM_REG_ISDR, 0);
+ bm_out(p, BM_REG_IIR, 0);
+
+ return 0;
-static ssize_t show_sbec(struct device *dev,
- struct device_attribute *dev_attr, char *buf)
+fail_rcr_empty:
+#ifndef __rtems__
+fail_affinity:
+#endif /* __rtems__ */
+ free_irq(c->irq, portal);
+fail_irq:
+ bm_mc_finish(p);
+fail_mc:
+ bm_rcr_finish(p);
+fail_rcr:
+ return -EIO;
+}
+
+struct bman_portal *bman_create_affine_portal(const struct bm_portal_config *c)
{
- int i;
+ struct bman_portal *portal;
+ int err;
- if (sscanf(dev_attr->attr.name, "sbec_%d", &i) != 1)
- return -EINVAL;
- return snprintf(buf, PAGE_SIZE, "%u\n", bm_in(SBEC(i)));
-};
+ portal = &per_cpu(bman_affine_portal, c->cpu);
+ err = bman_create_portal(portal, c);
+ if (err)
+ return NULL;
-static DEVICE_ATTR(err_isr, S_IRUSR, show_err_isr, NULL);
-static DEVICE_ATTR(fbpr_fpc, S_IRUSR, show_fbpr_fpc, NULL);
+#ifndef __rtems__
+ spin_lock(&affine_mask_lock);
+ cpumask_set_cpu(c->cpu, &affine_mask);
+ spin_unlock(&affine_mask_lock);
+#endif /* __rtems__ */
-/* Didn't use DEVICE_ATTR as 64 of this would be required.
- * Initialize them when needed. */
-static char *name_attrs_pool_count; /* "xx" + null-terminator */
-static struct device_attribute *dev_attr_buffer_pool_count;
+ return portal;
+}
-static DEVICE_ATTR(sbec_0, S_IRUSR, show_sbec, NULL);
-static DEVICE_ATTR(sbec_1, S_IRUSR, show_sbec, NULL);
+static u32 poll_portal_slow(struct bman_portal *p, u32 is)
+{
+ u32 ret = is;
-static struct attribute *bman_dev_attributes[] = {
- &dev_attr_fbpr_fpc.attr,
- &dev_attr_err_isr.attr,
- NULL
-};
+ if (is & BM_PIRQ_RCRI) {
+ bm_rcr_cce_update(&p->p);
+ bm_rcr_set_ithresh(&p->p, 0);
+ bm_out(&p->p, BM_REG_ISR, BM_PIRQ_RCRI);
+ is &= ~BM_PIRQ_RCRI;
+ }
-static struct attribute *bman_dev_ecr_attributes[] = {
- &dev_attr_sbec_0.attr,
- &dev_attr_sbec_1.attr,
- NULL
-};
+ /* There should be no status register bits left undefined */
+ DPAA_ASSERT(!is);
+ return ret;
+}
-static struct attribute **bman_dev_pool_count_attributes;
+int bman_p_irqsource_add(struct bman_portal *p, u32 bits)
+{
+ unsigned long irqflags;
-/* root level */
-static const struct attribute_group bman_dev_attr_grp = {
- .name = NULL,
- .attrs = bman_dev_attributes
-};
-static const struct attribute_group bman_dev_ecr_grp = {
- .name = "error_capture",
- .attrs = bman_dev_ecr_attributes
-};
-static struct attribute_group bman_dev_pool_countent_grp = {
- .name = "pool_count",
-};
+ local_irq_save(irqflags);
+ set_bits(bits & BM_PIRQ_VISIBLE, &p->irq_sources);
+ bm_out(&p->p, BM_REG_IER, p->irq_sources);
+ local_irq_restore(irqflags);
+ return 0;
+}
-static int of_fsl_bman_remove(struct platform_device *ofdev)
+static int bm_shutdown_pool(u32 bpid)
{
- sysfs_remove_group(&ofdev->dev.kobj, &bman_dev_attr_grp);
+ struct bm_mc_command *bm_cmd;
+ union bm_mc_result *bm_res;
+
+ while (1) {
+ struct bman_portal *p = get_affine_portal();
+ /* Acquire buffers until empty */
+ bm_cmd = bm_mc_start(&p->p);
+ bm_cmd->bpid = bpid;
+ bm_mc_commit(&p->p, BM_MCC_VERB_CMD_ACQUIRE | 1);
+ if (!bm_mc_result_timeout(&p->p, &bm_res)) {
+ put_affine_portal();
+ pr_crit("BMan Acquire Command timedout\n");
+ return -ETIMEDOUT;
+ }
+ if (!(bm_res->verb & BM_MCR_VERB_ACQUIRE_BUFCOUNT)) {
+ put_affine_portal();
+ /* Pool is empty */
+ return 0;
+ }
+ put_affine_portal();
+ }
+
return 0;
-};
-#endif /* __rtems__ */
+}
+
+struct gen_pool *bm_bpalloc;
-static int of_fsl_bman_probe(struct platform_device *ofdev)
+static int bm_alloc_bpid_range(u32 *result, u32 count)
{
- int ret, err_irq, i;
- struct device *dev = &ofdev->dev;
- struct device_node *node = dev->of_node;
- struct resource res;
- u32 __iomem *regs;
- u16 id;
- u8 major, minor;
+ unsigned long addr;
- if (!of_device_is_available(node))
- return -ENODEV;
+ addr = gen_pool_alloc(bm_bpalloc, count);
+ if (!addr)
+ return -ENOMEM;
- ret = of_address_to_resource(node, 0, &res);
- if (ret) {
- dev_err(dev, "Can't get %s property 'reg'\n", node->full_name);
- return ret;
- }
- regs = devm_ioremap(dev, res.start, res.end - res.start + 1);
- if (!regs)
- return -ENXIO;
-
- bm = bm_create(regs);
-
- bm_get_version(bm, &id, &major, &minor);
- dev_info(dev, "Bman ver:%04x,%02x,%02x\n", id, major, minor);
- if ((major == 1) && (minor == 0))
- bman_pool_max = 64;
- else if ((major == 2) && (minor == 0))
- bman_pool_max = 8;
- else if ((major == 2) && (minor == 1))
- bman_pool_max = 64;
- else
- dev_warn(dev, "unknown Bman version, default to rev1.0\n");
-#ifdef __rtems__
- bman_ip_rev = (u16)((major << 8) | minor);
-#endif /* __rtems__ */
+ *result = addr & ~DPAA_GENALLOC_OFF;
+ return 0;
+}
- bm_set_memory(bm, fbpr_a, 0, fbpr_sz);
+static int bm_release_bpid(u32 bpid)
+{
+ int ret;
- err_irq = of_irq_to_resource(node, 0, NULL);
- if (err_irq == NO_IRQ) {
- dev_info(dev, "Can't get %s property 'interrupts'\n",
- node->full_name);
- return -ENODEV;
- }
- ret = devm_request_irq(dev, err_irq, bman_isr, IRQF_SHARED, "bman-err",
- node);
- if (ret) {
- dev_err(dev, "devm_request_irq() failed %d for '%s'\n",
- ret, node->full_name);
+ ret = bm_shutdown_pool(bpid);
+ if (ret) {
+ pr_debug("BPID %d leaked\n", bpid);
return ret;
}
- /* Disable Buffer Pool State Change */
- bm_err_isr_disable_write(bm, BM_EIRQ_BSCN);
- /* Write-to-clear any stale bits, (eg. starvation being asserted prior
- * to resource allocation during driver init). */
- bm_err_isr_status_clear(bm, 0xffffffff);
- /* Enable Error Interrupts */
- bm_err_isr_enable_write(bm, 0xffffffff);
-#ifndef __rtems__
- ret = sysfs_create_group(&dev->kobj, &bman_dev_attr_grp);
- if (ret)
- goto done;
- ret = sysfs_create_group(&dev->kobj, &bman_dev_ecr_grp);
- if (ret)
- goto del_group_0;
-
- name_attrs_pool_count = devm_kmalloc(dev,
- sizeof(char) * bman_pool_max * 3, GFP_KERNEL);
- if (!name_attrs_pool_count)
- goto del_group_1;
-
- dev_attr_buffer_pool_count = devm_kmalloc(dev,
- sizeof(struct device_attribute) * bman_pool_max, GFP_KERNEL);
- if (!dev_attr_buffer_pool_count)
- goto del_group_1;
-
- bman_dev_pool_count_attributes = devm_kmalloc(dev,
- sizeof(struct attribute *) * (bman_pool_max + 1), GFP_KERNEL);
- if (!bman_dev_pool_count_attributes)
- goto del_group_1;
-
- for (i = 0; i < bman_pool_max; i++) {
- ret = scnprintf((name_attrs_pool_count + i * 3), 3, "%d", i);
- if (!ret)
- goto del_group_1;
- dev_attr_buffer_pool_count[i].attr.name =
- (name_attrs_pool_count + i * 3);
- dev_attr_buffer_pool_count[i].attr.mode = S_IRUSR;
- dev_attr_buffer_pool_count[i].show = show_pool_count;
- bman_dev_pool_count_attributes[i] =
- &dev_attr_buffer_pool_count[i].attr;
- }
- bman_dev_pool_count_attributes[bman_pool_max] = NULL;
-
- bman_dev_pool_countent_grp.attrs = bman_dev_pool_count_attributes;
-
- ret = sysfs_create_group(&dev->kobj, &bman_dev_pool_countent_grp);
- if (ret)
- goto del_group_1;
+ gen_pool_free(bm_bpalloc, bpid | DPAA_GENALLOC_OFF, 1);
+ return 0;
+}
- goto done;
+struct bman_pool *bman_new_pool(void)
+{
+ struct bman_pool *pool = NULL;
+ u32 bpid;
-del_group_1:
- sysfs_remove_group(&dev->kobj, &bman_dev_ecr_grp);
-del_group_0:
- sysfs_remove_group(&dev->kobj, &bman_dev_attr_grp);
-done:
- if (ret)
- dev_err(dev, "Cannot create dev attributes ret=%d\n", ret);
-#else /* __rtems__ */
- (void)i;
-#endif /* __rtems__ */
+ if (bm_alloc_bpid_range(&bpid, 1))
+ return NULL;
- return ret;
-};
+ pool = kmalloc(sizeof(*pool), GFP_KERNEL);
+ if (!pool)
+ goto err;
-#ifndef __rtems__
-static const struct of_device_id of_fsl_bman_ids[] = {
- {
- .compatible = "fsl,bman",
- },
- {}
-};
+ pool->bpid = bpid;
-static struct platform_driver of_fsl_bman_driver = {
- .driver = {
- .name = KBUILD_MODNAME,
- .of_match_table = of_fsl_bman_ids,
- },
- .probe = of_fsl_bman_probe,
- .remove = of_fsl_bman_remove,
-};
+ return pool;
+err:
+ bm_release_bpid(bpid);
+ kfree(pool);
+ return NULL;
+}
+EXPORT_SYMBOL(bman_new_pool);
-builtin_platform_driver(of_fsl_bman_driver);
-#else /* __rtems__ */
-#include <sys/types.h>
-#include <sys/kernel.h>
-#include <rtems.h>
-#include <bsp/fdt.h>
-#include <bsp/qoriq.h>
+void bman_free_pool(struct bman_pool *pool)
+{
+ bm_release_bpid(pool->bpid);
-static struct bm_portal_config bman_configs[NR_CPUS];
+ kfree(pool);
+}
+EXPORT_SYMBOL(bman_free_pool);
-u16 bman_ip_rev;
+int bman_get_bpid(const struct bman_pool *pool)
+{
+ return pool->bpid;
+}
+EXPORT_SYMBOL(bman_get_bpid);
-u16 bman_pool_max;
+static void update_rcr_ci(struct bman_portal *p, int avail)
+{
+ if (avail)
+ bm_rcr_cce_prefetch(&p->p);
+ else
+ bm_rcr_cce_update(&p->p);
+}
-SYSINIT_REFERENCE(irqs);
+int bman_release(struct bman_pool *pool, const struct bm_buffer *bufs, u8 num)
+{
+ struct bman_portal *p;
+ struct bm_rcr_entry *r;
+ unsigned long irqflags;
+ int avail, timeout = 1000; /* 1ms */
+ int i = num - 1;
+
+ DPAA_ASSERT(num > 0 && num <= 8);
+
+ do {
+ p = get_affine_portal();
+ local_irq_save(irqflags);
+ avail = bm_rcr_get_avail(&p->p);
+ if (avail < 2)
+ update_rcr_ci(p, avail);
+ r = bm_rcr_start(&p->p);
+ local_irq_restore(irqflags);
+ put_affine_portal();
+ if (likely(r))
+ break;
+
+ udelay(1);
+ } while (--timeout);
+
+ if (unlikely(!timeout))
+ return -ETIMEDOUT;
+
+ p = get_affine_portal();
+ local_irq_save(irqflags);
+ /*
+ * we can copy all but the first entry, as this can trigger badness
+ * with the valid-bit
+ */
+ bm_buffer_set64(r->bufs, bm_buffer_get64(bufs));
+ bm_buffer_set_bpid(r->bufs, pool->bpid);
+ if (i)
+ memcpy(&r->bufs[1], &bufs[1], i * sizeof(bufs[0]));
+
+ bm_rcr_pvb_commit(&p->p, BM_RCR_VERB_CMD_BPID_SINGLE |
+ (num & BM_RCR_VERB_BUFCOUNT_MASK));
+
+ local_irq_restore(irqflags);
+ put_affine_portal();
+ return 0;
+}
+EXPORT_SYMBOL(bman_release);
-static void
-bman_sysinit(void)
+int bman_acquire(struct bman_pool *pool, struct bm_buffer *bufs, u8 num)
{
- const char *fdt = bsp_fdt_get();
- struct device_node dn;
- struct platform_device ofdev = {
- .dev = {
- .of_node = &dn,
- .base = (uintptr_t)&qoriq
- }
- };
- const char *name;
- int cpu_count = (int)rtems_get_processor_count();
- int cpu;
+ struct bman_portal *p = get_affine_portal();
+ struct bm_mc_command *mcc;
+ union bm_mc_result *mcr;
int ret;
- int node;
- int parent;
-
- qoriq_reset_qman_and_bman();
- qoriq_clear_ce_portal(&qoriq_bman_portal[0][0],
- sizeof(qoriq_bman_portal[0]));
- qoriq_clear_ci_portal(&qoriq_bman_portal[1][0],
- sizeof(qoriq_bman_portal[1]));
-
- memset(&dn, 0, sizeof(dn));
-
- name = "fsl,bman";
- node = fdt_node_offset_by_compatible(fdt, 0, name);
- if (node < 0)
- panic("bman: no bman in FDT");
-
- dn.full_name = name;
- dn.offset = node;
- ret = of_fsl_bman_probe(&ofdev);
- if (ret != 0)
- panic("bman: probe failed");
-
- name = "fsl,bman-portal";
- node = fdt_node_offset_by_compatible(fdt, 0, name);
- if (node < 0)
- panic("bman: no portals in FDT");
- parent = fdt_parent_offset(fdt, node);
- if (parent < 0)
- panic("bman: no parent of portals in FDT");
- node = fdt_first_subnode(fdt, parent);
-
- dn.full_name = name;
- dn.offset = node;
-
- for (cpu = 0; cpu < cpu_count; ++cpu) {
- struct bm_portal_config *pcfg = &bman_configs[cpu];
- struct bman_portal *portal;
- struct resource res;
-
- if (node < 0)
- panic("bman: missing portal in FDT");
-
- ret = of_address_to_resource(&dn, 0, &res);
- if (ret != 0)
- panic("bman: no portal CE address");
- pcfg->addr_virt[0] = (__iomem void *)
- ((uintptr_t)&qoriq_bman_portal[0][0] + (uintptr_t)res.start);
- BSD_ASSERT((uintptr_t)pcfg->addr_virt[0] >=
- (uintptr_t)&qoriq_bman_portal[0][0]);
- BSD_ASSERT((uintptr_t)pcfg->addr_virt[0] <
- (uintptr_t)&qoriq_bman_portal[1][0]);
-
- ret = of_address_to_resource(&dn, 1, &res);
- if (ret != 0)
- panic("bman: no portal CI address");
- pcfg->addr_virt[1] = (__iomem void *)
- ((uintptr_t)&qoriq_bman_portal[0][0] + (uintptr_t)res.start);
- BSD_ASSERT((uintptr_t)pcfg->addr_virt[1] >=
- (uintptr_t)&qoriq_bman_portal[1][0]);
- BSD_ASSERT((uintptr_t)pcfg->addr_virt[1] <
- (uintptr_t)&qoriq_bman_portal[2][0]);
-
- pcfg->public_cfg.irq = of_irq_to_resource(&dn, 0, NULL);
- if (pcfg->public_cfg.irq == NO_IRQ)
- panic("bman: no portal interrupt");
-
- pcfg->public_cfg.cpu = cpu;
- bman_depletion_fill(&pcfg->public_cfg.mask);
-
- portal = bman_create_affine_portal(pcfg);
- if (portal == NULL)
- panic("bman: cannot create portal");
-
- bman_p_irqsource_add(portal, BM_PIRQ_RCRI | BM_PIRQ_BSCN);
-
- node = fdt_next_subnode(fdt, node);
- dn.offset = node;
+
+ DPAA_ASSERT(num > 0 && num <= 8);
+
+ mcc = bm_mc_start(&p->p);
+ mcc->bpid = pool->bpid;
+ bm_mc_commit(&p->p, BM_MCC_VERB_CMD_ACQUIRE |
+ (num & BM_MCC_VERB_ACQUIRE_BUFCOUNT));
+ if (!bm_mc_result_timeout(&p->p, &mcr)) {
+ put_affine_portal();
+ pr_crit("BMan Acquire Timeout\n");
+ return -ETIMEDOUT;
}
+ ret = mcr->verb & BM_MCR_VERB_ACQUIRE_BUFCOUNT;
+ if (bufs)
+ memcpy(&bufs[0], &mcr->bufs[0], num * sizeof(bufs[0]));
- bman_seed_bpid_range(0, bman_pool_max);
+ put_affine_portal();
+ if (ret != num)
+ ret = -ENOMEM;
+ return ret;
+}
+EXPORT_SYMBOL(bman_acquire);
+
+const struct bm_portal_config *
+bman_get_bm_portal_config(const struct bman_portal *portal)
+{
+ return portal->config;
}
-SYSINIT(bman_sysinit, SI_SUB_CPU, SI_ORDER_FIRST, bman_sysinit, NULL);
-#endif /* __rtems__ */