This patch series: A) addresses the final item in the staging
TODO list for the fsl-mc bus driver-- adding a functional driver
on top of the bus driver, and B) requests that the fsl-mc bus driver
be moved out of staging.
The proposed destination for the bus driver is drivers/bus.
Proposed location for global header files for fsl-mc and dpaa2
is include/linux/fsl.
The functional driver added is for the DPIO object which provides
queuing services for other DPAA2 drivers. An overview of the
DPIO object and driver components are in patch 2. Patches 3-7 are
internal components of the DPIO driver-- bit twiddling of hardware
registers, DPAA2 data structures, and the queuing APIs exposed
to other drivers.
Patch 8 adds the fsl-mc driver for the DPIO object. It provides
the probe/remove functions, demonstrating a working example of
how fsl-mc drivers initialize, interact with the management
complex hardware, map their mappable MMIO regions, initialize
interrupts, register an ISR, etc. All other DPAA2 drivers will
follow a similar initialization pattern.
The dpio driver is added under drivers/bus/fsl-mc/dpio. This
driver provides queueing related services and there is no other
obvious place it would go. Like the bus driver, it is part of
the DPAA2 infrastucture and putting it under the fsl-mc bus
driver seems like a logical place.
This series depends on the patch series:
[PATCH 00/14] staging: fsl-mc: cleanup and uprev to MC v10.x
https://www.spinics.net/lists/kernel/msg2362567.html
Ioana Radulescu (1):
bus: fsl-mc: dpio: add APIs for DPIO objects
Roy Pledge (6):
bus: fsl-mc: dpio: add frame descriptor and scatter/gather APIs
bus: fsl-mc: dpio: add global dpaa2 definitions
bus: fsl-mc: dpio: add QBMan portal APIs for DPAA2
bus: fsl-mc: dpio: add the DPAA2 DPIO service interface
bus: fsl-mc: dpio: add the DPAA2 DPIO object driver
bus: fsl-mc: dpio: add maintainer for DPIO
Stuart Yoder (2):
staging: fsl-mc: move bus driver out of staging
bus: fsl-mc: dpio: add DPIO driver overview document
Documentation/dpaa2/dpio-driver.txt | 135 +++
.../README.txt => Documentation/dpaa2/overview.txt | 0
MAINTAINERS | 6 +
drivers/bus/Kconfig | 3 +
drivers/bus/Makefile | 3 +
drivers/{staging/fsl-mc/bus => bus/fsl-mc}/Kconfig | 10 +
.../{staging/fsl-mc/bus => bus/fsl-mc}/Makefile | 4 +-
.../{staging/fsl-mc/bus => bus/fsl-mc}/dpbp-cmd.h | 0
drivers/{staging/fsl-mc/bus => bus/fsl-mc}/dpbp.c | 6 +-
.../{staging/fsl-mc/bus => bus/fsl-mc}/dpcon-cmd.h | 0
drivers/bus/fsl-mc/dpio/Makefile | 9 +
drivers/bus/fsl-mc/dpio/dpio-cmd.h | 198 ++++
drivers/bus/fsl-mc/dpio/dpio-driver.c | 289 ++++++
drivers/bus/fsl-mc/dpio/dpio-service.c | 614 ++++++++++++
drivers/bus/fsl-mc/dpio/dpio.c | 229 +++++
drivers/bus/fsl-mc/dpio/dpio.h | 108 +++
drivers/bus/fsl-mc/dpio/qbman-portal.c | 1009 ++++++++++++++++++++
drivers/bus/fsl-mc/dpio/qbman-portal.h | 464 +++++++++
.../{staging/fsl-mc/bus => bus/fsl-mc}/dpmcp-cmd.h | 0
drivers/{staging/fsl-mc/bus => bus/fsl-mc}/dpmcp.c | 5 +-
drivers/{staging/fsl-mc/bus => bus/fsl-mc}/dpmcp.h | 0
.../{staging/fsl-mc/bus => bus/fsl-mc}/dpmng-cmd.h | 0
drivers/{staging/fsl-mc/bus => bus/fsl-mc}/dpmng.c | 6 +-
.../{staging/fsl-mc/bus => bus/fsl-mc}/dprc-cmd.h | 0
.../fsl-mc/bus => bus/fsl-mc}/dprc-driver.c | 4 +-
drivers/{staging/fsl-mc/bus => bus/fsl-mc}/dprc.c | 6 +-
.../fsl-mc/bus => bus/fsl-mc}/fsl-mc-allocator.c | 4 +-
.../fsl-mc/bus => bus/fsl-mc}/fsl-mc-bus.c | 6 +-
.../fsl-mc/bus => bus/fsl-mc}/fsl-mc-msi.c | 2 +-
.../fsl-mc/bus => bus/fsl-mc}/fsl-mc-private.h | 4 +-
drivers/{staging/fsl-mc/bus => bus/fsl-mc}/mc-io.c | 4 +-
.../{staging/fsl-mc/bus => bus/fsl-mc}/mc-sys.c | 6 +-
drivers/irqchip/Makefile | 1 +
.../bus => irqchip}/irq-gic-v3-its-fsl-mc-msi.c | 2 +-
drivers/staging/Kconfig | 2 -
drivers/staging/Makefile | 1 -
drivers/staging/fsl-mc/Kconfig | 1 -
drivers/staging/fsl-mc/Makefile | 2 -
drivers/staging/fsl-mc/TODO | 18 -
include/linux/fsl/dpaa2-fd.h | 415 ++++++++
include/linux/fsl/dpaa2-global.h | 203 ++++
include/linux/fsl/dpaa2-io.h | 138 +++
.../fsl-mc/include => include/linux/fsl}/dpbp.h | 0
.../fsl-mc/include => include/linux/fsl}/dpmng.h | 0
.../fsl-mc/include => include/linux/fsl}/dprc.h | 0
.../fsl-mc/include => include/linux/fsl}/mc-bus.h | 2 +-
.../fsl-mc/include => include/linux/fsl}/mc-cmd.h | 0
.../fsl-mc/include => include/linux/fsl}/mc-sys.h | 0
.../fsl-mc/include => include/linux/fsl}/mc.h | 2 +-
49 files changed, 3867 insertions(+), 54 deletions(-)
create mode 100644 Documentation/dpaa2/dpio-driver.txt
rename drivers/staging/fsl-mc/README.txt => Documentation/dpaa2/overview.txt (100%)
rename drivers/{staging/fsl-mc/bus => bus/fsl-mc}/Kconfig (56%)
rename drivers/{staging/fsl-mc/bus => bus/fsl-mc}/Makefile (88%)
rename drivers/{staging/fsl-mc/bus => bus/fsl-mc}/dpbp-cmd.h (100%)
rename drivers/{staging/fsl-mc/bus => bus/fsl-mc}/dpbp.c (99%)
rename drivers/{staging/fsl-mc/bus => bus/fsl-mc}/dpcon-cmd.h (100%)
create mode 100644 drivers/bus/fsl-mc/dpio/Makefile
create mode 100644 drivers/bus/fsl-mc/dpio/dpio-cmd.h
create mode 100644 drivers/bus/fsl-mc/dpio/dpio-driver.c
create mode 100644 drivers/bus/fsl-mc/dpio/dpio-service.c
create mode 100644 drivers/bus/fsl-mc/dpio/dpio.c
create mode 100644 drivers/bus/fsl-mc/dpio/dpio.h
create mode 100644 drivers/bus/fsl-mc/dpio/qbman-portal.c
create mode 100644 drivers/bus/fsl-mc/dpio/qbman-portal.h
rename drivers/{staging/fsl-mc/bus => bus/fsl-mc}/dpmcp-cmd.h (100%)
rename drivers/{staging/fsl-mc/bus => bus/fsl-mc}/dpmcp.c (99%)
rename drivers/{staging/fsl-mc/bus => bus/fsl-mc}/dpmcp.h (100%)
rename drivers/{staging/fsl-mc/bus => bus/fsl-mc}/dpmng-cmd.h (100%)
rename drivers/{staging/fsl-mc/bus => bus/fsl-mc}/dpmng.c (96%)
rename drivers/{staging/fsl-mc/bus => bus/fsl-mc}/dprc-cmd.h (100%)
rename drivers/{staging/fsl-mc/bus => bus/fsl-mc}/dprc-driver.c (99%)
rename drivers/{staging/fsl-mc/bus => bus/fsl-mc}/dprc.c (99%)
rename drivers/{staging/fsl-mc/bus => bus/fsl-mc}/fsl-mc-allocator.c (99%)
rename drivers/{staging/fsl-mc/bus => bus/fsl-mc}/fsl-mc-bus.c (99%)
rename drivers/{staging/fsl-mc/bus => bus/fsl-mc}/fsl-mc-msi.c (99%)
rename drivers/{staging/fsl-mc/bus => bus/fsl-mc}/fsl-mc-private.h (96%)
rename drivers/{staging/fsl-mc/bus => bus/fsl-mc}/mc-io.c (99%)
rename drivers/{staging/fsl-mc/bus => bus/fsl-mc}/mc-sys.c (99%)
rename drivers/{staging/fsl-mc/bus => irqchip}/irq-gic-v3-its-fsl-mc-msi.c (99%)
delete mode 100644 drivers/staging/fsl-mc/Kconfig
delete mode 100644 drivers/staging/fsl-mc/Makefile
delete mode 100644 drivers/staging/fsl-mc/TODO
create mode 100644 include/linux/fsl/dpaa2-fd.h
create mode 100644 include/linux/fsl/dpaa2-global.h
create mode 100644 include/linux/fsl/dpaa2-io.h
rename {drivers/staging/fsl-mc/include => include/linux/fsl}/dpbp.h (100%)
rename {drivers/staging/fsl-mc/include => include/linux/fsl}/dpmng.h (100%)
rename {drivers/staging/fsl-mc/include => include/linux/fsl}/dprc.h (100%)
rename {drivers/staging/fsl-mc/include => include/linux/fsl}/mc-bus.h (99%)
rename {drivers/staging/fsl-mc/include => include/linux/fsl}/mc-cmd.h (100%)
rename {drivers/staging/fsl-mc/include => include/linux/fsl}/mc-sys.h (100%)
rename {drivers/staging/fsl-mc/include => include/linux/fsl}/mc.h (99%)
--
1.9.0
From: Roy Pledge <[email protected]>
Add global definitions for DPAA2 frame descriptors and scatter
gather entries.
Signed-off-by: Roy Pledge <[email protected]>
Signed-off-by: Stuart Yoder <[email protected]>
---
include/linux/fsl/dpaa2-fd.h | 415 +++++++++++++++++++++++++++++++++++++++++++
1 file changed, 415 insertions(+)
create mode 100644 include/linux/fsl/dpaa2-fd.h
diff --git a/include/linux/fsl/dpaa2-fd.h b/include/linux/fsl/dpaa2-fd.h
new file mode 100644
index 0000000..b3fa9ff
--- /dev/null
+++ b/include/linux/fsl/dpaa2-fd.h
@@ -0,0 +1,415 @@
+/*
+ * Copyright 2014-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:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef __FSL_DPAA2_FD_H
+#define __FSL_DPAA2_FD_H
+
+#include <linux/kernel.h>
+
+/**
+ * DOC: DPAA2 FD - Frame Descriptor APIs for DPAA2
+ *
+ * Frame Descriptors (FDs) are used to describe frame data in the DPAA2.
+ * Frames can be enqueued and dequeued to Frame Queues (FQs) which are consumed
+ * by the various DPAA accelerators (WRIOP, SEC, PME, DCE)
+ *
+ * There are three types of frames: single, scatter gather, and frame lists.
+ *
+ * The set of APIs in this file must be used to create, manipulate and
+ * query Frame Descriptors.
+ */
+
+/**
+ * struct dpaa2_fd - Struct describing FDs
+ * @words: for easier/faster copying the whole FD structure
+ * @addr: address in the FD
+ * @len: length in the FD
+ * @bpid: buffer pool ID
+ * @format_offset: format and offset fields
+ * @frc: frame context
+ * @ctrl: control bits...including dd, sc, va, err, etc
+ * @flc: flow context address
+ *
+ * This structure represents the basic Frame Descriptor used in the system.
+ */
+struct dpaa2_fd {
+ union {
+ u32 words[8];
+ struct dpaa2_fd_simple {
+ __le64 addr;
+ __le32 len;
+ __le16 bpid;
+ __le16 format_offset;
+ __le32 frc;
+ __le32 ctrl;
+ __le64 flc;
+ } simple;
+ };
+};
+
+#define FD_OFFSET_MASK 0x0FFF
+#define FD_FORMAT_MASK 0x3
+#define FD_FORMAT_SHIFT 12
+#define SG_SHORT_LEN_FLAG_MASK 0x1
+#define SG_SHORT_LEN_FLAG_SHIFT 14
+#define SG_SHORT_LEN_MASK 0x1FFFF
+#define SG_OFFSET_MASK 0x0FFF
+#define SG_FORMAT_MASK 0x3
+#define SG_FORMAT_SHIFT 12
+#define SG_BPID_MASK 0x3FFF
+#define SG_FINAL_FLAG_MASK 0x1
+#define SG_FINAL_FLAG_SHIFT 15
+
+enum dpaa2_fd_format {
+ dpaa2_fd_single = 0,
+ dpaa2_fd_list,
+ dpaa2_fd_sg
+};
+
+/**
+ * dpaa2_fd_get_addr() - get the addr field of frame descriptor
+ * @fd: the given frame descriptor
+ *
+ * Return the address in the frame descriptor.
+ */
+static inline dma_addr_t dpaa2_fd_get_addr(const struct dpaa2_fd *fd)
+{
+
+ return (dma_addr_t)fd->simple.addr;
+}
+
+/**
+ * dpaa2_fd_set_addr() - Set the addr field of frame descriptor
+ * @fd: the given frame descriptor
+ * @addr: the address needs to be set in frame descriptor
+ */
+static inline void dpaa2_fd_set_addr(struct dpaa2_fd *fd, dma_addr_t addr)
+{
+ fd->simple.addr = addr;
+}
+
+/**
+ * dpaa2_fd_get_frc() - Get the frame context in the frame descriptor
+ * @fd: the given frame descriptor
+ *
+ * Return the frame context field in the frame descriptor.
+ */
+static inline u32 dpaa2_fd_get_frc(const struct dpaa2_fd *fd)
+{
+ return fd->simple.frc;
+}
+
+/**
+ * dpaa2_fd_set_frc() - Set the frame context in the frame descriptor
+ * @fd: the given frame descriptor
+ * @frc: the frame context needs to be set in frame descriptor
+ */
+static inline void dpaa2_fd_set_frc(struct dpaa2_fd *fd, u32 frc)
+{
+ fd->simple.frc = frc;
+}
+
+/**
+ * dpaa2_fd_get_flc() - Get the flow context in the frame descriptor
+ * @fd: the given frame descriptor
+ *
+ * Return the flow context in the frame descriptor.
+ */
+static inline dma_addr_t dpaa2_fd_get_flc(const struct dpaa2_fd *fd)
+{
+ return (dma_addr_t)fd->simple.flc;
+}
+
+/**
+ * dpaa2_fd_set_flc() - Set the flow context field of frame descriptor
+ * @fd: the given frame descriptor
+ * @flc_addr: the flow context needs to be set in frame descriptor
+ */
+static inline void dpaa2_fd_set_flc(struct dpaa2_fd *fd, dma_addr_t flc_addr)
+{
+ fd->simple.flc = flc_addr;
+}
+
+/**
+ * dpaa2_fd_get_len() - Get the length in the frame descriptor
+ * @fd: the given frame descriptor
+ *
+ * Return the length field in the frame descriptor.
+ */
+static inline u32 dpaa2_fd_get_len(const struct dpaa2_fd *fd)
+{
+ return fd->simple.len;
+}
+
+/**
+ * dpaa2_fd_set_len() - Set the length field of frame descriptor
+ * @fd: the given frame descriptor
+ * @len: the length needs to be set in frame descriptor
+ */
+static inline void dpaa2_fd_set_len(struct dpaa2_fd *fd, u32 len)
+{
+ fd->simple.len = len;
+}
+
+/**
+ * dpaa2_fd_get_offset() - Get the offset field in the frame descriptor
+ * @fd: the given frame descriptor
+ *
+ * Return the offset.
+ */
+static inline uint16_t dpaa2_fd_get_offset(const struct dpaa2_fd *fd)
+{
+ return fd->simple.format_offset & FD_OFFSET_MASK;
+}
+
+/**
+ * dpaa2_fd_set_offset() - Set the offset field of frame descriptor
+ * @fd: the given frame descriptor
+ * @offset: the offset needs to be set in frame descriptor
+ */
+static inline void dpaa2_fd_set_offset(struct dpaa2_fd *fd, uint16_t offset)
+{
+ fd->simple.format_offset &= ~(FD_OFFSET_MASK);
+ fd->simple.format_offset |= offset;
+}
+
+/**
+ * dpaa2_fd_get_format() - Get the format field in the frame descriptor
+ * @fd: the given frame descriptor
+ *
+ * Return the format.
+ */
+static inline enum dpaa2_fd_format dpaa2_fd_get_format(
+ const struct dpaa2_fd *fd)
+{
+ return (enum dpaa2_fd_format)((fd->simple.format_offset
+ >> FD_FORMAT_SHIFT) & FD_FORMAT_MASK);
+}
+
+/**
+ * dpaa2_fd_set_format() - Set the format field of frame descriptor
+ * @fd: the given frame descriptor
+ * @format: the format needs to be set in frame descriptor
+ */
+static inline void dpaa2_fd_set_format(struct dpaa2_fd *fd,
+ enum dpaa2_fd_format format)
+{
+ fd->simple.format_offset &= ~(FD_FORMAT_MASK << FD_FORMAT_SHIFT);
+ fd->simple.format_offset |= format << FD_FORMAT_SHIFT;
+}
+
+/**
+ * dpaa2_fd_get_bpid() - Get the bpid field in the frame descriptor
+ * @fd: the given frame descriptor
+ *
+ * Return the buffer pool id.
+ */
+static inline uint16_t dpaa2_fd_get_bpid(const struct dpaa2_fd *fd)
+{
+ return fd->simple.bpid;
+}
+
+/**
+ * dpaa2_fd_set_bpid() - Set the bpid field of frame descriptor
+ * @fd: the given frame descriptor
+ * @bpid: buffer pool id to be set
+ */
+static inline void dpaa2_fd_set_bpid(struct dpaa2_fd *fd, uint16_t bpid)
+{
+ fd->simple.bpid = bpid;
+}
+
+/**
+ * struct dpaa2_sg_entry - the scatter-gathering structure
+ * @addr: address of the sg entry
+ * @len: length in this sg entry
+ * @bpid: buffer pool id
+ * @format_offset: offset in the MS 16 bits, BPID in the LS 16 bits
+ */
+struct dpaa2_sg_entry {
+ __le64 addr;
+ __le32 len;
+ __le16 bpid;
+ __le16 format_offset;
+};
+
+enum dpaa2_sg_format {
+ dpaa2_sg_single = 0,
+ dpaa2_sg_frame_data,
+ dpaa2_sg_sgt_ext
+};
+
+/* Accessors for SG entry fields */
+
+/**
+ * dpaa2_sg_get_addr() - Get the address from SG entry
+ * @sg: the given scatter-gathering object
+ *
+ * Return the address.
+ */
+static inline dma_addr_t dpaa2_sg_get_addr(const struct dpaa2_sg_entry *sg)
+{
+ return le64_to_cpu((dma_addr_t)sg->addr);
+}
+
+/**
+ * dpaa2_sg_set_addr() - Set the address in SG entry
+ * @sg: the given scatter-gathering object
+ * @addr: the address to be set
+ */
+static inline void dpaa2_sg_set_addr(struct dpaa2_sg_entry *sg, dma_addr_t addr)
+{
+ sg->addr = cpu_to_le64(addr);
+}
+
+static inline bool dpaa2_sg_short_len(const struct dpaa2_sg_entry *sg)
+{
+ return (le16_to_cpu(sg->format_offset) >> SG_SHORT_LEN_FLAG_SHIFT)
+ & SG_SHORT_LEN_FLAG_MASK;
+}
+
+/**
+ * dpaa2_sg_get_len() - Get the length in SG entry
+ * @sg: the given scatter-gathering object
+ *
+ * Return the length.
+ */
+static inline u32 dpaa2_sg_get_len(const struct dpaa2_sg_entry *sg)
+{
+ if (dpaa2_sg_short_len(sg))
+ return le32_to_cpu(sg->len) & SG_SHORT_LEN_MASK;
+
+ return le32_to_cpu(sg->len);
+}
+
+/**
+ * dpaa2_sg_set_len() - Set the length in SG entry
+ * @sg: the given scatter-gathering object
+ * @len: the length to be set
+ */
+static inline void dpaa2_sg_set_len(struct dpaa2_sg_entry *sg, u32 len)
+{
+ sg->len = cpu_to_le32(len);
+}
+
+/**
+ * dpaa2_sg_get_offset() - Get the offset in SG entry
+ * @sg: the given scatter-gathering object
+ *
+ * Return the offset.
+ */
+static inline u16 dpaa2_sg_get_offset(const struct dpaa2_sg_entry *sg)
+{
+ return le16_to_cpu(sg->format_offset) & SG_OFFSET_MASK;
+}
+
+/**
+ * dpaa2_sg_set_offset() - Set the offset in SG entry
+ * @sg: the given scatter-gathering object
+ * @offset: the offset to be set
+ */
+static inline void dpaa2_sg_set_offset(struct dpaa2_sg_entry *sg,
+ u16 offset)
+{
+ sg->format_offset &= cpu_to_le16(~(SG_OFFSET_MASK));
+ sg->format_offset |= cpu_to_le16(offset);
+}
+
+/**
+ * dpaa2_sg_get_format() - Get the SG format in SG entry
+ * @sg: the given scatter-gathering object
+ *
+ * Return the format.
+ */
+static inline enum dpaa2_sg_format
+ dpaa2_sg_get_format(const struct dpaa2_sg_entry *sg)
+{
+ return (enum dpaa2_sg_format)((le16_to_cpu(sg->format_offset)
+ >> SG_FORMAT_SHIFT) & SG_FORMAT_MASK);
+}
+
+/**
+ * dpaa2_sg_set_format() - Set the SG format in SG entry
+ * @sg: the given scatter-gathering object
+ * @format: the format to be set
+ */
+static inline void dpaa2_sg_set_format(struct dpaa2_sg_entry *sg,
+ enum dpaa2_sg_format format)
+{
+ sg->format_offset &= cpu_to_le16(~(SG_FORMAT_MASK << SG_FORMAT_SHIFT));
+ sg->format_offset |= cpu_to_le16(format << SG_FORMAT_SHIFT);
+}
+
+/**
+ * dpaa2_sg_get_bpid() - Get the buffer pool id in SG entry
+ * @sg: the given scatter-gathering object
+ *
+ * Return the bpid.
+ */
+static inline u16 dpaa2_sg_get_bpid(const struct dpaa2_sg_entry *sg)
+{
+ return le16_to_cpu(sg->bpid) & SG_BPID_MASK;
+}
+
+/**
+ * dpaa2_sg_set_bpid() - Set the buffer pool id in SG entry
+ * @sg: the given scatter-gathering object
+ * @bpid: the bpid to be set
+ */
+static inline void dpaa2_sg_set_bpid(struct dpaa2_sg_entry *sg, u16 bpid)
+{
+ sg->bpid &= cpu_to_le16(~(SG_BPID_MASK));
+ sg->bpid |= cpu_to_le16(bpid);
+}
+
+/**
+ * dpaa2_sg_is_final() - Check final bit in SG entry
+ * @sg: the given scatter-gathering object
+ *
+ * Return bool.
+ */
+static inline bool dpaa2_sg_is_final(const struct dpaa2_sg_entry *sg)
+{
+ return !!(le16_to_cpu(sg->format_offset) >> SG_FINAL_FLAG_SHIFT);
+}
+
+/**
+ * dpaa2_sg_set_final() - Set the final bit in SG entry
+ * @sg: the given scatter-gathering object
+ * @final: the final boolean to be set
+ */
+static inline void dpaa2_sg_set_final(struct dpaa2_sg_entry *sg, bool final)
+{
+ sg->format_offset &= cpu_to_le16(~(SG_FINAL_FLAG_MASK
+ << SG_FINAL_FLAG_SHIFT));
+ sg->format_offset |= cpu_to_le16(final << SG_FINAL_FLAG_SHIFT);
+}
+
+#endif /* __FSL_DPAA2_FD_H */
--
1.9.0
Move the source files out of staging into their final locations:
-include files in drivers/staging/fsl-mc/include go to include/linux/fsl
-irq-gic-v3-its-fsl-mc-msi.c goes to drivers/irqchip
-source in drivers/staging/fsl-mc/bus goes to drivers/bus/fsl-mc
-README.txt, providing and overview of DPAA goes to
Documentation/dpaa2/overview.txt
Delete other remaining staging files-- Makefile, Kconfig, TODO
cc: Thomas Gleixner <[email protected]>
cc: Jason Cooper <[email protected]>
cc: Marc Zyngier <[email protected]>
Signed-off-by: Stuart Yoder <[email protected]>
---
.../README.txt => Documentation/dpaa2/overview.txt | 0
drivers/bus/Kconfig | 3 +++
drivers/bus/Makefile | 3 +++
drivers/{staging/fsl-mc/bus => bus/fsl-mc}/Kconfig | 0
drivers/{staging/fsl-mc/bus => bus/fsl-mc}/Makefile | 1 -
drivers/{staging/fsl-mc/bus => bus/fsl-mc}/dpbp-cmd.h | 0
drivers/{staging/fsl-mc/bus => bus/fsl-mc}/dpbp.c | 6 +++---
drivers/{staging/fsl-mc/bus => bus/fsl-mc}/dpcon-cmd.h | 0
drivers/{staging/fsl-mc/bus => bus/fsl-mc}/dpmcp-cmd.h | 0
drivers/{staging/fsl-mc/bus => bus/fsl-mc}/dpmcp.c | 5 +++--
drivers/{staging/fsl-mc/bus => bus/fsl-mc}/dpmcp.h | 0
drivers/{staging/fsl-mc/bus => bus/fsl-mc}/dpmng-cmd.h | 0
drivers/{staging/fsl-mc/bus => bus/fsl-mc}/dpmng.c | 6 +++---
drivers/{staging/fsl-mc/bus => bus/fsl-mc}/dprc-cmd.h | 0
.../{staging/fsl-mc/bus => bus/fsl-mc}/dprc-driver.c | 4 ++--
drivers/{staging/fsl-mc/bus => bus/fsl-mc}/dprc.c | 6 +++---
.../fsl-mc/bus => bus/fsl-mc}/fsl-mc-allocator.c | 4 ++--
.../{staging/fsl-mc/bus => bus/fsl-mc}/fsl-mc-bus.c | 6 +++---
.../{staging/fsl-mc/bus => bus/fsl-mc}/fsl-mc-msi.c | 2 +-
.../fsl-mc/bus => bus/fsl-mc}/fsl-mc-private.h | 4 ++--
drivers/{staging/fsl-mc/bus => bus/fsl-mc}/mc-io.c | 4 ++--
drivers/{staging/fsl-mc/bus => bus/fsl-mc}/mc-sys.c | 6 +++---
drivers/irqchip/Makefile | 1 +
.../fsl-mc/bus => irqchip}/irq-gic-v3-its-fsl-mc-msi.c | 2 +-
drivers/staging/Kconfig | 2 --
drivers/staging/Makefile | 1 -
drivers/staging/fsl-mc/Kconfig | 1 -
drivers/staging/fsl-mc/Makefile | 2 --
drivers/staging/fsl-mc/TODO | 18 ------------------
.../fsl-mc/include => include/linux/fsl}/dpbp.h | 0
.../fsl-mc/include => include/linux/fsl}/dpmng.h | 0
.../fsl-mc/include => include/linux/fsl}/dprc.h | 0
.../fsl-mc/include => include/linux/fsl}/mc-bus.h | 2 +-
.../fsl-mc/include => include/linux/fsl}/mc-cmd.h | 0
.../fsl-mc/include => include/linux/fsl}/mc-sys.h | 0
.../staging/fsl-mc/include => include/linux/fsl}/mc.h | 2 +-
36 files changed, 37 insertions(+), 54 deletions(-)
rename drivers/staging/fsl-mc/README.txt => Documentation/dpaa2/overview.txt (100%)
rename drivers/{staging/fsl-mc/bus => bus/fsl-mc}/Kconfig (100%)
rename drivers/{staging/fsl-mc/bus => bus/fsl-mc}/Makefile (91%)
rename drivers/{staging/fsl-mc/bus => bus/fsl-mc}/dpbp-cmd.h (100%)
rename drivers/{staging/fsl-mc/bus => bus/fsl-mc}/dpbp.c (99%)
rename drivers/{staging/fsl-mc/bus => bus/fsl-mc}/dpcon-cmd.h (100%)
rename drivers/{staging/fsl-mc/bus => bus/fsl-mc}/dpmcp-cmd.h (100%)
rename drivers/{staging/fsl-mc/bus => bus/fsl-mc}/dpmcp.c (99%)
rename drivers/{staging/fsl-mc/bus => bus/fsl-mc}/dpmcp.h (100%)
rename drivers/{staging/fsl-mc/bus => bus/fsl-mc}/dpmng-cmd.h (100%)
rename drivers/{staging/fsl-mc/bus => bus/fsl-mc}/dpmng.c (96%)
rename drivers/{staging/fsl-mc/bus => bus/fsl-mc}/dprc-cmd.h (100%)
rename drivers/{staging/fsl-mc/bus => bus/fsl-mc}/dprc-driver.c (99%)
rename drivers/{staging/fsl-mc/bus => bus/fsl-mc}/dprc.c (99%)
rename drivers/{staging/fsl-mc/bus => bus/fsl-mc}/fsl-mc-allocator.c (99%)
rename drivers/{staging/fsl-mc/bus => bus/fsl-mc}/fsl-mc-bus.c (99%)
rename drivers/{staging/fsl-mc/bus => bus/fsl-mc}/fsl-mc-msi.c (99%)
rename drivers/{staging/fsl-mc/bus => bus/fsl-mc}/fsl-mc-private.h (96%)
rename drivers/{staging/fsl-mc/bus => bus/fsl-mc}/mc-io.c (99%)
rename drivers/{staging/fsl-mc/bus => bus/fsl-mc}/mc-sys.c (99%)
rename drivers/{staging/fsl-mc/bus => irqchip}/irq-gic-v3-its-fsl-mc-msi.c (99%)
delete mode 100644 drivers/staging/fsl-mc/Kconfig
delete mode 100644 drivers/staging/fsl-mc/Makefile
delete mode 100644 drivers/staging/fsl-mc/TODO
rename {drivers/staging/fsl-mc/include => include/linux/fsl}/dpbp.h (100%)
rename {drivers/staging/fsl-mc/include => include/linux/fsl}/dpmng.h (100%)
rename {drivers/staging/fsl-mc/include => include/linux/fsl}/dprc.h (100%)
rename {drivers/staging/fsl-mc/include => include/linux/fsl}/mc-bus.h (99%)
rename {drivers/staging/fsl-mc/include => include/linux/fsl}/mc-cmd.h (100%)
rename {drivers/staging/fsl-mc/include => include/linux/fsl}/mc-sys.h (100%)
rename {drivers/staging/fsl-mc/include => include/linux/fsl}/mc.h (99%)
diff --git a/drivers/staging/fsl-mc/README.txt b/Documentation/dpaa2/overview.txt
similarity index 100%
rename from drivers/staging/fsl-mc/README.txt
rename to Documentation/dpaa2/overview.txt
diff --git a/drivers/bus/Kconfig b/drivers/bus/Kconfig
index 7010dca..7d0e096 100644
--- a/drivers/bus/Kconfig
+++ b/drivers/bus/Kconfig
@@ -166,4 +166,7 @@ config VEXPRESS_CONFIG
help
Platform configuration infrastructure for the ARM Ltd.
Versatile Express.
+
+source "drivers/bus/fsl-mc/Kconfig"
+
endmenu
diff --git a/drivers/bus/Makefile b/drivers/bus/Makefile
index c6cfa6b..4521ab1 100644
--- a/drivers/bus/Makefile
+++ b/drivers/bus/Makefile
@@ -14,6 +14,9 @@ obj-$(CONFIG_MVEBU_MBUS) += mvebu-mbus.o
# Interconnect bus driver for OMAP SoCs.
obj-$(CONFIG_OMAP_INTERCONNECT) += omap_l3_smx.o omap_l3_noc.o
+# DPAA2 fsl-mc bus
+obj-$(CONFIG_FSL_MC_BUS) += fsl-mc/
+
obj-$(CONFIG_OMAP_OCP2SCP) += omap-ocp2scp.o
obj-$(CONFIG_QCOM_EBI2) += qcom-ebi2.o
obj-$(CONFIG_SUNXI_RSB) += sunxi-rsb.o
diff --git a/drivers/staging/fsl-mc/bus/Kconfig b/drivers/bus/fsl-mc/Kconfig
similarity index 100%
rename from drivers/staging/fsl-mc/bus/Kconfig
rename to drivers/bus/fsl-mc/Kconfig
diff --git a/drivers/staging/fsl-mc/bus/Makefile b/drivers/bus/fsl-mc/Makefile
similarity index 91%
rename from drivers/staging/fsl-mc/bus/Makefile
rename to drivers/bus/fsl-mc/Makefile
index 38716fd..d56afee 100644
--- a/drivers/staging/fsl-mc/bus/Makefile
+++ b/drivers/bus/fsl-mc/Makefile
@@ -15,6 +15,5 @@ mc-bus-driver-objs := fsl-mc-bus.o \
dprc-driver.o \
fsl-mc-allocator.o \
fsl-mc-msi.o \
- irq-gic-v3-its-fsl-mc-msi.o \
dpmcp.o \
dpbp.o
diff --git a/drivers/staging/fsl-mc/bus/dpbp-cmd.h b/drivers/bus/fsl-mc/dpbp-cmd.h
similarity index 100%
rename from drivers/staging/fsl-mc/bus/dpbp-cmd.h
rename to drivers/bus/fsl-mc/dpbp-cmd.h
diff --git a/drivers/staging/fsl-mc/bus/dpbp.c b/drivers/bus/fsl-mc/dpbp.c
similarity index 99%
rename from drivers/staging/fsl-mc/bus/dpbp.c
rename to drivers/bus/fsl-mc/dpbp.c
index cf4782f..f70e509 100644
--- a/drivers/staging/fsl-mc/bus/dpbp.c
+++ b/drivers/bus/fsl-mc/dpbp.c
@@ -29,9 +29,9 @@
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
-#include "../include/mc-sys.h"
-#include "../include/mc-cmd.h"
-#include "../include/dpbp.h"
+#include <linux/fsl/mc-sys.h>
+#include <linux/fsl/mc-cmd.h>
+#include <linux/fsl/dpbp.h>
#include "dpbp-cmd.h"
diff --git a/drivers/staging/fsl-mc/bus/dpcon-cmd.h b/drivers/bus/fsl-mc/dpcon-cmd.h
similarity index 100%
rename from drivers/staging/fsl-mc/bus/dpcon-cmd.h
rename to drivers/bus/fsl-mc/dpcon-cmd.h
diff --git a/drivers/staging/fsl-mc/bus/dpmcp-cmd.h b/drivers/bus/fsl-mc/dpmcp-cmd.h
similarity index 100%
rename from drivers/staging/fsl-mc/bus/dpmcp-cmd.h
rename to drivers/bus/fsl-mc/dpmcp-cmd.h
diff --git a/drivers/staging/fsl-mc/bus/dpmcp.c b/drivers/bus/fsl-mc/dpmcp.c
similarity index 99%
rename from drivers/staging/fsl-mc/bus/dpmcp.c
rename to drivers/bus/fsl-mc/dpmcp.c
index e4d1651..00db8e9 100644
--- a/drivers/staging/fsl-mc/bus/dpmcp.c
+++ b/drivers/bus/fsl-mc/dpmcp.c
@@ -29,8 +29,9 @@
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
-#include "../include/mc-sys.h"
-#include "../include/mc-cmd.h"
+
+#include <linux/fsl/mc-sys.h>
+#include <linux/fsl/mc-cmd.h>
#include "dpmcp.h"
#include "dpmcp-cmd.h"
diff --git a/drivers/staging/fsl-mc/bus/dpmcp.h b/drivers/bus/fsl-mc/dpmcp.h
similarity index 100%
rename from drivers/staging/fsl-mc/bus/dpmcp.h
rename to drivers/bus/fsl-mc/dpmcp.h
diff --git a/drivers/staging/fsl-mc/bus/dpmng-cmd.h b/drivers/bus/fsl-mc/dpmng-cmd.h
similarity index 100%
rename from drivers/staging/fsl-mc/bus/dpmng-cmd.h
rename to drivers/bus/fsl-mc/dpmng-cmd.h
diff --git a/drivers/staging/fsl-mc/bus/dpmng.c b/drivers/bus/fsl-mc/dpmng.c
similarity index 96%
rename from drivers/staging/fsl-mc/bus/dpmng.c
rename to drivers/bus/fsl-mc/dpmng.c
index ad5d5bb..312fa0ee 100644
--- a/drivers/staging/fsl-mc/bus/dpmng.c
+++ b/drivers/bus/fsl-mc/dpmng.c
@@ -29,9 +29,9 @@
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
-#include "../include/mc-sys.h"
-#include "../include/mc-cmd.h"
-#include "../include/dpmng.h"
+#include <linux/fsl/mc-sys.h>
+#include <linux/fsl/mc-cmd.h>
+#include <linux/fsl/dpmng.h>
#include "dpmng-cmd.h"
diff --git a/drivers/staging/fsl-mc/bus/dprc-cmd.h b/drivers/bus/fsl-mc/dprc-cmd.h
similarity index 100%
rename from drivers/staging/fsl-mc/bus/dprc-cmd.h
rename to drivers/bus/fsl-mc/dprc-cmd.h
diff --git a/drivers/staging/fsl-mc/bus/dprc-driver.c b/drivers/bus/fsl-mc/dprc-driver.c
similarity index 99%
rename from drivers/staging/fsl-mc/bus/dprc-driver.c
rename to drivers/bus/fsl-mc/dprc-driver.c
index 4e416d8..b20e060 100644
--- a/drivers/staging/fsl-mc/bus/dprc-driver.c
+++ b/drivers/bus/fsl-mc/dprc-driver.c
@@ -13,8 +13,8 @@
#include <linux/slab.h>
#include <linux/interrupt.h>
#include <linux/msi.h>
-#include "../include/mc-bus.h"
-#include "../include/mc-sys.h"
+#include <linux/fsl/mc-sys.h>
+#include <linux/fsl/mc-cmd.h>
#include "dprc-cmd.h"
#include "fsl-mc-private.h"
diff --git a/drivers/staging/fsl-mc/bus/dprc.c b/drivers/bus/fsl-mc/dprc.c
similarity index 99%
rename from drivers/staging/fsl-mc/bus/dprc.c
rename to drivers/bus/fsl-mc/dprc.c
index 572edd4..e2ebfb7 100644
--- a/drivers/staging/fsl-mc/bus/dprc.c
+++ b/drivers/bus/fsl-mc/dprc.c
@@ -29,9 +29,9 @@
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
-#include "../include/mc-sys.h"
-#include "../include/mc-cmd.h"
-#include "../include/dprc.h"
+#include <linux/fsl/mc-sys.h>
+#include <linux/fsl/mc-cmd.h>
+#include <linux/fsl/dprc.h>
#include "dprc-cmd.h"
diff --git a/drivers/staging/fsl-mc/bus/fsl-mc-allocator.c b/drivers/bus/fsl-mc/fsl-mc-allocator.c
similarity index 99%
rename from drivers/staging/fsl-mc/bus/fsl-mc-allocator.c
rename to drivers/bus/fsl-mc/fsl-mc-allocator.c
index ce07096..679574b 100644
--- a/drivers/staging/fsl-mc/bus/fsl-mc-allocator.c
+++ b/drivers/bus/fsl-mc/fsl-mc-allocator.c
@@ -10,8 +10,8 @@
#include <linux/module.h>
#include <linux/msi.h>
-#include "../include/mc-bus.h"
-#include "../include/mc-sys.h"
+#include <linux/fsl/mc-sys.h>
+#include <linux/fsl/mc-cmd.h>
#include "dpbp-cmd.h"
#include "dpcon-cmd.h"
diff --git a/drivers/staging/fsl-mc/bus/fsl-mc-bus.c b/drivers/bus/fsl-mc/fsl-mc-bus.c
similarity index 99%
rename from drivers/staging/fsl-mc/bus/fsl-mc-bus.c
rename to drivers/bus/fsl-mc/fsl-mc-bus.c
index 4e92437..e051b21 100644
--- a/drivers/staging/fsl-mc/bus/fsl-mc-bus.c
+++ b/drivers/bus/fsl-mc/fsl-mc-bus.c
@@ -18,9 +18,9 @@
#include <linux/bitops.h>
#include <linux/msi.h>
#include <linux/dma-mapping.h>
-#include "../include/mc-bus.h"
-#include "../include/dpmng.h"
-#include "../include/mc-sys.h"
+#include <linux/fsl/mc-bus.h>
+#include <linux/fsl/dpmng.h>
+#include <linux/fsl/mc-sys.h>
#include "fsl-mc-private.h"
#include "dprc-cmd.h"
diff --git a/drivers/staging/fsl-mc/bus/fsl-mc-msi.c b/drivers/bus/fsl-mc/fsl-mc-msi.c
similarity index 99%
rename from drivers/staging/fsl-mc/bus/fsl-mc-msi.c
rename to drivers/bus/fsl-mc/fsl-mc-msi.c
index 7975c6e..f2d6a22 100644
--- a/drivers/staging/fsl-mc/bus/fsl-mc-msi.c
+++ b/drivers/bus/fsl-mc/fsl-mc-msi.c
@@ -16,7 +16,7 @@
#include <linux/irq.h>
#include <linux/irqdomain.h>
#include <linux/msi.h>
-#include "../include/mc-bus.h"
+#include <linux/fsl/mc-bus.h>
/*
* Generate a unique ID identifying the interrupt (only used within the MSI
diff --git a/drivers/staging/fsl-mc/bus/fsl-mc-private.h b/drivers/bus/fsl-mc/fsl-mc-private.h
similarity index 96%
rename from drivers/staging/fsl-mc/bus/fsl-mc-private.h
rename to drivers/bus/fsl-mc/fsl-mc-private.h
index 5c49c9d..599425f 100644
--- a/drivers/staging/fsl-mc/bus/fsl-mc-private.h
+++ b/drivers/bus/fsl-mc/fsl-mc-private.h
@@ -10,8 +10,8 @@
#ifndef _FSL_MC_PRIVATE_H_
#define _FSL_MC_PRIVATE_H_
-#include "../include/mc.h"
-#include "../include/mc-bus.h"
+#include <linux/fsl/mc.h>
+#include <linux/fsl/mc-bus.h>
int __must_check fsl_mc_device_add(struct dprc_obj_desc *obj_desc,
struct fsl_mc_io *mc_io,
diff --git a/drivers/staging/fsl-mc/bus/mc-io.c b/drivers/bus/fsl-mc/mc-io.c
similarity index 99%
rename from drivers/staging/fsl-mc/bus/mc-io.c
rename to drivers/bus/fsl-mc/mc-io.c
index d66b87f..501fba3 100644
--- a/drivers/staging/fsl-mc/bus/mc-io.c
+++ b/drivers/bus/fsl-mc/mc-io.c
@@ -31,8 +31,8 @@
*/
#include <linux/io.h>
-#include "../include/mc-bus.h"
-#include "../include/mc-sys.h"
+#include <linux/fsl/mc-sys.h>
+#include <linux/fsl/mc-cmd.h>
#include "fsl-mc-private.h"
#include "dpmcp.h"
diff --git a/drivers/staging/fsl-mc/bus/mc-sys.c b/drivers/bus/fsl-mc/mc-sys.c
similarity index 99%
rename from drivers/staging/fsl-mc/bus/mc-sys.c
rename to drivers/bus/fsl-mc/mc-sys.c
index 4d82802..ac86226 100644
--- a/drivers/staging/fsl-mc/bus/mc-sys.c
+++ b/drivers/bus/fsl-mc/mc-sys.c
@@ -37,9 +37,9 @@
#include <linux/ioport.h>
#include <linux/device.h>
#include <linux/io.h>
-#include "../include/mc-sys.h"
-#include "../include/mc-cmd.h"
-#include "../include/mc.h"
+#include <linux/fsl/mc-sys.h>
+#include <linux/fsl/mc-cmd.h>
+#include <linux/fsl/mc.h>
#include "dpmcp.h"
diff --git a/drivers/irqchip/Makefile b/drivers/irqchip/Makefile
index e4dbfc8..075709d 100644
--- a/drivers/irqchip/Makefile
+++ b/drivers/irqchip/Makefile
@@ -74,3 +74,4 @@ obj-$(CONFIG_LS_SCFG_MSI) += irq-ls-scfg-msi.o
obj-$(CONFIG_EZNPS_GIC) += irq-eznps.o
obj-$(CONFIG_ARCH_ASPEED) += irq-aspeed-vic.o
obj-$(CONFIG_STM32_EXTI) += irq-stm32-exti.o
+obj-$(CONFIG_FSL_MC_BUS) += irq-gic-v3-its-fsl-mc-msi.o
diff --git a/drivers/staging/fsl-mc/bus/irq-gic-v3-its-fsl-mc-msi.c b/drivers/irqchip/irq-gic-v3-its-fsl-mc-msi.c
similarity index 99%
rename from drivers/staging/fsl-mc/bus/irq-gic-v3-its-fsl-mc-msi.c
rename to drivers/irqchip/irq-gic-v3-its-fsl-mc-msi.c
index 6b1cd57..347a3ea 100644
--- a/drivers/staging/fsl-mc/bus/irq-gic-v3-its-fsl-mc-msi.c
+++ b/drivers/irqchip/irq-gic-v3-its-fsl-mc-msi.c
@@ -16,7 +16,7 @@
#include <linux/msi.h>
#include <linux/of.h>
#include <linux/of_irq.h>
-#include "../include/mc-bus.h"
+#include <linux/fsl/mc-bus.h>
static struct irq_chip its_msi_irq_chip = {
.name = "ITS-fMSI",
diff --git a/drivers/staging/Kconfig b/drivers/staging/Kconfig
index 58a7b35..8d7a13f 100644
--- a/drivers/staging/Kconfig
+++ b/drivers/staging/Kconfig
@@ -92,8 +92,6 @@ source "drivers/staging/clocking-wizard/Kconfig"
source "drivers/staging/fbtft/Kconfig"
-source "drivers/staging/fsl-mc/Kconfig"
-
source "drivers/staging/wilc1000/Kconfig"
source "drivers/staging/most/Kconfig"
diff --git a/drivers/staging/Makefile b/drivers/staging/Makefile
index 2fa9745..8a88b1d 100644
--- a/drivers/staging/Makefile
+++ b/drivers/staging/Makefile
@@ -35,7 +35,6 @@ obj-$(CONFIG_CRYPTO_SKEIN) += skein/
obj-$(CONFIG_UNISYSSPAR) += unisys/
obj-$(CONFIG_COMMON_CLK_XLNX_CLKWZRD) += clocking-wizard/
obj-$(CONFIG_FB_TFT) += fbtft/
-obj-$(CONFIG_FSL_MC_BUS) += fsl-mc/
obj-$(CONFIG_WILC1000) += wilc1000/
obj-$(CONFIG_MOST) += most/
obj-$(CONFIG_ISDN_I4L) += i4l/
diff --git a/drivers/staging/fsl-mc/Kconfig b/drivers/staging/fsl-mc/Kconfig
deleted file mode 100644
index 32df07b..0000000
--- a/drivers/staging/fsl-mc/Kconfig
+++ /dev/null
@@ -1 +0,0 @@
-source "drivers/staging/fsl-mc/bus/Kconfig"
diff --git a/drivers/staging/fsl-mc/Makefile b/drivers/staging/fsl-mc/Makefile
deleted file mode 100644
index 9c6a001..0000000
--- a/drivers/staging/fsl-mc/Makefile
+++ /dev/null
@@ -1,2 +0,0 @@
-# Freescale Management Complex (MC) bus drivers
-obj-$(CONFIG_FSL_MC_BUS) += bus/
diff --git a/drivers/staging/fsl-mc/TODO b/drivers/staging/fsl-mc/TODO
deleted file mode 100644
index 54a8bc6..0000000
--- a/drivers/staging/fsl-mc/TODO
+++ /dev/null
@@ -1,18 +0,0 @@
-* Add at least one device driver for a DPAA2 object (child device of the
- fsl-mc bus). Most likely candidate for this is adding DPAA2 Ethernet
- driver support, which depends on drivers for several objects: DPNI,
- DPIO, DPMAC. Other pre-requisites include:
-
- * MC firmware uprev. The MC firmware upon which the fsl-mc
- bus driver and DPAA2 object drivers are based is continuing
- to evolve, so minor updates are needed to keep in sync with binary
- interface changes to the MC.
-
-* Cleanup
-
-Please send any patches to Greg Kroah-Hartman <[email protected]>,
[email protected], [email protected],
[email protected]
-
-[1] https://lkml.org/lkml/2015/7/9/93
-[2] https://lkml.org/lkml/2015/7/7/712
diff --git a/drivers/staging/fsl-mc/include/dpbp.h b/include/linux/fsl/dpbp.h
similarity index 100%
rename from drivers/staging/fsl-mc/include/dpbp.h
rename to include/linux/fsl/dpbp.h
diff --git a/drivers/staging/fsl-mc/include/dpmng.h b/include/linux/fsl/dpmng.h
similarity index 100%
rename from drivers/staging/fsl-mc/include/dpmng.h
rename to include/linux/fsl/dpmng.h
diff --git a/drivers/staging/fsl-mc/include/dprc.h b/include/linux/fsl/dprc.h
similarity index 100%
rename from drivers/staging/fsl-mc/include/dprc.h
rename to include/linux/fsl/dprc.h
diff --git a/drivers/staging/fsl-mc/include/mc-bus.h b/include/linux/fsl/mc-bus.h
similarity index 99%
rename from drivers/staging/fsl-mc/include/mc-bus.h
rename to include/linux/fsl/mc-bus.h
index e915574..7acf3f0 100644
--- a/drivers/staging/fsl-mc/include/mc-bus.h
+++ b/include/linux/fsl/mc-bus.h
@@ -11,7 +11,7 @@
#ifndef _FSL_MC_MCBUS_H_
#define _FSL_MC_MCBUS_H_
-#include "../include/mc.h"
+#include <linux/fsl/mc.h>
#include <linux/mutex.h>
struct irq_domain;
diff --git a/drivers/staging/fsl-mc/include/mc-cmd.h b/include/linux/fsl/mc-cmd.h
similarity index 100%
rename from drivers/staging/fsl-mc/include/mc-cmd.h
rename to include/linux/fsl/mc-cmd.h
diff --git a/drivers/staging/fsl-mc/include/mc-sys.h b/include/linux/fsl/mc-sys.h
similarity index 100%
rename from drivers/staging/fsl-mc/include/mc-sys.h
rename to include/linux/fsl/mc-sys.h
diff --git a/drivers/staging/fsl-mc/include/mc.h b/include/linux/fsl/mc.h
similarity index 99%
rename from drivers/staging/fsl-mc/include/mc.h
rename to include/linux/fsl/mc.h
index a781a36..cdba52a 100644
--- a/drivers/staging/fsl-mc/include/mc.h
+++ b/include/linux/fsl/mc.h
@@ -14,7 +14,7 @@
#include <linux/device.h>
#include <linux/mod_devicetable.h>
#include <linux/interrupt.h>
-#include "../include/dprc.h"
+#include <linux/fsl/dprc.h>
#define FSL_MC_VENDOR_FREESCALE 0x1957
--
1.9.0
From: Roy Pledge <[email protected]>
add Roy Pledge as maintainer of DPIO
Signed-off-by: Roy Pledge <[email protected]>
Signed-off-by: Stuart Yoder <[email protected]>
---
MAINTAINERS | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/MAINTAINERS b/MAINTAINERS
index 797a08a..1aa991e 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -5097,6 +5097,12 @@ L: [email protected]
S: Maintained
F: drivers/staging/fsl-mc/
+DPAA2 DATAPATH I/O (DPIO) DRIVER
+M: Roy Pledge <[email protected]>
+L: [email protected]
+S: Maintained
+F: drivers/bus/fsl-mc/dpio
+
FREEVXFS FILESYSTEM
M: Christoph Hellwig <[email protected]>
W: ftp://ftp.openlinux.org/pub/people/hch/vxfs
--
1.9.0
From: Roy Pledge <[email protected]>
Add QBman APIs for frame queue and buffer pool operations.
Signed-off-by: Roy Pledge <[email protected]>
Signed-off-by: Haiying Wang <[email protected]>
Signed-off-by: Stuart Yoder <[email protected]>
---
drivers/bus/fsl-mc/dpio/Makefile | 2 +-
drivers/bus/fsl-mc/dpio/qbman-portal.c | 1009 ++++++++++++++++++++++++++++++++
drivers/bus/fsl-mc/dpio/qbman-portal.h | 464 +++++++++++++++
3 files changed, 1474 insertions(+), 1 deletion(-)
create mode 100644 drivers/bus/fsl-mc/dpio/qbman-portal.c
create mode 100644 drivers/bus/fsl-mc/dpio/qbman-portal.h
diff --git a/drivers/bus/fsl-mc/dpio/Makefile b/drivers/bus/fsl-mc/dpio/Makefile
index 128befc..6588498 100644
--- a/drivers/bus/fsl-mc/dpio/Makefile
+++ b/drivers/bus/fsl-mc/dpio/Makefile
@@ -6,4 +6,4 @@ subdir-ccflags-y := -Werror
obj-$(CONFIG_FSL_MC_DPIO) += fsl-mc-dpio.o
-fsl-mc-dpio-objs := dpio.o
+fsl-mc-dpio-objs := dpio.o qbman-portal.o
diff --git a/drivers/bus/fsl-mc/dpio/qbman-portal.c b/drivers/bus/fsl-mc/dpio/qbman-portal.c
new file mode 100644
index 0000000..1eb3dd9
--- /dev/null
+++ b/drivers/bus/fsl-mc/dpio/qbman-portal.c
@@ -0,0 +1,1009 @@
+/*
+ * Copyright (C) 2014 Freescale Semiconductor, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <asm/cacheflush.h>
+#include <linux/io.h>
+#include <linux/slab.h>
+#include <linux/fsl/dpaa2-global.h>
+
+#include "qbman-portal.h"
+
+#define QMAN_REV_4000 0x04000000
+#define QMAN_REV_4100 0x04010000
+#define QMAN_REV_4101 0x04010001
+
+/* All QBMan command and result structures use this "valid bit" encoding */
+#define QB_VALID_BIT ((u32)0x80)
+
+/* QBMan portal management command codes */
+#define QBMAN_MC_ACQUIRE 0x30
+#define QBMAN_WQCHAN_CONFIGURE 0x46
+
+/* CINH register offsets */
+#define QBMAN_CINH_SWP_EQAR 0x8c0
+#define QBMAN_CINH_SWP_DQPI 0xa00
+#define QBMAN_CINH_SWP_DCAP 0xac0
+#define QBMAN_CINH_SWP_SDQCR 0xb00
+#define QBMAN_CINH_SWP_RAR 0xcc0
+#define QBMAN_CINH_SWP_ISR 0xe00
+#define QBMAN_CINH_SWP_IER 0xe40
+#define QBMAN_CINH_SWP_ISDR 0xe80
+#define QBMAN_CINH_SWP_IIR 0xec0
+
+/* CENA register offsets */
+#define QBMAN_CENA_SWP_EQCR(n) (0x000 + ((u32)(n) << 6))
+#define QBMAN_CENA_SWP_DQRR(n) (0x200 + ((u32)(n) << 6))
+#define QBMAN_CENA_SWP_RCR(n) (0x400 + ((u32)(n) << 6))
+#define QBMAN_CENA_SWP_CR 0x600
+#define QBMAN_CENA_SWP_RR(vb) (0x700 + ((u32)(vb) >> 1))
+#define QBMAN_CENA_SWP_VDQCR 0x780
+
+/* Reverse mapping of QBMAN_CENA_SWP_DQRR() */
+#define QBMAN_IDX_FROM_DQRR(p) (((unsigned long)p & 0x1ff) >> 6)
+
+/* SDQCR attribute codes */
+#define QB_SDQCR_FC_SHIFT 29
+#define QB_SDQCR_FC_MASK 0x1
+#define QB_SDQCR_DCT_SHIFT 24
+#define QB_SDQCR_DCT_MASK 0x3
+#define QB_SDQCR_SRC_SHIFT 0
+#define QB_SDQCR_SRC_MASK 0xff
+
+enum qbman_sdqcr_dct {
+ qbman_sdqcr_dct_null = 0,
+ qbman_sdqcr_dct_prio_ics,
+ qbman_sdqcr_dct_active_ics,
+ qbman_sdqcr_dct_active
+};
+
+enum qbman_sdqcr_fc {
+ qbman_sdqcr_fc_one = 0,
+ qbman_sdqcr_fc_up_to_3 = 1
+};
+
+/* Portal Access */
+
+static inline u32 qbman_read_register(struct qbman_swp *p, u32 offset)
+{
+ return readl_relaxed(p->addr_cinh + offset);
+}
+
+static inline void qbman_write_register(struct qbman_swp *p, u32 offset,
+ u32 value)
+{
+ writel_relaxed(value, p->addr_cinh + offset);
+}
+
+static inline void *qbman_get_cmd(struct qbman_swp *p, u32 offset)
+{
+ return p->addr_cena + offset;
+}
+
+#define QBMAN_CINH_SWP_CFG 0xd00
+
+#define SWP_CFG_DQRR_MF_SHIFT 20
+#define SWP_CFG_EST_SHIFT 16
+#define SWP_CFG_WN_SHIFT 14
+#define SWP_CFG_RPM_SHIFT 12
+#define SWP_CFG_DCM_SHIFT 10
+#define SWP_CFG_EPM_SHIFT 8
+#define SWP_CFG_SD_SHIFT 5
+#define SWP_CFG_SP_SHIFT 4
+#define SWP_CFG_SE_SHIFT 3
+#define SWP_CFG_DP_SHIFT 2
+#define SWP_CFG_DE_SHIFT 1
+#define SWP_CFG_EP_SHIFT 0
+
+static inline u32 qbman_set_swp_cfg(u8 max_fill, u8 wn, u8 est, u8 rpm, u8 dcm,
+ u8 epm, int sd, int sp, int se,
+ int dp, int de, int ep)
+{
+ return cpu_to_le32 (max_fill << SWP_CFG_DQRR_MF_SHIFT |
+ est << SWP_CFG_EST_SHIFT |
+ wn << SWP_CFG_WN_SHIFT |
+ rpm << SWP_CFG_RPM_SHIFT |
+ dcm << SWP_CFG_DCM_SHIFT |
+ epm << SWP_CFG_EPM_SHIFT |
+ sd << SWP_CFG_SD_SHIFT |
+ sp << SWP_CFG_SP_SHIFT |
+ se << SWP_CFG_SE_SHIFT |
+ dp << SWP_CFG_DP_SHIFT |
+ de << SWP_CFG_DE_SHIFT |
+ ep << SWP_CFG_EP_SHIFT);
+}
+
+/**
+ * qbman_swp_init() - Create a functional object representing the given
+ * QBMan portal descriptor.
+ * @d: the given qbman swp descriptor
+ *
+ * Return qbman_swp portal for success, NULL if the object cannot
+ * be created.
+ */
+struct qbman_swp *qbman_swp_init(const struct qbman_swp_desc *d)
+{
+ struct qbman_swp *p = kmalloc(sizeof(*p), GFP_KERNEL);
+ u32 reg;
+
+ if (!p)
+ return NULL;
+ p->desc = d;
+ p->mc.valid_bit = QB_VALID_BIT;
+ p->sdq = 0;
+ p->sdq |= qbman_sdqcr_dct_prio_ics << QB_SDQCR_DCT_SHIFT;
+ p->sdq |= qbman_sdqcr_fc_up_to_3 << QB_SDQCR_FC_SHIFT;
+ p->sdq |= 0xbb << QB_SDQCR_DCT_SHIFT;
+
+ atomic_set(&p->vdq.available, 1);
+ p->vdq.valid_bit = QB_VALID_BIT;
+ p->dqrr.next_idx = 0;
+ p->dqrr.valid_bit = QB_VALID_BIT;
+
+ if ((p->desc->qman_version & 0xFFFF0000) < QMAN_REV_4100) {
+ p->dqrr.dqrr_size = 4;
+ p->dqrr.reset_bug = 1;
+ } else {
+ p->dqrr.dqrr_size = 8;
+ p->dqrr.reset_bug = 0;
+ }
+
+ p->addr_cena = d->cena_bar;
+ p->addr_cinh = d->cinh_bar;
+
+ reg = qbman_set_swp_cfg(p->dqrr.dqrr_size,
+ 1, /* Writes Non-cacheable */
+ 0, /* EQCR_CI stashing threshold */
+ 3, /* RPM: Valid bit mode, RCR in array mode */
+ 2, /* DCM: Discrete consumption ack mode */
+ 3, /* EPM: Valid bit mode, EQCR in array mode */
+ 0, /* mem stashing drop enable == FALSE */
+ 1, /* mem stashing priority == TRUE */
+ 0, /* mem stashing enable == FALSE */
+ 1, /* dequeue stashing priority == TRUE */
+ 0, /* dequeue stashing enable == FALSE */
+ 0); /* EQCR_CI stashing priority == FALSE */
+
+ qbman_write_register(p, QBMAN_CINH_SWP_CFG, reg);
+ reg = qbman_read_register(p, QBMAN_CINH_SWP_CFG);
+ if (!reg) {
+ pr_err("The portal is not enabled!\n");
+ return NULL;
+ }
+
+ /*
+ * SDQCR needs to be initialized to 0 when no channels are
+ * being dequeued from or else the QMan HW will indicate an
+ * error. The values that were calculated above will be
+ * applied when dequeues from a specific channel are enabled.
+ */
+ qbman_write_register(p, QBMAN_CINH_SWP_SDQCR, 0);
+ return p;
+}
+
+/**
+ * qbman_swp_finish() - Create and destroy a functional object representing
+ * the given QBMan portal descriptor.
+ * @p: the qbman_swp object to be destroyed
+ */
+void qbman_swp_finish(struct qbman_swp *p)
+{
+ kfree(p);
+}
+
+/**
+ * qbman_swp_interrupt_read_status()
+ * @p: the given software portal
+ *
+ * Return the value in the SWP_ISR register.
+ */
+u32 qbman_swp_interrupt_read_status(struct qbman_swp *p)
+{
+ return qbman_read_register(p, QBMAN_CINH_SWP_ISR);
+}
+
+/**
+ * qbman_swp_interrupt_clear_status()
+ * @p: the given software portal
+ * @mask: The mask to clear in SWP_ISR register
+ */
+void qbman_swp_interrupt_clear_status(struct qbman_swp *p, u32 mask)
+{
+ qbman_write_register(p, QBMAN_CINH_SWP_ISR, mask);
+}
+
+/**
+ * qbman_swp_interrupt_get_trigger() - read interrupt enable register
+ * @p: the given software portal
+ *
+ * Return the value in the SWP_IER register.
+ */
+u32 qbman_swp_interrupt_get_trigger(struct qbman_swp *p)
+{
+ return qbman_read_register(p, QBMAN_CINH_SWP_IER);
+}
+
+/**
+ * qbman_swp_interrupt_set_trigger() - enable interrupts for a swp
+ * @p: the given software portal
+ * @mask: The mask of bits to enable in SWP_IER
+ */
+void qbman_swp_interrupt_set_trigger(struct qbman_swp *p, u32 mask)
+{
+ qbman_write_register(p, QBMAN_CINH_SWP_IER, mask);
+}
+
+/**
+ * qbman_swp_interrupt_get_inhibit() - read interrupt mask register
+ * @p: the given software portal object
+ *
+ * Return the value in the SWP_IIR register.
+ */
+int qbman_swp_interrupt_get_inhibit(struct qbman_swp *p)
+{
+ return qbman_read_register(p, QBMAN_CINH_SWP_IIR);
+}
+
+/**
+ * qbman_swp_interrupt_set_inhibit() - write interrupt mask register
+ * @p: the given software portal object
+ * @mask: The mask to set in SWP_IIR register
+ */
+void qbman_swp_interrupt_set_inhibit(struct qbman_swp *p, int inhibit)
+{
+ qbman_write_register(p, QBMAN_CINH_SWP_IIR, inhibit ? 0xffffffff : 0);
+}
+
+/*
+ * Different management commands all use this common base layer of code to issue
+ * commands and poll for results.
+ */
+
+/*
+ * Returns a pointer to where the caller should fill in their management command
+ * (caller should ignore the verb byte)
+ */
+void *qbman_swp_mc_start(struct qbman_swp *p)
+{
+ return qbman_get_cmd(p, QBMAN_CENA_SWP_CR);
+}
+
+/*
+ * Commits merges in the caller-supplied command verb (which should not include
+ * the valid-bit) and submits the command to hardware
+ */
+void qbman_swp_mc_submit(struct qbman_swp *p, void *cmd, u8 cmd_verb)
+{
+ u8 *v = cmd;
+
+ dma_wmb();
+ *v = cmd_verb | p->mc.valid_bit;
+}
+
+/*
+ * Checks for a completed response (returns non-NULL if only if the response
+ * is complete).
+ */
+void *qbman_swp_mc_result(struct qbman_swp *p)
+{
+ u32 *ret, verb;
+
+ ret = qbman_get_cmd(p, QBMAN_CENA_SWP_RR(p->mc.valid_bit));
+
+ /* Remove the valid-bit - command completed if the rest is non-zero */
+ verb = ret[0] & ~QB_VALID_BIT;
+ if (!verb)
+ return NULL;
+ p->mc.valid_bit ^= QB_VALID_BIT;
+ return ret;
+}
+
+#define QB_ENQUEUE_CMD_OPTIONS_SHIFT 0
+enum qb_enqueue_commands {
+ enqueue_empty = 0,
+ enqueue_response_always = 1,
+ enqueue_rejects_to_fq = 2
+};
+
+#define QB_ENQUEUE_CMD_ORP_ENABLE_SHIFT 2
+#define QB_ENQUEUE_CMD_IRQ_ON_DISPATCH_SHIFT 3
+#define QB_ENQUEUE_CMD_TARGET_TYPE_SHIFT 4
+
+/**
+ * qbman_eq_desc_clear() - Clear the contents of a descriptor to
+ * default/starting state.
+ */
+void qbman_eq_desc_clear(struct qbman_eq_desc *d)
+{
+ memset(d, 0, sizeof(*d));
+}
+
+/**
+ * qbman_eq_desc_set_no_orp() - Set enqueue descriptor without orp
+ * @d: the enqueue descriptor.
+ * @response_success: 1 = enqueue with response always; 0 = enqueue with
+ * rejections returned on a FQ.
+ */
+void qbman_eq_desc_set_no_orp(struct qbman_eq_desc *d, int respond_success)
+{
+ d->verb &= ~(1 << QB_ENQUEUE_CMD_ORP_ENABLE_SHIFT);
+ if (respond_success)
+ d->verb |= enqueue_response_always;
+ else
+ d->verb |= enqueue_rejects_to_fq;
+}
+
+/*
+ * Exactly one of the following descriptor "targets" should be set. (Calling any
+ * one of these will replace the effect of any prior call to one of these.)
+ * -enqueue to a frame queue
+ * -enqueue to a queuing destination
+ */
+
+/**
+ * qbman_eq_desc_set_fq() - set the FQ for the enqueue command
+ * @d: the enqueue descriptor
+ * @fqid: the id of the frame queue to be enqueued
+ */
+void qbman_eq_desc_set_fq(struct qbman_eq_desc *d, u32 fqid)
+{
+ d->verb &= ~(1 << QB_ENQUEUE_CMD_TARGET_TYPE_SHIFT);
+ d->tgtid = cpu_to_le32(fqid);
+}
+
+/**
+ * qbman_eq_desc_set_qd() - Set Queuing Destination for the enqueue command
+ * @d: the enqueue descriptor
+ * @qdid: the id of the queuing destination to be enqueued
+ * @qd_bin: the queuing destination bin
+ * @qd_prio: the queuing destination priority
+ */
+void qbman_eq_desc_set_qd(struct qbman_eq_desc *d, u32 qdid,
+ u32 qd_bin, u32 qd_prio)
+{
+ d->verb |= 1 << QB_ENQUEUE_CMD_TARGET_TYPE_SHIFT;
+ d->tgtid = cpu_to_le32(qdid);
+ d->qdbin = cpu_to_le16(qd_bin);
+ d->qpri = qd_prio;
+}
+
+#define EQAR_IDX(eqar) ((eqar) & 0x7)
+#define EQAR_VB(eqar) ((eqar) & 0x80)
+#define EQAR_SUCCESS(eqar) ((eqar) & 0x100)
+
+/**
+ * qbman_swp_enqueue() - Issue an enqueue command
+ * @s: the software portal used for enqueue
+ * @d: the enqueue descriptor
+ * @fd: the frame descriptor to be enqueued
+ *
+ * Please note that 'fd' should only be NULL if the "action" of the
+ * descriptor is "orp_hole" or "orp_nesn".
+ *
+ * Return 0 for successful enqueue, -EBUSY if the EQCR is not ready.
+ */
+int qbman_swp_enqueue(struct qbman_swp *s, const struct qbman_eq_desc *d,
+ const struct dpaa2_fd *fd)
+{
+ struct qbman_eq_desc *p;
+ u32 eqar = qbman_read_register(s, QBMAN_CINH_SWP_EQAR);
+
+ if (!EQAR_SUCCESS(eqar))
+ return -EBUSY;
+
+ p = qbman_get_cmd(s, QBMAN_CENA_SWP_EQCR(EQAR_IDX(eqar)));
+ memcpy(&p->dca, &d->dca, 31);
+ memcpy(&p->fd, fd, sizeof(*fd));
+
+ /* Set the verb byte, have to substitute in the valid-bit */
+ dma_wmb();
+ p->verb = d->verb | EQAR_VB(eqar);
+
+ return 0;
+}
+
+/* Static (push) dequeue */
+
+/**
+ * qbman_swp_push_get() - Get the push dequeue setup
+ * @p: the software portal object
+ * @channel_idx: the channel index to query
+ * @enabled: returned boolean to show whether the push dequeue is enabled
+ * for the given channel
+ */
+void qbman_swp_push_get(struct qbman_swp *s, u8 channel_idx, int *enabled)
+{
+ u16 src = (s->sdq >> QB_SDQCR_SRC_SHIFT) & QB_SDQCR_SRC_MASK;
+
+ WARN_ON(channel_idx > 15);
+ *enabled = src | (1 << channel_idx);
+}
+
+/**
+ * qbman_swp_push_set() - Enable or disable push dequeue
+ * @p: the software portal object
+ * @channel_idx: the channel index (0 to 15)
+ * @enable: enable or disable push dequeue
+ */
+void qbman_swp_push_set(struct qbman_swp *s, u8 channel_idx, int enable)
+{
+ u16 dqsrc;
+
+ WARN_ON(channel_idx > 15);
+ if (enable)
+ s->sdq |= 1 << channel_idx;
+ else
+ s->sdq &= ~(1 << channel_idx);
+
+ /* Read make the complete src map. If no channels are enabled
+ * the SDQCR must be 0 or else QMan will assert errors
+ */
+ dqsrc = (s->sdq >> QB_SDQCR_SRC_SHIFT) & QB_SDQCR_SRC_MASK;
+ if (dqsrc != 0)
+ qbman_write_register(s, QBMAN_CINH_SWP_SDQCR, s->sdq);
+ else
+ qbman_write_register(s, QBMAN_CINH_SWP_SDQCR, 0);
+}
+
+#define QB_VDQCR_VERB_DCT_SHIFT 0
+#define QB_VDQCR_VERB_DT_SHIFT 2
+#define QB_VDQCR_VERB_RLS_SHIFT 4
+#define QB_VDQCR_VERB_WAE_SHIFT 5
+
+enum qb_pull_dt_e {
+ qb_pull_dt_channel,
+ qb_pull_dt_workqueue,
+ qb_pull_dt_framequeue
+};
+
+/**
+ * qbman_pull_desc_clear() - Clear the contents of a descriptor to
+ * default/starting state
+ * @d: the pull dequeue descriptor to be cleared
+ */
+void qbman_pull_desc_clear(struct qbman_pull_desc *d)
+{
+ memset(d, 0, sizeof(*d));
+}
+
+/**
+ * qbman_pull_desc_set_storage()- Set the pull dequeue storage
+ * @d: the pull dequeue descriptor to be set
+ * @storage: the pointer of the memory to store the dequeue result
+ * @storage_phys: the physical address of the storage memory
+ * @stash: to indicate whether write allocate is enabled
+ *
+ * If not called, or if called with 'storage' as NULL, the result pull dequeues
+ * will produce results to DQRR. If 'storage' is non-NULL, then results are
+ * produced to the given memory location (using the DMA address which
+ * the caller provides in 'storage_phys'), and 'stash' controls whether or not
+ * those writes to main-memory express a cache-warming attribute.
+ */
+void qbman_pull_desc_set_storage(struct qbman_pull_desc *d,
+ struct dpaa2_dq *storage,
+ dma_addr_t storage_phys,
+ int stash)
+{
+ /* save the virtual address */
+ d->rsp_addr_virt = (u64)storage;
+
+ if (!storage) {
+ d->verb &= ~(1 << QB_VDQCR_VERB_RLS_SHIFT);
+ return;
+ }
+ d->verb |= 1 << QB_VDQCR_VERB_RLS_SHIFT;
+ if (stash)
+ d->verb |= 1 << QB_VDQCR_VERB_WAE_SHIFT;
+ else
+ d->verb &= ~(1 << QB_VDQCR_VERB_WAE_SHIFT);
+
+ d->rsp_addr = cpu_to_le64(storage_phys);
+}
+
+/**
+ * qbman_pull_desc_set_numframes() - Set the number of frames to be dequeued
+ * @d: the pull dequeue descriptor to be set
+ * @numframes: number of frames to be set, must be between 1 and 16, inclusive
+ */
+void qbman_pull_desc_set_numframes(struct qbman_pull_desc *d, u8 numframes)
+{
+ d->numf = numframes - 1;
+}
+
+void qbman_pull_desc_set_token(struct qbman_pull_desc *d, u8 token)
+{
+ d->tok = token;
+}
+
+
+/*
+ * Exactly one of the following descriptor "actions" should be set. (Calling any
+ * one of these will replace the effect of any prior call to one of these.)
+ * - pull dequeue from the given frame queue (FQ)
+ * - pull dequeue from any FQ in the given work queue (WQ)
+ * - pull dequeue from any FQ in any WQ in the given channel
+ */
+
+/**
+ * qbman_pull_desc_set_fq() - Set fqid from which the dequeue command dequeues
+ * @fqid: the frame queue index of the given FQ
+ */
+void qbman_pull_desc_set_fq(struct qbman_pull_desc *d, u32 fqid)
+{
+ d->verb |= 1 << QB_VDQCR_VERB_DCT_SHIFT;
+ d->verb |= qb_pull_dt_framequeue << QB_VDQCR_VERB_DT_SHIFT;
+ d->dq_src = cpu_to_le32(fqid);
+}
+
+/**
+ * qbman_pull_desc_set_wq() - Set wqid from which the dequeue command dequeues
+ * @wqid: composed of channel id and wqid within the channel
+ * @dct: the dequeue command type
+ */
+void qbman_pull_desc_set_wq(struct qbman_pull_desc *d, u32 wqid,
+ enum qbman_pull_type_e dct)
+{
+ d->verb |= dct << QB_VDQCR_VERB_DCT_SHIFT;
+ d->verb |= qb_pull_dt_workqueue << QB_VDQCR_VERB_DT_SHIFT;
+ d->dq_src = cpu_to_le32(wqid);
+}
+
+/**
+ * qbman_pull_desc_set_channel() - Set channelid from which the dequeue command
+ * dequeues
+ * @chid: the channel id to be dequeued
+ * @dct: the dequeue command type
+ */
+void qbman_pull_desc_set_channel(struct qbman_pull_desc *d, u32 chid,
+ enum qbman_pull_type_e dct)
+{
+ d->verb |= dct << QB_VDQCR_VERB_DCT_SHIFT;
+ d->verb |= qb_pull_dt_channel << QB_VDQCR_VERB_DT_SHIFT;
+ d->dq_src = cpu_to_le32(chid);
+}
+
+/**
+ * qbman_swp_pull() - Issue the pull dequeue command
+ * @s: the software portal object
+ * @d: the software portal descriptor which has been configured with
+ * the set of qbman_pull_desc_set_*() calls
+ *
+ * Return 0 for success, and -EBUSY if the software portal is not ready
+ * to do pull dequeue.
+ */
+int qbman_swp_pull(struct qbman_swp *s, struct qbman_pull_desc *d)
+{
+ struct qbman_pull_desc *p;
+
+ if (!atomic_dec_and_test(&s->vdq.available)) {
+ atomic_inc(&s->vdq.available);
+ return -EBUSY;
+ }
+ s->vdq.storage = (void *)d->rsp_addr_virt;
+ d->tok = 1;
+ p = qbman_get_cmd(s, QBMAN_CENA_SWP_VDQCR);
+ *p = *d;
+ dma_wmb();
+
+ /* Set the verb byte, have to substitute in the valid-bit */
+ p->verb |= s->vdq.valid_bit;
+ s->vdq.valid_bit ^= QB_VALID_BIT;
+
+ return 0;
+}
+
+#define QMAN_DQRR_PI_MASK 0xf
+
+/**
+ * qbman_swp_dqrr_next() - Get an valid DQRR entry
+ * @s: the software portal object
+ *
+ * Return NULL if there are no unconsumed DQRR entries. Return a DQRR entry
+ * only once, so repeated calls can return a sequence of DQRR entries, without
+ * requiring they be consumed immediately or in any particular order.
+ */
+const struct dpaa2_dq *qbman_swp_dqrr_next(struct qbman_swp *s)
+{
+ u32 verb;
+ u32 response_verb;
+ u32 flags;
+ struct dpaa2_dq *p;
+
+ /* Before using valid-bit to detect if something is there, we have to
+ * handle the case of the DQRR reset bug...
+ */
+ if (unlikely(s->dqrr.reset_bug)) {
+ /*
+ * We pick up new entries by cache-inhibited producer index,
+ * which means that a non-coherent mapping would require us to
+ * invalidate and read *only* once that PI has indicated that
+ * there's an entry here. The first trip around the DQRR ring
+ * will be much less efficient than all subsequent trips around
+ * it...
+ */
+ u8 pi = qbman_read_register(s, QBMAN_CINH_SWP_DQPI) &
+ QMAN_DQRR_PI_MASK;
+
+ /* there are new entries if pi != next_idx */
+ if (pi == s->dqrr.next_idx)
+ return NULL;
+
+ /*
+ * if next_idx is/was the last ring index, and 'pi' is
+ * different, we can disable the workaround as all the ring
+ * entries have now been DMA'd to so valid-bit checking is
+ * repaired. Note: this logic needs to be based on next_idx
+ * (which increments one at a time), rather than on pi (which
+ * can burst and wrap-around between our snapshots of it).
+ */
+ if (s->dqrr.next_idx == (s->dqrr.dqrr_size - 1)) {
+ pr_debug("next_idx=%d, pi=%d, clear reset bug\n",
+ s->dqrr.next_idx, pi);
+ s->dqrr.reset_bug = 0;
+ }
+ prefetch(qbman_get_cmd(s,
+ QBMAN_CENA_SWP_DQRR(s->dqrr.next_idx)));
+ }
+
+ p = qbman_get_cmd(s, QBMAN_CENA_SWP_DQRR(s->dqrr.next_idx));
+ verb = p->dq.verb;
+
+ /*
+ * If the valid-bit isn't of the expected polarity, nothing there. Note,
+ * in the DQRR reset bug workaround, we shouldn't need to skip these
+ * check, because we've already determined that a new entry is available
+ * and we've invalidated the cacheline before reading it, so the
+ * valid-bit behaviour is repaired and should tell us what we already
+ * knew from reading PI.
+ */
+ if ((verb & QB_VALID_BIT) != s->dqrr.valid_bit) {
+ prefetch(qbman_get_cmd(s,
+ QBMAN_CENA_SWP_DQRR(s->dqrr.next_idx)));
+ return NULL;
+ }
+ /*
+ * There's something there. Move "next_idx" attention to the next ring
+ * entry (and prefetch it) before returning what we found.
+ */
+ s->dqrr.next_idx++;
+ s->dqrr.next_idx &= s->dqrr.dqrr_size - 1; /* Wrap around */
+ if (!s->dqrr.next_idx)
+ s->dqrr.valid_bit ^= QB_VALID_BIT;
+
+ /*
+ * If this is the final response to a volatile dequeue command
+ * indicate that the vdq is available
+ */
+ flags = p->dq.stat;
+ response_verb = verb & QBMAN_RESULT_MASK;
+ if ((response_verb == QBMAN_RESULT_DQ) &&
+ (flags & DPAA2_DQ_STAT_VOLATILE) &&
+ (flags & DPAA2_DQ_STAT_EXPIRED))
+ atomic_inc(&s->vdq.available);
+
+ prefetch(qbman_get_cmd(s, QBMAN_CENA_SWP_DQRR(s->dqrr.next_idx)));
+
+ return p;
+}
+
+/**
+ * qbman_swp_dqrr_consume() - Consume DQRR entries previously returned from
+ * qbman_swp_dqrr_next().
+ * @s: the software portal object
+ * @dq: the DQRR entry to be consumed
+ */
+void qbman_swp_dqrr_consume(struct qbman_swp *s, const struct dpaa2_dq *dq)
+{
+ qbman_write_register(s, QBMAN_CINH_SWP_DCAP, QBMAN_IDX_FROM_DQRR(dq));
+}
+
+
+/**
+ * qbman_result_has_new_result() - Check and get the dequeue response from the
+ * dq storage memory set in pull dequeue command
+ * @s: the software portal object
+ * @dq: the dequeue result read from the memory
+ *
+ * Return 1 for getting a valid dequeue result, or 0 for not getting a valid
+ * dequeue result.
+ *
+ * Only used for user-provided storage of dequeue results, not DQRR. For
+ * efficiency purposes, the driver will perform any required endianness
+ * conversion to ensure that the user's dequeue result storage is in host-endian
+ * format. As such, once the user has called qbman_result_has_new_result() and
+ * been returned a valid dequeue result, they should not call it again on
+ * the same memory location (except of course if another dequeue command has
+ * been executed to produce a new result to that location).
+ */
+int qbman_result_has_new_result(struct qbman_swp *s, const struct dpaa2_dq *dq)
+{
+ if (!dq->dq.tok)
+ return 0;
+
+ /*
+ * Set token to be 0 so we will detect change back to 1
+ * next time the looping is traversed. Const is cast away here
+ * as we want users to treat the dequeue responses as read only.
+ */
+ ((struct dpaa2_dq *)dq)->dq.tok = 0;
+
+ /*
+ * Determine whether VDQCR is available based on whether the
+ * current result is sitting in the first storage location of
+ * the busy command.
+ */
+ if (s->vdq.storage == dq) {
+ s->vdq.storage = NULL;
+ atomic_inc(&s->vdq.available);
+ }
+
+ return 1;
+}
+
+/**
+ * qbman_release_desc_clear() - Clear the contents of a descriptor to
+ * default/starting state.
+ */
+void qbman_release_desc_clear(struct qbman_release_desc *d)
+{
+ memset(d, 0, sizeof(*d));
+ d->verb = 1 << 5; /* Release Command Valid */
+}
+
+/**
+ * qbman_release_desc_set_bpid() - Set the ID of the buffer pool to release to
+ */
+void qbman_release_desc_set_bpid(struct qbman_release_desc *d, u16 bpid)
+{
+ d->bpid = cpu_to_le16(bpid);
+}
+
+/**
+ * qbman_release_desc_set_rcdi() - Determines whether or not the portal's RCDI
+ * interrupt source should be asserted after the release command is completed.
+ */
+void qbman_release_desc_set_rcdi(struct qbman_release_desc *d, int enable)
+{
+ if (enable)
+ d->verb |= 1 << 6;
+ else
+ d->verb &= ~(1 << 6);
+}
+
+#define RAR_IDX(rar) ((rar) & 0x7)
+#define RAR_VB(rar) ((rar) & 0x80)
+#define RAR_SUCCESS(rar) ((rar) & 0x100)
+
+/**
+ * qbman_swp_release() - Issue a buffer release command
+ * @s: the software portal object
+ * @d: the release descriptor
+ * @buffers: a pointer pointing to the buffer address to be released
+ * @num_buffers: number of buffers to be released, must be less than 8
+ *
+ * Return 0 for success, -EBUSY if the release command ring is not ready.
+ */
+int qbman_swp_release(struct qbman_swp *s, const struct qbman_release_desc *d,
+ const u64 *buffers, unsigned int num_buffers)
+{
+ int i;
+ struct qbman_release_desc *p;
+ u32 rar;
+
+ if (!num_buffers || (num_buffers > 7))
+ return -EINVAL;
+
+ rar = qbman_read_register(s, QBMAN_CINH_SWP_RAR);
+ if (!RAR_SUCCESS(rar))
+ return -EBUSY;
+
+ /* Start the release command */
+ p = qbman_get_cmd(s, QBMAN_CENA_SWP_RCR(RAR_IDX(rar)));
+ /* Copy the caller's buffer pointers to the command */
+ for (i = 0; i < num_buffers; i++)
+ p->buf[i] = cpu_to_le64(buffers[i]);
+
+ /*
+ * Set the verb byte, have to substitute in the valid-bit and the number
+ * of buffers.
+ */
+ dma_wmb();
+ p->verb = d->verb | RAR_VB(rar) | num_buffers;
+
+ return 0;
+}
+
+struct qbman_acquire_desc {
+ u8 verb;
+ u8 reserved;
+ u16 bpid;
+ u8 num;
+ u8 reserved2[59];
+};
+
+struct qbman_acquire_rslt {
+ u8 verb;
+ u8 rslt;
+ u16 reserved;
+ u8 num;
+ u8 reserved2[3];
+ u64 buf[7];
+};
+
+/**
+ * qbman_swp_acquire() - Issue a buffer acquire command
+ * @s: the software portal object
+ * @bpid: the buffer pool index
+ * @buffers: a pointer pointing to the acquired buffer addresses
+ * @num_buffers: number of buffers to be acquired, must be less than 8
+ *
+ * Return 0 for success, or negative error code if the acquire command
+ * fails.
+ */
+int qbman_swp_acquire(struct qbman_swp *s, u16 bpid, u64 *buffers,
+ unsigned int num_buffers)
+{
+ struct qbman_acquire_desc *p;
+ struct qbman_acquire_rslt *r;
+ int i;
+
+ if (!num_buffers || (num_buffers > 7))
+ return -EINVAL;
+
+ /* Start the management command */
+ p = qbman_swp_mc_start(s);
+
+ if (!p)
+ return -EBUSY;
+
+ /* Encode the caller-provided attributes */
+ p->bpid = cpu_to_le16(bpid);
+ p->num = num_buffers;
+
+ /* Complete the management command */
+ r = qbman_swp_mc_complete(s, p, p->verb | QBMAN_MC_ACQUIRE);
+
+ /* Decode the outcome */
+ WARN_ON((r->verb & 0x7f) != QBMAN_MC_ACQUIRE);
+
+ /* Determine success or failure */
+ if (unlikely(r->rslt != QBMAN_MC_RSLT_OK)) {
+ pr_err("Acquire buffers from BPID 0x%x failed, code=0x%02x\n",
+ bpid, r->rslt);
+ return -EIO;
+ }
+
+ WARN_ON(r->num > num_buffers);
+
+ /* Copy the acquired buffers to the caller's array */
+ for (i = 0; i < r->num; i++)
+ buffers[i] = le64_to_cpu(r->buf[i]);
+
+ return (int)r->num;
+}
+
+struct qbman_alt_fq_state_desc {
+ u8 verb;
+ u8 reserved[3];
+ u32 fqid;
+ u8 reserved2[56];
+};
+
+struct qbman_alt_fq_state_rslt {
+ u8 verb;
+ u8 rslt;
+ u8 reserved[62];
+};
+
+#define ALT_FQ_FQID_MASK 0x00FFFFFF
+
+int qbman_swp_alt_fq_state(struct qbman_swp *s, u32 fqid,
+ u8 alt_fq_verb)
+{
+ struct qbman_alt_fq_state_desc *p;
+ struct qbman_alt_fq_state_rslt *r;
+
+ /* Start the management command */
+ p = qbman_swp_mc_start(s);
+ if (!p)
+ return -EBUSY;
+
+ p->fqid = cpu_to_le32(fqid) & ALT_FQ_FQID_MASK;
+
+ /* Complete the management command */
+ r = qbman_swp_mc_complete(s, p, p->verb | alt_fq_verb);
+
+ /* Decode the outcome */
+ WARN_ON(r->verb != alt_fq_verb);
+
+ /* Determine success or failure */
+ if (unlikely(r->rslt != QBMAN_MC_RSLT_OK)) {
+ pr_err("ALT FQID %d failed: verb = 0x%08x, code = 0x%02x\n",
+ fqid, r->verb, r->rslt);
+ return -EIO;
+ }
+
+ return 0;
+}
+
+struct qbman_cdan_ctrl_desc {
+ u8 verb;
+ u8 reserved;
+ u16 ch;
+ u8 we;
+ u8 ctrl;
+ u16 reserved2;
+ u64 cdan_ctx;
+ u8 reserved3[48];
+
+};
+
+struct qbman_cdan_ctrl_rslt {
+ u8 verb;
+ u8 rslt;
+ u16 ch;
+ u8 reserved[60];
+};
+
+int qbman_swp_CDAN_set(struct qbman_swp *s, u16 channelid,
+ u8 we_mask, u8 cdan_en,
+ u64 ctx)
+{
+ struct qbman_cdan_ctrl_desc *p = NULL;
+ struct qbman_cdan_ctrl_rslt *r = NULL;
+
+ /* Start the management command */
+ p = qbman_swp_mc_start(s);
+ if (!p)
+ return -EBUSY;
+
+ /* Encode the caller-provided attributes */
+ p->verb = 0;
+ p->ch = cpu_to_le16(channelid);
+ p->we = we_mask;
+ if (cdan_en)
+ p->ctrl = 1;
+ else
+ p->ctrl = 0;
+ p->cdan_ctx = cpu_to_le64(ctx);
+
+ /* Complete the management command */
+ r = qbman_swp_mc_complete(s, p, p->verb | QBMAN_WQCHAN_CONFIGURE);
+ WARN_ON((r->verb & 0x7f) != QBMAN_WQCHAN_CONFIGURE);
+
+ /* Determine success or failure */
+ if (unlikely(r->rslt != QBMAN_MC_RSLT_OK)) {
+ pr_err("CDAN cQID %d failed: code = 0x%02x\n",
+ channelid, r->rslt);
+ return -EIO;
+ }
+
+ return 0;
+}
diff --git a/drivers/bus/fsl-mc/dpio/qbman-portal.h b/drivers/bus/fsl-mc/dpio/qbman-portal.h
new file mode 100644
index 0000000..11cd43d
--- /dev/null
+++ b/drivers/bus/fsl-mc/dpio/qbman-portal.h
@@ -0,0 +1,464 @@
+/*
+ * Copyright (C) 2014-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:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <linux/fsl/dpaa2-fd.h>
+
+struct dpaa2_dq;
+struct qbman_swp;
+
+/* qbman software portal descriptor structure */
+struct qbman_swp_desc {
+ void *cena_bar; /* Cache-enabled portal base address */
+ void *cinh_bar; /* Cache-inhibited portal base address */
+ u32 qman_version;
+};
+
+#define QBMAN_SWP_INTERRUPT_EQRI 0x01
+#define QBMAN_SWP_INTERRUPT_EQDI 0x02
+#define QBMAN_SWP_INTERRUPT_DQRI 0x04
+#define QBMAN_SWP_INTERRUPT_RCRI 0x08
+#define QBMAN_SWP_INTERRUPT_RCDI 0x10
+#define QBMAN_SWP_INTERRUPT_VDCI 0x20
+
+/* the structure for pull dequeue descriptor */
+struct qbman_pull_desc {
+ u8 verb;
+ u8 numf;
+ u8 tok;
+ u8 reserved;
+ u32 dq_src;
+ u64 rsp_addr;
+ u64 rsp_addr_virt;
+ u8 padding[40];
+};
+
+enum qbman_pull_type_e {
+ /* dequeue with priority precedence, respect intra-class scheduling */
+ qbman_pull_type_prio = 1,
+ /* dequeue with active FQ precedence, respect ICS */
+ qbman_pull_type_active,
+ /* dequeue with active FQ precedence, no ICS */
+ qbman_pull_type_active_noics
+};
+
+/* Definitions for parsing dequeue entries */
+#define QBMAN_RESULT_MASK 0x7f
+#define QBMAN_RESULT_DQ 0x60
+#define QBMAN_RESULT_FQRN 0x21
+#define QBMAN_RESULT_FQRNI 0x22
+#define QBMAN_RESULT_FQPN 0x24
+#define QBMAN_RESULT_FQDAN 0x25
+#define QBMAN_RESULT_CDAN 0x26
+#define QBMAN_RESULT_CSCN_MEM 0x27
+#define QBMAN_RESULT_CGCU 0x28
+#define QBMAN_RESULT_BPSCN 0x29
+#define QBMAN_RESULT_CSCN_WQ 0x2a
+
+/* QBMan FQ management command codes */
+#define QBMAN_FQ_SCHEDULE 0x48
+#define QBMAN_FQ_FORCE 0x49
+#define QBMAN_FQ_XON 0x4d
+#define QBMAN_FQ_XOFF 0x4e
+
+/* structure of enqueue descriptor */
+struct qbman_eq_desc {
+ u8 verb;
+ u8 dca;
+ u16 seqnum;
+ u16 orpid;
+ u16 reserved1;
+ u32 tgtid;
+ u32 tag;
+ u16 qdbin;
+ u8 qpri;
+ u8 reserved[3];
+ u8 wae;
+ u8 rspid;
+ u64 rsp_addr;
+ u8 fd[32];
+};
+
+/* buffer release descriptor */
+struct qbman_release_desc {
+ u8 verb;
+ u8 reserved;
+ u16 bpid;
+ u32 reserved2;
+ u64 buf[7];
+};
+
+/* Management command result codes */
+#define QBMAN_MC_RSLT_OK 0xf0
+
+#define CODE_CDAN_WE_EN 0x1
+#define CODE_CDAN_WE_CTX 0x4
+
+/* portal data structure */
+struct qbman_swp {
+ const struct qbman_swp_desc *desc;
+ void __iomem *addr_cena;
+ void __iomem *addr_cinh;
+
+ /* Management commands */
+ struct {
+ u32 valid_bit; /* 0x00 or 0x80 */
+ } mc;
+
+ /* Push dequeues */
+ u32 sdq;
+
+ /* Volatile dequeues */
+ struct {
+ atomic_t available; /* indicates if a command can be sent */
+ u32 valid_bit; /* 0x00 or 0x80 */
+ struct dpaa2_dq *storage; /* NULL if DQRR */
+ } vdq;
+
+ /* DQRR */
+ struct {
+ u32 next_idx;
+ u32 valid_bit;
+ u8 dqrr_size;
+ int reset_bug; /* indicates dqrr reset workaround is needed */
+ } dqrr;
+};
+
+struct qbman_swp *qbman_swp_init(const struct qbman_swp_desc *d);
+void qbman_swp_finish(struct qbman_swp *p);
+u32 qbman_swp_interrupt_read_status(struct qbman_swp *p);
+void qbman_swp_interrupt_clear_status(struct qbman_swp *p, u32 mask);
+u32 qbman_swp_interrupt_get_trigger(struct qbman_swp *p);
+void qbman_swp_interrupt_set_trigger(struct qbman_swp *p, u32 mask);
+int qbman_swp_interrupt_get_inhibit(struct qbman_swp *p);
+void qbman_swp_interrupt_set_inhibit(struct qbman_swp *p, int inhibit);
+
+void qbman_swp_push_get(struct qbman_swp *p, u8 channel_idx, int *enabled);
+void qbman_swp_push_set(struct qbman_swp *p, u8 channel_idx, int enable);
+
+void qbman_pull_desc_clear(struct qbman_pull_desc *d);
+void qbman_pull_desc_set_storage(struct qbman_pull_desc *d,
+ struct dpaa2_dq *storage,
+ dma_addr_t storage_phys,
+ int stash);
+void qbman_pull_desc_set_numframes(struct qbman_pull_desc *d, u8 numframes);
+void qbman_pull_desc_set_fq(struct qbman_pull_desc *d, u32 fqid);
+void qbman_pull_desc_set_wq(struct qbman_pull_desc *d, u32 wqid,
+ enum qbman_pull_type_e dct);
+void qbman_pull_desc_set_channel(struct qbman_pull_desc *d, u32 chid,
+ enum qbman_pull_type_e dct);
+
+int qbman_swp_pull(struct qbman_swp *p, struct qbman_pull_desc *d);
+
+const struct dpaa2_dq *qbman_swp_dqrr_next(struct qbman_swp *s);
+void qbman_swp_dqrr_consume(struct qbman_swp *s, const struct dpaa2_dq *dq);
+
+int qbman_result_has_new_result(struct qbman_swp *p, const struct dpaa2_dq *dq);
+
+void qbman_eq_desc_clear(struct qbman_eq_desc *d);
+void qbman_eq_desc_set_no_orp(struct qbman_eq_desc *d, int respond_success);
+void qbman_eq_desc_set_token(struct qbman_eq_desc *d, u8 token);
+void qbman_eq_desc_set_fq(struct qbman_eq_desc *d, u32 fqid);
+void qbman_eq_desc_set_qd(struct qbman_eq_desc *d, u32 qdid,
+ u32 qd_bin, u32 qd_prio);
+
+int qbman_swp_enqueue(struct qbman_swp *p, const struct qbman_eq_desc *d,
+ const struct dpaa2_fd *fd);
+
+void qbman_release_desc_clear(struct qbman_release_desc *d);
+void qbman_release_desc_set_bpid(struct qbman_release_desc *d, u16 bpid);
+void qbman_release_desc_set_rcdi(struct qbman_release_desc *d, int enable);
+
+int qbman_swp_release(struct qbman_swp *s, const struct qbman_release_desc *d,
+ const u64 *buffers, unsigned int num_buffers);
+int qbman_swp_acquire(struct qbman_swp *s, u16 bpid, u64 *buffers,
+ unsigned int num_buffers);
+int qbman_swp_alt_fq_state(struct qbman_swp *s, u32 fqid,
+ u8 alt_fq_verb);
+int qbman_swp_CDAN_set(struct qbman_swp *s, u16 channelid,
+ u8 we_mask, u8 cdan_en,
+ u64 ctx);
+
+void *qbman_swp_mc_start(struct qbman_swp *p);
+void qbman_swp_mc_submit(struct qbman_swp *p, void *cmd, u8 cmd_verb);
+void *qbman_swp_mc_result(struct qbman_swp *p);
+
+/**
+ * qbman_result_is_DQ() - check if the dequeue result is a dequeue response
+ * @dq: the dequeue result to be checked
+ *
+ * DQRR entries may contain non-dequeue results, ie. notifications
+ */
+static inline int qbman_result_is_DQ(const struct dpaa2_dq *dq)
+{
+ return ((dq->dq.verb & QBMAN_RESULT_MASK) == QBMAN_RESULT_DQ);
+}
+
+/**
+ * qbman_result_is_SCN() - Check the dequeue result is notification or not
+ * @dq: the dequeue result to be checked
+ *
+ */
+static inline int qbman_result_is_SCN(const struct dpaa2_dq *dq)
+{
+ return !qbman_result_is_DQ(dq);
+}
+
+/* FQ Data Availability */
+static inline int qbman_result_is_FQDAN(const struct dpaa2_dq *dq)
+{
+ return ((dq->dq.verb & QBMAN_RESULT_MASK) == QBMAN_RESULT_FQDAN);
+}
+
+/* Channel Data Availability */
+static inline int qbman_result_is_CDAN(const struct dpaa2_dq *dq)
+{
+ return ((dq->dq.verb & QBMAN_RESULT_MASK) == QBMAN_RESULT_CDAN);
+}
+
+/* Congestion State Change */
+static inline int qbman_result_is_CSCN(const struct dpaa2_dq *dq)
+{
+ return ((dq->dq.verb & QBMAN_RESULT_MASK) == QBMAN_RESULT_CSCN_WQ);
+}
+
+/* Buffer Pool State Change */
+static inline int qbman_result_is_BPSCN(const struct dpaa2_dq *dq)
+{
+ return ((dq->dq.verb & QBMAN_RESULT_MASK) == QBMAN_RESULT_BPSCN);
+}
+
+/* Congestion Group Count Update */
+static inline int qbman_result_is_CGCU(const struct dpaa2_dq *dq)
+{
+ return ((dq->dq.verb & QBMAN_RESULT_MASK) == QBMAN_RESULT_CGCU);
+}
+
+/* Retirement */
+static inline int qbman_result_is_FQRN(const struct dpaa2_dq *dq)
+{
+ return ((dq->dq.verb & QBMAN_RESULT_MASK) == QBMAN_RESULT_FQRN);
+}
+
+/* Retirement Immediate */
+static inline int qbman_result_is_FQRNI(const struct dpaa2_dq *dq)
+{
+ return ((dq->dq.verb & QBMAN_RESULT_MASK) == QBMAN_RESULT_FQRNI);
+}
+
+ /* Park */
+static inline int qbman_result_is_FQPN(const struct dpaa2_dq *dq)
+{
+ return ((dq->dq.verb & QBMAN_RESULT_MASK) == QBMAN_RESULT_FQPN);
+}
+
+/**
+ * qbman_result_SCN_state() - Get the state field in State-change notification
+ */
+static inline u8 qbman_result_SCN_state(const struct dpaa2_dq *scn)
+{
+ return scn->scn.state;
+}
+
+#define SCN_RID_MASK 0x00FFFFFF
+
+/**
+ * qbman_result_SCN_rid() - Get the resource id in State-change notification
+ */
+static inline u32 qbman_result_SCN_rid(const struct dpaa2_dq *scn)
+{
+ return le32_to_cpu(scn->scn.rid_tok) & SCN_RID_MASK;
+}
+
+/**
+ * qbman_result_SCN_ctx() - Get the context data in State-change notification
+ */
+static inline u64 qbman_result_SCN_ctx(const struct dpaa2_dq *scn)
+{
+ return le64_to_cpu(scn->scn.ctx);
+}
+
+/**
+ * qbman_swp_fq_schedule() - Move the fq to the scheduled state
+ * @s: the software portal object
+ * @fqid: the index of frame queue to be scheduled
+ *
+ * There are a couple of different ways that a FQ can end up parked state,
+ * This schedules it.
+ *
+ * Return 0 for success, or negative error code for failure.
+ */
+static inline int qbman_swp_fq_schedule(struct qbman_swp *s, u32 fqid)
+{
+ return qbman_swp_alt_fq_state(s, fqid, QBMAN_FQ_SCHEDULE);
+}
+
+/**
+ * qbman_swp_fq_force() - Force the FQ to fully scheduled state
+ * @s: the software portal object
+ * @fqid: the index of frame queue to be forced
+ *
+ * Force eligible will force a tentatively-scheduled FQ to be fully-scheduled
+ * and thus be available for selection by any channel-dequeuing behaviour (push
+ * or pull). If the FQ is subsequently "dequeued" from the channel and is still
+ * empty at the time this happens, the resulting dq_entry will have no FD.
+ * (qbman_result_DQ_fd() will return NULL.)
+ *
+ * Return 0 for success, or negative error code for failure.
+ */
+static inline int qbman_swp_fq_force(struct qbman_swp *s, u32 fqid)
+{
+ return qbman_swp_alt_fq_state(s, fqid, QBMAN_FQ_FORCE);
+}
+
+/**
+ * qbman_swp_fq_xon() - sets FQ flow-control to XON
+ * @s: the software portal object
+ * @fqid: the index of frame queue
+ *
+ * This setting doesn't affect enqueues to the FQ, just dequeues.
+ *
+ * Return 0 for success, or negative error code for failure.
+ */
+static inline int qbman_swp_fq_xon(struct qbman_swp *s, u32 fqid)
+{
+ return qbman_swp_alt_fq_state(s, fqid, QBMAN_FQ_XON);
+}
+
+/**
+ * qbman_swp_fq_xoff() - sets FQ flow-control to XOFF
+ * @s: the software portal object
+ * @fqid: the index of frame queue
+ *
+ * This setting doesn't affect enqueues to the FQ, just dequeues.
+ * XOFF FQs will remain in the tenatively-scheduled state, even when
+ * non-empty, meaning they won't be selected for scheduled dequeuing.
+ * If a FQ is changed to XOFF after it had already become truly-scheduled
+ * to a channel, and a pull dequeue of that channel occurs that selects
+ * that FQ for dequeuing, then the resulting dq_entry will have no FD.
+ * (qbman_result_DQ_fd() will return NULL.)
+ *
+ * Return 0 for success, or negative error code for failure.
+ */
+static inline int qbman_swp_fq_xoff(struct qbman_swp *s, u32 fqid)
+{
+ return qbman_swp_alt_fq_state(s, fqid, QBMAN_FQ_XOFF);
+}
+
+/* If the user has been allocated a channel object that is going to generate
+ * CDANs to another channel, then the qbman_swp_CDAN* functions will be
+ * necessary.
+ *
+ * CDAN-enabled channels only generate a single CDAN notification, after which
+ * they need to be reenabled before they'll generate another. The idea is
+ * that pull dequeuing will occur in reaction to the CDAN, followed by a
+ * reenable step. Each function generates a distinct command to hardware, so a
+ * combination function is provided if the user wishes to modify the "context"
+ * (which shows up in each CDAN message) each time they reenable, as a single
+ * command to hardware.
+ */
+
+/**
+ * qbman_swp_CDAN_set_context() - Set CDAN context
+ * @s: the software portal object
+ * @channelid: the channel index
+ * @ctx: the context to be set in CDAN
+ *
+ * Return 0 for success, or negative error code for failure.
+ */
+static inline int qbman_swp_CDAN_set_context(struct qbman_swp *s, u16 channelid,
+ u64 ctx)
+{
+ return qbman_swp_CDAN_set(s, channelid,
+ CODE_CDAN_WE_CTX,
+ 0, ctx);
+}
+
+/**
+ * qbman_swp_CDAN_enable() - Enable CDAN for the channel
+ * @s: the software portal object
+ * @channelid: the index of the channel to generate CDAN
+ *
+ * Return 0 for success, or negative error code for failure.
+ */
+static inline int qbman_swp_CDAN_enable(struct qbman_swp *s, u16 channelid)
+{
+ return qbman_swp_CDAN_set(s, channelid,
+ CODE_CDAN_WE_EN,
+ 1, 0);
+}
+
+/**
+ * qbman_swp_CDAN_disable() - disable CDAN for the channel
+ * @s: the software portal object
+ * @channelid: the index of the channel to generate CDAN
+ *
+ * Return 0 for success, or negative error code for failure.
+ */
+static inline int qbman_swp_CDAN_disable(struct qbman_swp *s, u16 channelid)
+{
+ return qbman_swp_CDAN_set(s, channelid,
+ CODE_CDAN_WE_EN,
+ 0, 0);
+}
+
+/**
+ * qbman_swp_CDAN_set_context_enable() - Set CDAN contest and enable CDAN
+ * @s: the software portal object
+ * @channelid: the index of the channel to generate CDAN
+ * @ctx:i the context set in CDAN
+ *
+ * Return 0 for success, or negative error code for failure.
+ */
+static inline int qbman_swp_CDAN_set_context_enable(struct qbman_swp *s,
+ u16 channelid,
+ u64 ctx)
+{
+ return qbman_swp_CDAN_set(s, channelid,
+ CODE_CDAN_WE_EN | CODE_CDAN_WE_CTX,
+ 1, ctx);
+}
+
+/* Wraps up submit + poll-for-result */
+static inline void *qbman_swp_mc_complete(struct qbman_swp *swp, void *cmd,
+ u8 cmd_verb)
+{
+ int loopvar = 1000;
+
+ qbman_swp_mc_submit(swp, cmd, cmd_verb);
+
+ do {
+ cmd = qbman_swp_mc_result(swp);
+ } while (cmd == NULL && loopvar--);
+
+ WARN_ON(!loopvar);
+
+ return cmd;
+}
--
1.9.0
From: Roy Pledge <[email protected]>
The DPIO service interface handles initialization of DPIO objects
and exports APIs to be used by other DPAA2 object drivers to perform
queuing and buffer management related operations. The service allows
registration of callbacks when frames or notifications are received.
Signed-off-by: Roy Pledge <[email protected]>
Signed-off-by: Haiying Wang <[email protected]>
Signed-off-by: Stuart Yoder <[email protected]>
---
drivers/bus/fsl-mc/dpio/Makefile | 2 +-
drivers/bus/fsl-mc/dpio/dpio-service.c | 614 +++++++++++++++++++++++++++++++++
include/linux/fsl/dpaa2-io.h | 138 ++++++++
3 files changed, 753 insertions(+), 1 deletion(-)
create mode 100644 drivers/bus/fsl-mc/dpio/dpio-service.c
create mode 100644 include/linux/fsl/dpaa2-io.h
diff --git a/drivers/bus/fsl-mc/dpio/Makefile b/drivers/bus/fsl-mc/dpio/Makefile
index 6588498..0778da7 100644
--- a/drivers/bus/fsl-mc/dpio/Makefile
+++ b/drivers/bus/fsl-mc/dpio/Makefile
@@ -6,4 +6,4 @@ subdir-ccflags-y := -Werror
obj-$(CONFIG_FSL_MC_DPIO) += fsl-mc-dpio.o
-fsl-mc-dpio-objs := dpio.o qbman-portal.o
+fsl-mc-dpio-objs := dpio.o qbman-portal.o dpio-service.o
diff --git a/drivers/bus/fsl-mc/dpio/dpio-service.c b/drivers/bus/fsl-mc/dpio/dpio-service.c
new file mode 100644
index 0000000..7a455a7
--- /dev/null
+++ b/drivers/bus/fsl-mc/dpio/dpio-service.c
@@ -0,0 +1,614 @@
+/*
+ * Copyright 2014-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:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include <linux/types.h>
+#include <linux/fsl/mc.h>
+#include <linux/fsl/dpaa2-io.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/interrupt.h>
+#include <linux/dma-mapping.h>
+#include <linux/slab.h>
+
+#include "dpio.h"
+#include "qbman-portal.h"
+
+struct dpaa2_io {
+ atomic_t refs;
+ struct dpaa2_io_desc dpio_desc;
+ struct qbman_swp_desc swp_desc;
+ struct qbman_swp *swp;
+ struct list_head node;
+ spinlock_t lock_mgmt_cmd;
+ spinlock_t lock_notifications;
+ struct list_head notifications;
+};
+
+struct dpaa2_io_store {
+ unsigned int max;
+ dma_addr_t paddr;
+ struct dpaa2_dq *vaddr;
+ void *alloced_addr; /* unaligned value from kmalloc() */
+ unsigned int idx; /* position of the next-to-be-returned entry */
+ struct qbman_swp *swp; /* portal used to issue VDQCR */
+ struct device *dev; /* device used for DMA mapping */
+};
+
+/* keep a per cpu array of DPIOs for fast access */
+static struct dpaa2_io *dpio_by_cpu[NR_CPUS];
+static struct list_head dpio_list = LIST_HEAD_INIT(dpio_list);
+static DEFINE_SPINLOCK(dpio_list_lock);
+
+static inline struct dpaa2_io *service_select_by_cpu(struct dpaa2_io *d,
+ int cpu)
+{
+ if (d)
+ return d;
+
+ if (unlikely(cpu >= NR_CPUS))
+ return NULL;
+
+ /*
+ * If cpu == -1, choose the current cpu, with no guarantees about
+ * potentially being migrated away.
+ */
+ if (unlikely(cpu < 0))
+ cpu = smp_processor_id();
+
+ /* If a specific cpu was requested, pick it up immediately */
+ return dpio_by_cpu[cpu];
+}
+
+static inline struct dpaa2_io *service_select(struct dpaa2_io *d)
+{
+ if (d)
+ return d;
+
+ spin_lock(&dpio_list_lock);
+ d = list_entry(dpio_list.next, struct dpaa2_io, node);
+ list_del(&d->node);
+ list_add_tail(&d->node, &dpio_list);
+ spin_unlock(&dpio_list_lock);
+
+ return d;
+}
+
+/**
+ * dpaa2_io_create() - create a dpaa2_io object.
+ * @desc: the dpaa2_io descriptor
+ *
+ * Activates a "struct dpaa2_io" corresponding to the given config of an actual
+ * DPIO object.
+ *
+ * Return a valid dpaa2_io object for success, or NULL for failure.
+ */
+struct dpaa2_io *dpaa2_io_create(const struct dpaa2_io_desc *desc)
+{
+ struct dpaa2_io *obj = kmalloc(sizeof(*obj), GFP_KERNEL);
+
+ if (!obj)
+ return NULL;
+
+ /* check if CPU is out of range (-1 means any cpu) */
+ if (desc->cpu >= NR_CPUS)
+ return NULL;
+
+ atomic_set(&obj->refs, 1);
+ obj->dpio_desc = *desc;
+ obj->swp_desc.cena_bar = obj->dpio_desc.regs_cena;
+ obj->swp_desc.cinh_bar = obj->dpio_desc.regs_cinh;
+ obj->swp_desc.qman_version = obj->dpio_desc.qman_version;
+ obj->swp = qbman_swp_init(&obj->swp_desc);
+
+ if (!obj->swp) {
+ kfree(obj);
+ return NULL;
+ }
+
+ INIT_LIST_HEAD(&obj->node);
+ spin_lock_init(&obj->lock_mgmt_cmd);
+ spin_lock_init(&obj->lock_notifications);
+ INIT_LIST_HEAD(&obj->notifications);
+
+ /* For now only enable DQRR interrupts */
+ qbman_swp_interrupt_set_trigger(obj->swp,
+ QBMAN_SWP_INTERRUPT_DQRI);
+ qbman_swp_interrupt_clear_status(obj->swp, 0xffffffff);
+ if (obj->dpio_desc.receives_notifications)
+ qbman_swp_push_set(obj->swp, 0, 1);
+
+ spin_lock(&dpio_list_lock);
+ list_add_tail(&obj->node, &dpio_list);
+ if (desc->cpu >= 0 && !dpio_by_cpu[desc->cpu])
+ dpio_by_cpu[desc->cpu] = obj;
+ spin_unlock(&dpio_list_lock);
+
+ return obj;
+}
+EXPORT_SYMBOL(dpaa2_io_create);
+
+/**
+ * dpaa2_io_down() - release the dpaa2_io object.
+ * @d: the dpaa2_io object to be released.
+ *
+ * The "struct dpaa2_io" type can represent an individual DPIO object (as
+ * described by "struct dpaa2_io_desc") or an instance of a "DPIO service",
+ * which can be used to group/encapsulate multiple DPIO objects. In all cases,
+ * each handle obtained should be released using this function.
+ */
+void dpaa2_io_down(struct dpaa2_io *d)
+{
+ if (!atomic_dec_and_test(&d->refs))
+ return;
+ kfree(d);
+}
+EXPORT_SYMBOL(dpaa2_io_down);
+
+#define DPAA_POLL_MAX 32
+
+/**
+ * dpaa2_io_irq() - ISR for DPIO interrupts
+ *
+ * @obj: the given DPIO object.
+ *
+ * Return IRQ_HANDLED for success or IRQ_NONE if there
+ * were no pending interrupts.
+ */
+irqreturn_t dpaa2_io_irq(struct dpaa2_io *obj)
+{
+ const struct dpaa2_dq *dq;
+ int max = 0;
+ struct qbman_swp *swp;
+ u32 status;
+
+ swp = obj->swp;
+ status = qbman_swp_interrupt_read_status(swp);
+ if (!status)
+ return IRQ_NONE;
+
+ dq = qbman_swp_dqrr_next(swp);
+ while (dq) {
+ if (qbman_result_is_SCN(dq)) {
+ struct dpaa2_io_notification_ctx *ctx;
+ u64 q64;
+
+ q64 = qbman_result_SCN_ctx(dq);
+ ctx = (void *)q64;
+ ctx->cb(ctx);
+ } else {
+ pr_crit("fsl-mc-dpio: Unrecognised/ignored DQRR entry\n");
+ }
+ qbman_swp_dqrr_consume(swp, dq);
+ ++max;
+ if (max > DPAA_POLL_MAX)
+ goto done;
+ dq = qbman_swp_dqrr_next(swp);
+ }
+done:
+ qbman_swp_interrupt_clear_status(swp, status);
+ qbman_swp_interrupt_set_inhibit(swp, 0);
+ return IRQ_HANDLED;
+}
+EXPORT_SYMBOL(dpaa2_io_irq);
+
+/**
+ * dpaa2_io_service_register() - Prepare for servicing of FQDAN or CDAN
+ * notifications on the given DPIO service.
+ * @d: the given DPIO service.
+ * @ctx: the notification context.
+ *
+ * The caller should make the MC command to attach a DPAA2 object to
+ * a DPIO after this function completes successfully. In that way:
+ * (a) The DPIO service is "ready" to handle a notification arrival
+ * (which might happen before the "attach" command to MC has
+ * returned control of execution back to the caller)
+ * (b) The DPIO service can provide back to the caller the 'dpio_id' and
+ * 'qman64' parameters that it should pass along in the MC command
+ * in order for the object to be configured to produce the right
+ * notification fields to the DPIO service.
+ *
+ * Return 0 for success, or -ENODEV for failure.
+ */
+int dpaa2_io_service_register(struct dpaa2_io *d,
+ struct dpaa2_io_notification_ctx *ctx)
+{
+ unsigned long irqflags;
+
+ d = service_select_by_cpu(d, ctx->desired_cpu);
+ if (!d)
+ return -ENODEV;
+
+ ctx->dpio_id = d->dpio_desc.dpio_id;
+ ctx->qman64 = (u64)ctx;
+ ctx->dpio_private = d;
+ spin_lock_irqsave(&d->lock_notifications, irqflags);
+ list_add(&ctx->node, &d->notifications);
+ spin_unlock_irqrestore(&d->lock_notifications, irqflags);
+
+ /* Enable the generation of CDAN notifications */
+ if (ctx->is_cdan)
+ qbman_swp_CDAN_set_context_enable(d->swp,
+ (u16)ctx->id,
+ ctx->qman64);
+ return 0;
+}
+EXPORT_SYMBOL(dpaa2_io_service_register);
+
+/**
+ * dpaa2_io_service_deregister - The opposite of 'register'.
+ * @service: the given DPIO service.
+ * @ctx: the notification context.
+ *
+ * This function should be called only after sending the MC command to
+ * to detach the notification-producing device from the DPIO.
+ */
+void dpaa2_io_service_deregister(struct dpaa2_io *service,
+ struct dpaa2_io_notification_ctx *ctx)
+{
+ struct dpaa2_io *d = ctx->dpio_private;
+ unsigned long irqflags;
+
+ if (ctx->is_cdan)
+ qbman_swp_CDAN_disable(d->swp, (u16)ctx->id);
+
+ spin_lock_irqsave(&d->lock_notifications, irqflags);
+ list_del(&ctx->node);
+ spin_unlock_irqrestore(&d->lock_notifications, irqflags);
+}
+EXPORT_SYMBOL(dpaa2_io_service_deregister);
+
+/**
+ * dpaa2_io_service_rearm() - Rearm the notification for the given DPIO service.
+ * @service: the given DPIO service.
+ * @ctx: the notification context.
+ *
+ * Once a FQDAN/CDAN has been produced, the corresponding FQ/channel is
+ * considered "disarmed". Ie. the user can issue pull dequeue operations on that
+ * traffic source for as long as it likes. Eventually it may wish to "rearm"
+ * that source to allow it to produce another FQDAN/CDAN, that's what this
+ * function achieves.
+ *
+ * Return 0 for success.
+ */
+int dpaa2_io_service_rearm(struct dpaa2_io *d,
+ struct dpaa2_io_notification_ctx *ctx)
+{
+ unsigned long irqflags;
+ int err;
+
+ d = service_select(d);
+ if (!unlikely(d))
+ return -ENODEV;
+
+ spin_lock_irqsave(&d->lock_mgmt_cmd, irqflags);
+ if (ctx->is_cdan)
+ err = qbman_swp_CDAN_enable(d->swp, (u16)ctx->id);
+ else
+ err = qbman_swp_fq_schedule(d->swp, ctx->id);
+ spin_unlock_irqrestore(&d->lock_mgmt_cmd, irqflags);
+
+ return err;
+}
+EXPORT_SYMBOL(dpaa2_io_service_rearm);
+
+/**
+ * dpaa2_io_service_pull_fq() - pull dequeue functions from a fq.
+ * @d: the given DPIO service.
+ * @fqid: the given frame queue id.
+ * @s: the dpaa2_io_store object for the result.
+ *
+ * Return 0 for success, or error code for failure.
+ */
+int dpaa2_io_service_pull_fq(struct dpaa2_io *d, u32 fqid,
+ struct dpaa2_io_store *s)
+{
+ struct qbman_pull_desc pd;
+ int err;
+
+ qbman_pull_desc_clear(&pd);
+ qbman_pull_desc_set_storage(&pd, s->vaddr, s->paddr, 1);
+ qbman_pull_desc_set_numframes(&pd, (u8)s->max);
+ qbman_pull_desc_set_fq(&pd, fqid);
+
+ d = service_select(d);
+ if (!d)
+ return -ENODEV;
+ s->swp = d->swp;
+ err = qbman_swp_pull(d->swp, &pd);
+ if (err)
+ s->swp = NULL;
+
+ return err;
+}
+EXPORT_SYMBOL(dpaa2_io_service_pull_fq);
+
+/**
+ * dpaa2_io_service_pull_channel() - pull dequeue functions from a channel.
+ * @d: the given DPIO service.
+ * @channelid: the given channel id.
+ * @s: the dpaa2_io_store object for the result.
+ *
+ * Return 0 for success, or error code for failure.
+ */
+int dpaa2_io_service_pull_channel(struct dpaa2_io *d, u32 channelid,
+ struct dpaa2_io_store *s)
+{
+ struct qbman_pull_desc pd;
+ int err;
+
+ qbman_pull_desc_clear(&pd);
+ qbman_pull_desc_set_storage(&pd, s->vaddr, s->paddr, 1);
+ qbman_pull_desc_set_numframes(&pd, (u8)s->max);
+ qbman_pull_desc_set_channel(&pd, channelid, qbman_pull_type_prio);
+
+ d = service_select(d);
+ if (!d)
+ return -ENODEV;
+
+ s->swp = d->swp;
+ err = qbman_swp_pull(d->swp, &pd);
+ if (err)
+ s->swp = NULL;
+
+ return err;
+}
+EXPORT_SYMBOL(dpaa2_io_service_pull_channel);
+
+/**
+ * dpaa2_io_service_enqueue_fq() - Enqueue a frame to a frame queue.
+ * @d: the given DPIO service.
+ * @fqid: the given frame queue id.
+ * @fd: the frame descriptor which is enqueued.
+ *
+ * Return 0 for successful enqueue, -EBUSY if the enqueue ring is not ready,
+ * or -ENODEV if there is no dpio service.
+ */
+int dpaa2_io_service_enqueue_fq(struct dpaa2_io *d,
+ u32 fqid,
+ const struct dpaa2_fd *fd)
+{
+ struct qbman_eq_desc ed;
+
+ d = service_select(d);
+ if (!d)
+ return -ENODEV;
+
+ qbman_eq_desc_clear(&ed);
+ qbman_eq_desc_set_no_orp(&ed, 0);
+ qbman_eq_desc_set_fq(&ed, fqid);
+
+ return qbman_swp_enqueue(d->swp, &ed, fd);
+}
+EXPORT_SYMBOL(dpaa2_io_service_enqueue_fq);
+
+/**
+ * dpaa2_io_service_enqueue_qd() - Enqueue a frame to a QD.
+ * @d: the given DPIO service.
+ * @qdid: the given queuing destination id.
+ * @prio: the given queuing priority.
+ * @qdbin: the given queuing destination bin.
+ * @fd: the frame descriptor which is enqueued.
+ *
+ * Return 0 for successful enqueue, or -EBUSY if the enqueue ring is not ready,
+ * or -ENODEV if there is no dpio service.
+ */
+int dpaa2_io_service_enqueue_qd(struct dpaa2_io *d,
+ u32 qdid, u8 prio, u16 qdbin,
+ const struct dpaa2_fd *fd)
+{
+ struct qbman_eq_desc ed;
+
+ d = service_select(d);
+ if (!d)
+ return -ENODEV;
+
+ qbman_eq_desc_clear(&ed);
+ qbman_eq_desc_set_no_orp(&ed, 0);
+ qbman_eq_desc_set_qd(&ed, qdid, qdbin, prio);
+
+ return qbman_swp_enqueue(d->swp, &ed, fd);
+}
+EXPORT_SYMBOL(dpaa2_io_service_enqueue_qd);
+
+/**
+ * dpaa2_io_service_release() - Release buffers to a buffer pool.
+ * @d: the given DPIO object.
+ * @bpid: the buffer pool id.
+ * @buffers: the buffers to be released.
+ * @num_buffers: the number of the buffers to be released.
+ *
+ * Return 0 for success, and negative error code for failure.
+ */
+int dpaa2_io_service_release(struct dpaa2_io *d,
+ u32 bpid,
+ const u64 *buffers,
+ unsigned int num_buffers)
+{
+ struct qbman_release_desc rd;
+
+ d = service_select(d);
+ if (!d)
+ return -ENODEV;
+
+ qbman_release_desc_clear(&rd);
+ qbman_release_desc_set_bpid(&rd, bpid);
+
+ return qbman_swp_release(d->swp, &rd, buffers, num_buffers);
+}
+EXPORT_SYMBOL(dpaa2_io_service_release);
+
+/**
+ * dpaa2_io_service_acquire() - Acquire buffers from a buffer pool.
+ * @d: the given DPIO object.
+ * @bpid: the buffer pool id.
+ * @buffers: the buffer addresses for acquired buffers.
+ * @num_buffers: the expected number of the buffers to acquire.
+ *
+ * Return a negative error code if the command failed, otherwise it returns
+ * the number of buffers acquired, which may be less than the number requested.
+ * Eg. if the buffer pool is empty, this will return zero.
+ */
+int dpaa2_io_service_acquire(struct dpaa2_io *d,
+ u32 bpid,
+ u64 *buffers,
+ unsigned int num_buffers)
+{
+ unsigned long irqflags;
+ int err;
+
+ d = service_select(d);
+ if (!d)
+ return -ENODEV;
+
+ spin_lock_irqsave(&d->lock_mgmt_cmd, irqflags);
+ err = qbman_swp_acquire(d->swp, bpid, buffers, num_buffers);
+ spin_unlock_irqrestore(&d->lock_mgmt_cmd, irqflags);
+
+ return err;
+}
+EXPORT_SYMBOL(dpaa2_io_service_acquire);
+
+/*
+ * 'Stores' are reusable memory blocks for holding dequeue results, and to
+ * assist with parsing those results.
+ */
+
+/**
+ * dpaa2_io_store_create() - Create the dma memory storage for dequeue result.
+ * @max_frames: the maximum number of dequeued result for frames, must be <= 16.
+ * @dev: the device to allow mapping/unmapping the DMAable region.
+ *
+ * The size of the storage is "max_frames*sizeof(struct dpaa2_dq)".
+ * The 'dpaa2_io_store' returned is a DPIO service managed object.
+ *
+ * Return pointer to dpaa2_io_store struct for successfuly created storage
+ * memory, or NULL on error.
+ */
+struct dpaa2_io_store *dpaa2_io_store_create(unsigned int max_frames,
+ struct device *dev)
+{
+ struct dpaa2_io_store *ret;
+ size_t size;
+
+ if (!max_frames || (max_frames > 16))
+ return NULL;
+
+ ret = kmalloc(sizeof(*ret), GFP_KERNEL);
+ if (!ret)
+ return NULL;
+
+ ret->max = max_frames;
+ size = max_frames * sizeof(struct dpaa2_dq) + 64;
+ ret->alloced_addr = kmalloc(size, GFP_KERNEL);
+ if (!ret->alloced_addr) {
+ kfree(ret);
+ return NULL;
+ }
+
+ ret->vaddr = PTR_ALIGN(ret->alloced_addr, 64);
+ ret->paddr = dma_map_single(dev, ret->vaddr,
+ sizeof(struct dpaa2_dq) * max_frames,
+ DMA_FROM_DEVICE);
+ if (dma_mapping_error(dev, ret->paddr)) {
+ kfree(ret->alloced_addr);
+ kfree(ret);
+ return NULL;
+ }
+
+ ret->idx = 0;
+ ret->dev = dev;
+
+ return ret;
+}
+EXPORT_SYMBOL(dpaa2_io_store_create);
+
+/**
+ * dpaa2_io_store_destroy() - Frees the dma memory storage for dequeue
+ * result.
+ * @s: the storage memory to be destroyed.
+ */
+void dpaa2_io_store_destroy(struct dpaa2_io_store *s)
+{
+ dma_unmap_single(s->dev, s->paddr, sizeof(struct dpaa2_dq) * s->max,
+ DMA_FROM_DEVICE);
+ kfree(s->alloced_addr);
+ kfree(s);
+}
+EXPORT_SYMBOL(dpaa2_io_store_destroy);
+
+/**
+ * dpaa2_io_store_next() - Determine when the next dequeue result is available.
+ * @s: the dpaa2_io_store object.
+ * @is_last: indicate whether this is the last frame in the pull command.
+ *
+ * When an object driver performs dequeues to a dpaa2_io_store, this function
+ * can be used to determine when the next frame result is available. Once
+ * this function returns non-NULL, a subsequent call to it will try to find
+ * the next dequeue result.
+ *
+ * Note that if a pull-dequeue has a NULL result because the target FQ/channel
+ * was empty, then this function will also return NULL (rather than expecting
+ * the caller to always check for this. As such, "is_last" can be used to
+ * differentiate between "end-of-empty-dequeue" and "still-waiting".
+ *
+ * Return dequeue result for a valid dequeue result, or NULL for empty dequeue.
+ */
+struct dpaa2_dq *dpaa2_io_store_next(struct dpaa2_io_store *s, int *is_last)
+{
+ int match;
+ struct dpaa2_dq *ret = &s->vaddr[s->idx];
+
+ match = qbman_result_has_new_result(s->swp, ret);
+ if (!match) {
+ *is_last = 0;
+ return NULL;
+ }
+
+ s->idx++;
+
+ if (dpaa2_dq_is_pull_complete(ret)) {
+ *is_last = 1;
+ s->idx = 0;
+ /*
+ * If we get an empty dequeue result to terminate a zero-results
+ * vdqcr, return NULL to the caller rather than expecting him to
+ * check non-NULL results every time.
+ */
+ if (!(dpaa2_dq_flags(ret) & DPAA2_DQ_STAT_VALIDFRAME))
+ ret = NULL;
+ } else {
+ *is_last = 0;
+ }
+
+ return ret;
+}
+EXPORT_SYMBOL(dpaa2_io_store_next);
diff --git a/include/linux/fsl/dpaa2-io.h b/include/linux/fsl/dpaa2-io.h
new file mode 100644
index 0000000..12e7ad8
--- /dev/null
+++ b/include/linux/fsl/dpaa2-io.h
@@ -0,0 +1,138 @@
+/*
+ * Copyright 2014-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:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef __FSL_DPAA2_IO_H
+#define __FSL_DPAA2_IO_H
+
+#include <linux/types.h>
+#include <linux/cpumask.h>
+
+#include <linux/fsl/dpaa2-fd.h>
+#include <linux/fsl/dpaa2-global.h>
+
+struct dpaa2_io;
+struct dpaa2_io_store;
+struct device;
+
+/**
+ * DOC: DPIO Service
+ *
+ * The DPIO service provides APIs for users to interact with the datapath
+ * by enqueueing and dequeing frame descriptors.
+ *
+ * The following set of APIs can be used to enqueue and dequeue frames
+ * as well as producing notification callbacks when data is available
+ * for dequeue.
+ */
+
+/**
+ * struct dpaa2_io_desc - The DPIO descriptor
+ * @receives_notifications: Use notificaton mode. Non-zero if the DPIO
+ * has a channel.
+ * @has_8prio: Set to non-zero for channel with 8 priority WQs. Ignored
+ * unless receives_notification is TRUE.
+ * @cpu: The cpu index that at least interrupt handlers will
+ * execute on.
+ * @stash_affinity: The stash affinity for this portal favour 'cpu'
+ * @regs_cena: The cache enabled regs.
+ * @regs_cinh: The cache inhibited regs
+ * @dpio_id: The dpio index
+ * @qman_version: The qman version
+ *
+ * Describes the attributes and features of the DPIO object.
+ */
+struct dpaa2_io_desc {
+ int receives_notifications;
+ int has_8prio;
+ int cpu;
+ void *regs_cena;
+ void *regs_cinh;
+ int dpio_id;
+ u32 qman_version;
+};
+
+struct dpaa2_io *dpaa2_io_create(const struct dpaa2_io_desc *desc);
+
+void dpaa2_io_down(struct dpaa2_io *d);
+
+irqreturn_t dpaa2_io_irq(struct dpaa2_io *obj);
+
+/**
+ * struct dpaa2_io_notification_ctx - The DPIO notification context structure
+ * @cb: The callback to be invoked when the notification arrives
+ * @is_cdan: Zero for FQDAN, non-zero for CDAN
+ * @id: FQID or channel ID, needed for rearm
+ * @desired_cpu: The cpu on which the notifications will show up. -1 means
+ * any CPU.
+ * @dpio_id: The dpio index
+ * @qman64: The 64-bit context value shows up in the FQDAN/CDAN.
+ * @node: The list node
+ * @dpio_private: The dpio object internal to dpio_service
+ *
+ * Used when a FQDAN/CDAN registration is made by drivers.
+ */
+struct dpaa2_io_notification_ctx {
+ void (*cb)(struct dpaa2_io_notification_ctx *);
+ int is_cdan;
+ u32 id;
+ int desired_cpu;
+ int dpio_id;
+ u64 qman64;
+ struct list_head node;
+ void *dpio_private;
+};
+
+int dpaa2_io_service_register(struct dpaa2_io *service,
+ struct dpaa2_io_notification_ctx *ctx);
+void dpaa2_io_service_deregister(struct dpaa2_io *service,
+ struct dpaa2_io_notification_ctx *ctx);
+int dpaa2_io_service_rearm(struct dpaa2_io *service,
+ struct dpaa2_io_notification_ctx *ctx);
+
+int dpaa2_io_service_pull_fq(struct dpaa2_io *d, u32 fqid,
+ struct dpaa2_io_store *s);
+int dpaa2_io_service_pull_channel(struct dpaa2_io *d, u32 channelid,
+ struct dpaa2_io_store *s);
+
+int dpaa2_io_service_enqueue_fq(struct dpaa2_io *d, u32 fqid,
+ const struct dpaa2_fd *fd);
+int dpaa2_io_service_enqueue_qd(struct dpaa2_io *d, u32 qdid, u8 prio,
+ u16 qdbin, const struct dpaa2_fd *fd);
+int dpaa2_io_service_release(struct dpaa2_io *d, u32 bpid,
+ const u64 *buffers, unsigned int num_buffers);
+int dpaa2_io_service_acquire(struct dpaa2_io *d, u32 bpid,
+ u64 *buffers, unsigned int num_buffers);
+
+struct dpaa2_io_store *dpaa2_io_store_create(unsigned int max_frames,
+ struct device *dev);
+void dpaa2_io_store_destroy(struct dpaa2_io_store *s);
+struct dpaa2_dq *dpaa2_io_store_next(struct dpaa2_io_store *s, int *is_last);
+
+#endif /* __FSL_DPAA2_IO_H */
--
1.9.0
From: Ioana Radulescu <[email protected]>
Add the command build/parse APIs for operating on DPIO objects through
the DPAA2 Management Complex.
Signed-off-by: Ioana Radulescu <[email protected]>
Signed-off-by: Roy Pledge <[email protected]>
Signed-off-by: Stuart Yoder <[email protected]>
---
drivers/bus/fsl-mc/Kconfig | 10 ++
drivers/bus/fsl-mc/Makefile | 3 +
drivers/bus/fsl-mc/dpio/Makefile | 9 ++
drivers/bus/fsl-mc/dpio/dpio-cmd.h | 198 ++++++++++++++++++++++++++++++++
drivers/bus/fsl-mc/dpio/dpio.c | 229 +++++++++++++++++++++++++++++++++++++
drivers/bus/fsl-mc/dpio/dpio.h | 108 +++++++++++++++++
6 files changed, 557 insertions(+)
create mode 100644 drivers/bus/fsl-mc/dpio/Makefile
create mode 100644 drivers/bus/fsl-mc/dpio/dpio-cmd.h
create mode 100644 drivers/bus/fsl-mc/dpio/dpio.c
create mode 100644 drivers/bus/fsl-mc/dpio/dpio.h
diff --git a/drivers/bus/fsl-mc/Kconfig b/drivers/bus/fsl-mc/Kconfig
index 5c009ab..a10aaf0 100644
--- a/drivers/bus/fsl-mc/Kconfig
+++ b/drivers/bus/fsl-mc/Kconfig
@@ -15,3 +15,13 @@ config FSL_MC_BUS
architecture. The fsl-mc bus driver handles discovery of
DPAA2 objects (which are represented as Linux devices) and
binding objects to drivers.
+
+config FSL_MC_DPIO
+ tristate "QorIQ DPAA2 DPIO driver"
+ depends on FSL_MC_BUS
+ help
+ Driver for the DPAA2 DPIO object. A DPIO provides queue and
+ buffer management facilities for software to interact with
+ other DPAA2 objects. This driver does not expose the DPIO
+ objects individually, but groups them under a service layer
+ API.
diff --git a/drivers/bus/fsl-mc/Makefile b/drivers/bus/fsl-mc/Makefile
index d56afee..d18df72 100644
--- a/drivers/bus/fsl-mc/Makefile
+++ b/drivers/bus/fsl-mc/Makefile
@@ -17,3 +17,6 @@ mc-bus-driver-objs := fsl-mc-bus.o \
fsl-mc-msi.o \
dpmcp.o \
dpbp.o
+
+# MC DPIO driver
+obj-$(CONFIG_FSL_MC_DPIO) += dpio/
diff --git a/drivers/bus/fsl-mc/dpio/Makefile b/drivers/bus/fsl-mc/dpio/Makefile
new file mode 100644
index 0000000..128befc
--- /dev/null
+++ b/drivers/bus/fsl-mc/dpio/Makefile
@@ -0,0 +1,9 @@
+#
+# QorIQ DPAA2 DPIO driver
+#
+
+subdir-ccflags-y := -Werror
+
+obj-$(CONFIG_FSL_MC_DPIO) += fsl-mc-dpio.o
+
+fsl-mc-dpio-objs := dpio.o
diff --git a/drivers/bus/fsl-mc/dpio/dpio-cmd.h b/drivers/bus/fsl-mc/dpio/dpio-cmd.h
new file mode 100644
index 0000000..b25a4cc
--- /dev/null
+++ b/drivers/bus/fsl-mc/dpio/dpio-cmd.h
@@ -0,0 +1,198 @@
+/*
+ * Copyright 2013-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:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of the above-listed copyright holders nor the
+ * names of any contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef _FSL_DPIO_CMD_H
+#define _FSL_DPIO_CMD_H
+
+/* DPIO Version */
+#define DPIO_VER_MAJOR 4
+#define DPIO_VER_MINOR 2
+
+/* Command Versioning */
+
+#define DPIO_CMD_ID_OFFSET 4
+#define DPIO_CMD_BASE_VERSION 1
+
+#define DPIO_CMD(id) ((id << DPIO_CMD_ID_OFFSET) | DPIO_CMD_BASE_VERSION)
+
+/* Command IDs */
+#define DPIO_CMDID_CLOSE DPIO_CMD(0x800)
+#define DPIO_CMDID_OPEN DPIO_CMD(0x803)
+#define DPIO_CMDID_CREATE DPIO_CMD(0x903)
+#define DPIO_CMDID_DESTROY DPIO_CMD(0x983)
+#define DPIO_CMDID_GET_API_VERSION DPIO_CMD(0xa03)
+
+#define DPIO_CMDID_ENABLE DPIO_CMD(0x002)
+#define DPIO_CMDID_DISABLE DPIO_CMD(0x003)
+#define DPIO_CMDID_GET_ATTR DPIO_CMD(0x004)
+#define DPIO_CMDID_RESET DPIO_CMD(0x005)
+#define DPIO_CMDID_IS_ENABLED DPIO_CMD(0x006)
+
+#define DPIO_CMDID_SET_IRQ DPIO_CMD(0x010)
+#define DPIO_CMDID_GET_IRQ DPIO_CMD(0x011)
+#define DPIO_CMDID_SET_IRQ_ENABLE DPIO_CMD(0x012)
+#define DPIO_CMDID_GET_IRQ_ENABLE DPIO_CMD(0x013)
+#define DPIO_CMDID_SET_IRQ_MASK DPIO_CMD(0x014)
+#define DPIO_CMDID_GET_IRQ_MASK DPIO_CMD(0x015)
+#define DPIO_CMDID_GET_IRQ_STATUS DPIO_CMD(0x016)
+#define DPIO_CMDID_CLEAR_IRQ_STATUS DPIO_CMD(0x017)
+
+#define DPIO_CMDID_SET_STASHING_DEST DPIO_CMD(0x120)
+#define DPIO_CMDID_GET_STASHING_DEST DPIO_CMD(0x121)
+#define DPIO_CMDID_ADD_STATIC_DEQUEUE_CHANNEL DPIO_CMD(0x122)
+#define DPIO_CMDID_REMOVE_STATIC_DEQUEUE_CHANNEL DPIO_CMD(0x123)
+
+struct dpio_cmd_open {
+ __le32 dpio_id;
+};
+
+#define DPIO_CHANNEL_MODE_MASK 0x3
+
+struct dpio_cmd_create {
+ __le16 pad0;
+ u8 channel_mode;
+ u8 pad1;
+ u8 num_priorities;
+
+};
+
+#define DPIO_ENABLE 1
+
+struct dpio_rsp_is_enabled {
+ u8 enabled;
+};
+
+struct dpio_cmd_set_irq {
+ /* cmd word 0 */
+ u8 irq_index;
+ u8 pad[3];
+ __le32 irq_val;
+ /* cmd word 1 */
+ __le64 irq_addr;
+ /* cmd word 2 */
+ __le32 irq_num;
+};
+
+struct dpio_cmd_get_irq {
+ __le32 pad;
+ u8 irq_index;
+};
+
+struct dpio_rsp_get_irq {
+ /* response word 0 */
+ __le32 irq_val;
+ __le32 pad;
+ /* response word 1 */
+ __le64 irq_addr;
+ /* response word 2 */
+ __le32 irq_num;
+ __le32 type;
+};
+
+struct dpio_cmd_set_irq_enable {
+ u8 enable;
+ u8 pad[3];
+ u8 irq_index;
+};
+
+struct dpio_cmd_get_irq_enable {
+ __le32 pad;
+ u8 irq_index;
+};
+
+struct dpio_rsp_get_irq_enable {
+ u8 enabled;
+};
+
+struct dpio_cmd_set_irq_mask {
+ __le32 mask;
+ u8 irq_index;
+};
+
+struct dpio_cmd_get_irq_mask {
+ __le32 pad;
+ u8 irq_index;
+};
+
+struct dpio_rsp_get_irq_mask {
+ __le32 mask;
+};
+
+struct dpio_cmd_get_irq_status {
+ __le32 status;
+ u8 irq_index;
+};
+
+struct dpio_rsp_get_irq_status {
+ __le32 status;
+};
+
+struct dpio_cmd_clear_irq_status {
+ __le32 status;
+ u8 irq_index;
+};
+
+struct dpio_rsp_get_attr {
+ /* cmd word 0 */
+ __le32 id;
+ __le16 qbman_portal_id;
+ u8 num_priorities;
+ u8 channel_mode;
+ /* cmd word 1 */
+ __le64 qbman_portal_ce_addr;
+ /* cmd word 2 */
+ __le64 qbman_portal_ci_addr;
+ /* cmd word 3 */
+ __le32 pad;
+ __le32 qbman_version;
+};
+
+struct dpio_cmd_set_stashing_dest {
+ u8 sdest;
+};
+
+struct dpio_rsp_get_stashing_dest {
+ u8 sdest;
+};
+
+struct dpio_cmd_add_static_dequeue_channel {
+ __le32 dpcon_id;
+};
+
+struct dpio_rsp_add_static_dequeue_channel {
+ u8 channel_index;
+};
+
+struct dpio_cmd_remove_static_dequeue_channel {
+ __le32 dpcon_id;
+};
+
+#endif /* _FSL_DPIO_CMD_H */
diff --git a/drivers/bus/fsl-mc/dpio/dpio.c b/drivers/bus/fsl-mc/dpio/dpio.c
new file mode 100644
index 0000000..5f1ee19
--- /dev/null
+++ b/drivers/bus/fsl-mc/dpio/dpio.c
@@ -0,0 +1,229 @@
+/*
+ * Copyright 2013-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:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of the above-listed copyright holders nor the
+ * names of any contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+#include <linux/fsl/mc-sys.h>
+#include <linux/fsl/mc-cmd.h>
+
+#include "dpio.h"
+#include "dpio-cmd.h"
+
+/*
+ * Data Path I/O Portal API
+ * Contains initialization APIs and runtime control APIs for DPIO
+ */
+
+/**
+ * dpio_open() - Open a control session for the specified object
+ * @mc_io: Pointer to MC portal's I/O object
+ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
+ * @dpio_id: DPIO unique ID
+ * @token: Returned token; use in subsequent API calls
+ *
+ * This function can be used to open a control session for an
+ * already created object; an object may have been declared in
+ * the DPL or by calling the dpio_create() function.
+ * This function returns a unique authentication token,
+ * associated with the specific object ID and the specific MC
+ * portal; this token must be used in all subsequent commands for
+ * this specific object.
+ *
+ * Return: '0' on Success; Error code otherwise.
+ */
+int dpio_open(struct fsl_mc_io *mc_io,
+ u32 cmd_flags,
+ int dpio_id,
+ u16 *token)
+{
+ struct mc_command cmd = { 0 };
+ struct dpio_cmd_open *dpio_cmd;
+ int err;
+
+ /* prepare command */
+ cmd.header = mc_encode_cmd_header(DPIO_CMDID_OPEN,
+ cmd_flags,
+ 0);
+ dpio_cmd = (struct dpio_cmd_open *)cmd.params;
+ dpio_cmd->dpio_id = cpu_to_le32(dpio_id);
+
+ /* send command to mc*/
+ err = mc_send_command(mc_io, &cmd);
+ if (err)
+ return err;
+
+ /* retrieve response parameters */
+ *token = mc_cmd_hdr_read_token(&cmd);
+
+ return 0;
+}
+
+/**
+ * dpio_close() - Close the control session of the object
+ * @mc_io: Pointer to MC portal's I/O object
+ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
+ * @token: Token of DPIO object
+ *
+ * Return: '0' on Success; Error code otherwise.
+ */
+int dpio_close(struct fsl_mc_io *mc_io,
+ u32 cmd_flags,
+ u16 token)
+{
+ struct mc_command cmd = { 0 };
+
+ /* prepare command */
+ cmd.header = mc_encode_cmd_header(DPIO_CMDID_CLOSE,
+ cmd_flags,
+ token);
+
+ /* send command to mc*/
+ return mc_send_command(mc_io, &cmd);
+}
+
+/**
+ * dpio_enable() - Enable the DPIO, allow I/O portal operations.
+ * @mc_io: Pointer to MC portal's I/O object
+ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
+ * @token: Token of DPIO object
+ *
+ * Return: '0' on Success; Error code otherwise
+ */
+int dpio_enable(struct fsl_mc_io *mc_io,
+ u32 cmd_flags,
+ u16 token)
+{
+ struct mc_command cmd = { 0 };
+
+ /* prepare command */
+ cmd.header = mc_encode_cmd_header(DPIO_CMDID_ENABLE,
+ cmd_flags,
+ token);
+
+ /* send command to mc*/
+ return mc_send_command(mc_io, &cmd);
+}
+
+/**
+ * dpio_disable() - Disable the DPIO, stop any I/O portal operation.
+ * @mc_io: Pointer to MC portal's I/O object
+ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
+ * @token: Token of DPIO object
+ *
+ * Return: '0' on Success; Error code otherwise
+ */
+int dpio_disable(struct fsl_mc_io *mc_io,
+ u32 cmd_flags,
+ u16 token)
+{
+ struct mc_command cmd = { 0 };
+
+ /* prepare command */
+ cmd.header = mc_encode_cmd_header(DPIO_CMDID_DISABLE,
+ cmd_flags,
+ token);
+
+ /* send command to mc*/
+ return mc_send_command(mc_io, &cmd);
+}
+
+/**
+ * dpio_get_attributes() - Retrieve DPIO attributes
+ * @mc_io: Pointer to MC portal's I/O object
+ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
+ * @token: Token of DPIO object
+ * @attr: Returned object's attributes
+ *
+ * Return: '0' on Success; Error code otherwise
+ */
+int dpio_get_attributes(struct fsl_mc_io *mc_io,
+ u32 cmd_flags,
+ u16 token,
+ struct dpio_attr *attr)
+{
+ struct mc_command cmd = { 0 };
+ struct dpio_rsp_get_attr *dpio_rsp;
+ int err;
+
+ /* prepare command */
+ cmd.header = mc_encode_cmd_header(DPIO_CMDID_GET_ATTR,
+ cmd_flags,
+ token);
+
+ /* send command to mc*/
+ err = mc_send_command(mc_io, &cmd);
+ if (err)
+ return err;
+
+ /* retrieve response parameters */
+ dpio_rsp = (struct dpio_rsp_get_attr *)cmd.params;
+ attr->id = le32_to_cpu(dpio_rsp->id);
+ attr->qbman_portal_id = le16_to_cpu(dpio_rsp->qbman_portal_id);
+ attr->num_priorities = dpio_rsp->num_priorities;
+ attr->channel_mode = dpio_rsp->channel_mode & DPIO_CHANNEL_MODE_MASK;
+ attr->qbman_portal_ce_offset =
+ le64_to_cpu(dpio_rsp->qbman_portal_ce_addr);
+ attr->qbman_portal_ci_offset =
+ le64_to_cpu(dpio_rsp->qbman_portal_ci_addr);
+ attr->qbman_version = le32_to_cpu(dpio_rsp->qbman_version);
+
+ return 0;
+}
+
+/**
+ * dpio_get_api_version - Get Data Path I/O API version
+ * @mc_io: Pointer to MC portal's DPIO object
+ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
+ * @major_ver: Major version of DPIO API
+ * @minor_ver: Minor version of DPIO API
+ *
+ * Return: '0' on Success; Error code otherwise
+ */
+int dpio_get_api_version(struct fsl_mc_io *mc_io,
+ u32 cmd_flags,
+ u16 *major_ver,
+ u16 *minor_ver)
+{
+ struct mc_command cmd = { 0 };
+ int err;
+
+ /* prepare command */
+ cmd.header = mc_encode_cmd_header(DPIO_CMDID_GET_API_VERSION,
+ cmd_flags, 0);
+
+ /* send command to mc */
+ err = mc_send_command(mc_io, &cmd);
+ if (err)
+ return err;
+
+ /* retrieve response parameters */
+ mc_cmd_read_api_version(&cmd, major_ver, minor_ver);
+
+ return 0;
+}
diff --git a/drivers/bus/fsl-mc/dpio/dpio.h b/drivers/bus/fsl-mc/dpio/dpio.h
new file mode 100644
index 0000000..743ceca
--- /dev/null
+++ b/drivers/bus/fsl-mc/dpio/dpio.h
@@ -0,0 +1,108 @@
+/*
+ * Copyright 2013-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:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of the above-listed copyright holders nor the
+ * names of any contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef __FSL_DPIO_H
+#define __FSL_DPIO_H
+
+struct fsl_mc_io;
+
+int dpio_open(struct fsl_mc_io *mc_io,
+ u32 cmd_flags,
+ int dpio_id,
+ u16 *token);
+
+int dpio_close(struct fsl_mc_io *mc_io,
+ u32 cmd_flags,
+ u16 token);
+
+/**
+ * enum dpio_channel_mode - DPIO notification channel mode
+ * @DPIO_NO_CHANNEL: No support for notification channel
+ * @DPIO_LOCAL_CHANNEL: Notifications on data availability can be received by a
+ * dedicated channel in the DPIO; user should point the queue's
+ * destination in the relevant interface to this DPIO
+ */
+enum dpio_channel_mode {
+ DPIO_NO_CHANNEL = 0,
+ DPIO_LOCAL_CHANNEL = 1,
+};
+
+/**
+ * struct dpio_cfg - Structure representing DPIO configuration
+ * @channel_mode: Notification channel mode
+ * @num_priorities: Number of priorities for the notification channel (1-8);
+ * relevant only if 'channel_mode = DPIO_LOCAL_CHANNEL'
+ */
+struct dpio_cfg {
+ enum dpio_channel_mode channel_mode;
+ u8 num_priorities;
+};
+
+int dpio_enable(struct fsl_mc_io *mc_io,
+ u32 cmd_flags,
+ u16 token);
+
+int dpio_disable(struct fsl_mc_io *mc_io,
+ u32 cmd_flags,
+ u16 token);
+
+/**
+ * struct dpio_attr - Structure representing DPIO attributes
+ * @id: DPIO object ID
+ * @qbman_portal_ce_offset: offset of the software portal cache-enabled area
+ * @qbman_portal_ci_offset: offset of the software portal cache-inhibited area
+ * @qbman_portal_id: Software portal ID
+ * @channel_mode: Notification channel mode
+ * @num_priorities: Number of priorities for the notification channel (1-8);
+ * relevant only if 'channel_mode = DPIO_LOCAL_CHANNEL'
+ * @qbman_version: QBMAN version
+ */
+struct dpio_attr {
+ int id;
+ u64 qbman_portal_ce_offset;
+ u64 qbman_portal_ci_offset;
+ u16 qbman_portal_id;
+ enum dpio_channel_mode channel_mode;
+ u8 num_priorities;
+ u32 qbman_version;
+};
+
+int dpio_get_attributes(struct fsl_mc_io *mc_io,
+ u32 cmd_flags,
+ u16 token,
+ struct dpio_attr *attr);
+
+int dpio_get_api_version(struct fsl_mc_io *mc_io,
+ u32 cmd_flags,
+ u16 *major_ver,
+ u16 *minor_ver);
+
+#endif /* __FSL_DPIO_H */
--
1.9.0
add document describing the dpio driver and it's role, components
and major interfaces
Signed-off-by: Stuart Yoder <[email protected]>
---
Documentation/dpaa2/dpio-driver.txt | 135 ++++++++++++++++++++++++++++++++++++
1 file changed, 135 insertions(+)
create mode 100644 Documentation/dpaa2/dpio-driver.txt
diff --git a/Documentation/dpaa2/dpio-driver.txt b/Documentation/dpaa2/dpio-driver.txt
new file mode 100644
index 0000000..5c192b3
--- /dev/null
+++ b/Documentation/dpaa2/dpio-driver.txt
@@ -0,0 +1,135 @@
+Copyright (C) 2016 Freescale Semiconductor Inc.
+
+Introduction
+------------
+
+A DPAA2 DPIO (Data Path I/O) is a hardware object that provides
+interfaces to enqueue and dequeue frames to/from network interfaces
+and other accelerators. A DPIO also provides hardware buffer
+pool management for network interfaces.
+
+This document provides an overview the Linux DPIO driver, its
+subcomponents, and its APIs.
+
+See Documentation/dpaa2/overview.txt for a general overview of DPAA2
+and the general DPAA2 driver architecture in Linux.
+
+Driver Overview
+---------------
+
+The DPIO driver is bound to DPIO objects discovered on the fsl-mc bus and
+provides services that:
+ A) allow other drivers, such as the Ethernet driver, to enqueue and dequeue
+ frames for their respective objects
+ B) allow drivers to register callbacks for data availability notifications
+ when data becomes available on a queue or channel
+ C) allow drivers to manage hardware buffer pools
+
+The Linux DPIO driver consists of 3 primary components--
+ DPIO object driver-- fsl-mc driver that manages the DPIO object
+ DPIO service-- provides APIs to other Linux drivers for services
+ QBman portal interface-- sends portal commands, gets responses
+
+ fsl-mc other
+ bus drivers
+ | |
+ +---+----+ +------+-----+
+ |DPIO obj| |DPIO service|
+ | driver |---| (DPIO) |
+ +--------+ +------+-----+
+ |
+ +------+-----+
+ | QBman |
+ | portal i/f |
+ +------------+
+ |
+ hardware
+
+The diagram below shows how the DPIO driver components fit with the other
+DPAA2 Linux driver components:
+ +------------+
+ | OS Network |
+ | Stack |
+ +------------+ +------------+
+ | Allocator |. . . . . . . | Ethernet |
+ |(DPMCP,DPBP)| | (DPNI) |
+ +-.----------+ +---+---+----+
+ . . ^ |
+ . . <data avail, | |<enqueue,
+ . . tx confirm> | | dequeue>
+ +-------------+ . | |
+ | DPRC driver | . +--------+ +------------+
+ | (DPRC) | . . |DPIO obj| |DPIO service|
+ +----------+--+ | driver |-| (DPIO) |
+ | +--------+ +------+-----+
+ |<dev add/remove> +------|-----+
+ | | QBman |
+ +----+--------------+ | portal i/f |
+ | MC-bus driver | +------------+
+ | | |
+ | /soc/fsl-mc | |
+ +-------------------+ |
+ |
+ =========================================|=========|========================
+ +-+--DPIO---|-----------+
+ | | |
+ | QBman Portal |
+ +-----------------------+
+
+ ============================================================================
+
+
+DPIO Object Driver (dpio-driver.c)
+----------------------------------
+
+ The dpio-driver component registers with the fsl-mc bus to handle objects of
+ type "dpio". The implementation of probe() handles basic initialization
+ of the DPIO including mapping of the DPIO regions (the QBman SW portal)
+ and initializing interrupts and registering irq handlers. The dpio-driver
+ registers the probed DPIO with dpio-service.
+
+DPIO service (dpio-service.c, dpaa2-io.h)
+------------------------------------------
+
+ The dpio service component provides queuing, notification, and buffers
+ management services to DPAA2 drivers, such as the Ethernet driver. A system
+ will typically allocate 1 DPIO object per CPU to allow queuing operations
+ to happen simultaneously across all CPUs.
+
+ Notification handling
+ dpaa2_io_service_register()
+ dpaa2_io_service_deregister()
+ dpaa2_io_service_rearm()
+
+ Queuing
+ dpaa2_io_service_pull_fq()
+ dpaa2_io_service_pull_channel()
+ dpaa2_io_service_enqueue_fq()
+ dpaa2_io_service_enqueue_qd()
+ dpaa2_io_store_create()
+ dpaa2_io_store_destroy()
+ dpaa2_io_store_next()
+
+ Buffer pool management
+ dpaa2_io_service_release()
+ dpaa2_io_service_acquire()
+
+QBman portal interface (qbman-portal.c)
+---------------------------------------
+
+ The qbman-portal component provides APIs to do the low level hardware
+ bit twiddling for operations such as:
+ -initializing Qman software portals
+ -building and sending portal commands
+ -portal interrupt configuration and processing
+
+ The qbman-portal APIs are not public to other drivers, and are
+ only used by dpio-service.
+
+Other (dpaa2-fd.h, dpaa2-global.h)
+----------------------------------
+
+ Frame descriptor and scatter-gather definitions and the APIs used to
+ manipulate them are defined in dpaa2-fd.h.
+
+ Dequeue result struct and parsing APIs are defined in dpaa2-global.h.
--
1.9.0
From: Roy Pledge <[email protected]>
Create header for global dpaa2 definitions. Add definitions
for dequeue results.
Signed-off-by: Roy Pledge <[email protected]>
Signed-off-by: Stuart Yoder <[email protected]>
---
include/linux/fsl/dpaa2-global.h | 203 +++++++++++++++++++++++++++++++++++++++
1 file changed, 203 insertions(+)
create mode 100644 include/linux/fsl/dpaa2-global.h
diff --git a/include/linux/fsl/dpaa2-global.h b/include/linux/fsl/dpaa2-global.h
new file mode 100644
index 0000000..3ee3f29
--- /dev/null
+++ b/include/linux/fsl/dpaa2-global.h
@@ -0,0 +1,203 @@
+/*
+ * Copyright 2014-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:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef __FSL_DPAA2_GLOBAL_H
+#define __FSL_DPAA2_GLOBAL_H
+
+#include <linux/types.h>
+#include <linux/cpumask.h>
+#include <linux/fsl/dpaa2-fd.h>
+
+struct dpaa2_dq {
+ union {
+ struct common {
+ u8 verb;
+ u8 reserved[63];
+ } common;
+ struct dq {
+ u8 verb;
+ u8 stat;
+ __le16 seqnum;
+ __le16 oprid;
+ u8 reserved;
+ u8 tok;
+ __le32 fqid;
+ u32 reserved2;
+ __le32 fq_byte_cnt;
+ __le32 fq_frm_cnt;
+ __le64 fqd_ctx;
+ u8 fd[32];
+ } dq;
+ struct scn {
+ u8 verb;
+ u8 stat;
+ u8 state;
+ u8 reserved;
+ __le32 rid_tok;
+ __le64 ctx;
+ } scn;
+ };
+};
+
+
+/* Parsing frame dequeue results */
+/* FQ empty */
+#define DPAA2_DQ_STAT_FQEMPTY 0x80
+/* FQ held active */
+#define DPAA2_DQ_STAT_HELDACTIVE 0x40
+/* FQ force eligible */
+#define DPAA2_DQ_STAT_FORCEELIGIBLE 0x20
+/* valid frame */
+#define DPAA2_DQ_STAT_VALIDFRAME 0x10
+/* FQ ODP enable */
+#define DPAA2_DQ_STAT_ODPVALID 0x04
+/* volatile dequeue */
+#define DPAA2_DQ_STAT_VOLATILE 0x02
+/* volatile dequeue command is expired */
+#define DPAA2_DQ_STAT_EXPIRED 0x01
+
+#define DQ_FQID_MASK 0x00FFFFFF
+#define DQ_FRAME_COUNT_MASK 0x00FFFFFF
+
+/**
+ * dpaa2_dq_flags() - Get the stat field of dequeue response
+ * @dq: the dequeue result.
+ */
+static inline u32 dpaa2_dq_flags(const struct dpaa2_dq *dq)
+{
+ return dq->dq.stat;
+}
+
+/**
+ * dpaa2_dq_is_pull() - Check whether the dq response is from a pull
+ * command.
+ * @dq: the dequeue result
+ *
+ * Return 1 for volatile(pull) dequeue, 0 for static dequeue.
+ */
+static inline int dpaa2_dq_is_pull(const struct dpaa2_dq *dq)
+{
+ return (int)(dpaa2_dq_flags(dq) & DPAA2_DQ_STAT_VOLATILE);
+}
+
+/**
+ * dpaa2_dq_is_pull_complete() - Check whether the pull command is completed.
+ * @dq: the dequeue result
+ *
+ * Return boolean.
+ */
+static inline int dpaa2_dq_is_pull_complete(
+ const struct dpaa2_dq *dq)
+{
+ return (int)(dpaa2_dq_flags(dq) & DPAA2_DQ_STAT_EXPIRED);
+}
+
+/**
+ * dpaa2_dq_seqnum() - Get the seqnum field in dequeue response
+ * @dq: the dequeue result
+ *
+ * seqnum is valid only if VALIDFRAME flag is TRUE
+ *
+ * Return seqnum.
+ */
+static inline u16 dpaa2_dq_seqnum(const struct dpaa2_dq *dq)
+{
+ return le16_to_cpu(dq->dq.seqnum);
+}
+
+/**
+ * dpaa2_dq_odpid() - Get the odpid field in dequeue response
+ * @dq: the dequeue result
+ *
+ * odpid is valid only if ODPVAILD flag is TRUE.
+ *
+ * Return odpid.
+ */
+static inline u16 dpaa2_dq_odpid(const struct dpaa2_dq *dq)
+{
+ return le16_to_cpu(dq->dq.oprid);
+}
+
+/**
+ * dpaa2_dq_fqid() - Get the fqid in dequeue response
+ * @dq: the dequeue result
+ *
+ * Return fqid.
+ */
+static inline u32 dpaa2_dq_fqid(const struct dpaa2_dq *dq)
+{
+ return le32_to_cpu(dq->dq.fqid) & DQ_FQID_MASK;
+}
+
+/**
+ * dpaa2_dq_byte_count() - Get the byte count in dequeue response
+ * @dq: the dequeue result
+ *
+ * Return the byte count remaining in the FQ.
+ */
+static inline u32 dpaa2_dq_byte_count(const struct dpaa2_dq *dq)
+{
+ return le32_to_cpu(dq->dq.fq_byte_cnt);
+}
+
+/**
+ * dpaa2_dq_frame_count() - Get the frame count in dequeue response
+ * @dq: the dequeue result
+ *
+ * Return the frame count remaining in the FQ.
+ */
+static inline u32 dpaa2_dq_frame_count(const struct dpaa2_dq *dq)
+{
+ return le32_to_cpu(dq->dq.fq_frm_cnt) & DQ_FRAME_COUNT_MASK;
+}
+
+/**
+ * dpaa2_dq_fd_ctx() - Get the frame queue context in dequeue response
+ * @dq: the dequeue result
+ *
+ * Return the frame queue context.
+ */
+static inline u64 dpaa2_dq_fqd_ctx(const struct dpaa2_dq *dq)
+{
+ return le64_to_cpu(dq->dq.fqd_ctx);
+}
+
+/**
+ * dpaa2_dq_fd() - Get the frame descriptor in dequeue response
+ * @dq: the dequeue result
+ *
+ * Return the frame descriptor.
+ */
+static inline const struct dpaa2_fd *dpaa2_dq_fd(const struct dpaa2_dq *dq)
+{
+ return (const struct dpaa2_fd *)&dq->dq.fd[0];
+}
+
+#endif /* __FSL_DPAA2_GLOBAL_H */
--
1.9.0
From: Roy Pledge <[email protected]>
The DPIO driver registers with the fsl-mc bus to handle bus-related
events for DPIO objects. Key responsibility is mapping I/O
regions, setting up interrupt handlers, and calling the DPIO
service initialization during probe.
Signed-off-by: Roy Pledge <[email protected]>
Signed-off-by: Haiying Wang <[email protected]>
Signed-off-by: Stuart Yoder <[email protected]>
---
drivers/bus/fsl-mc/dpio/Makefile | 2 +-
drivers/bus/fsl-mc/dpio/dpio-driver.c | 289 ++++++++++++++++++++++++++++++++++
2 files changed, 290 insertions(+), 1 deletion(-)
create mode 100644 drivers/bus/fsl-mc/dpio/dpio-driver.c
diff --git a/drivers/bus/fsl-mc/dpio/Makefile b/drivers/bus/fsl-mc/dpio/Makefile
index 0778da7..837d330 100644
--- a/drivers/bus/fsl-mc/dpio/Makefile
+++ b/drivers/bus/fsl-mc/dpio/Makefile
@@ -6,4 +6,4 @@ subdir-ccflags-y := -Werror
obj-$(CONFIG_FSL_MC_DPIO) += fsl-mc-dpio.o
-fsl-mc-dpio-objs := dpio.o qbman-portal.o dpio-service.o
+fsl-mc-dpio-objs := dpio.o qbman-portal.o dpio-service.o dpio-driver.o
diff --git a/drivers/bus/fsl-mc/dpio/dpio-driver.c b/drivers/bus/fsl-mc/dpio/dpio-driver.c
new file mode 100644
index 0000000..ad04a2c
--- /dev/null
+++ b/drivers/bus/fsl-mc/dpio/dpio-driver.c
@@ -0,0 +1,289 @@
+/*
+ * Copyright 2014-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:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/interrupt.h>
+#include <linux/msi.h>
+#include <linux/dma-mapping.h>
+#include <linux/delay.h>
+
+#include <linux/fsl/mc.h>
+#include <linux/fsl/dpaa2-io.h>
+
+#include "qbman-portal.h"
+#include "dpio.h"
+#include "dpio-cmd.h"
+
+MODULE_LICENSE("Dual BSD/GPL");
+MODULE_AUTHOR("Freescale Semiconductor, Inc");
+MODULE_DESCRIPTION("DPIO Driver");
+
+struct dpio_priv {
+ struct dpaa2_io *io;
+};
+
+static irqreturn_t dpio_irq_handler(int irq_num, void *arg)
+{
+ struct device *dev = (struct device *)arg;
+ struct dpio_priv *priv = dev_get_drvdata(dev);
+
+ return dpaa2_io_irq(priv->io);
+}
+
+static void unregister_dpio_irq_handlers(struct fsl_mc_device *dpio_dev)
+{
+ struct fsl_mc_device_irq *irq;
+
+ irq = dpio_dev->irqs[0];
+
+ /* clear the affinity hint */
+ irq_set_affinity_hint(irq->msi_desc->irq, NULL);
+}
+
+static int register_dpio_irq_handlers(struct fsl_mc_device *dpio_dev, int cpu)
+{
+ struct dpio_priv *priv;
+ int error;
+ struct fsl_mc_device_irq *irq;
+ cpumask_t mask;
+
+ priv = dev_get_drvdata(&dpio_dev->dev);
+
+ irq = dpio_dev->irqs[0];
+ error = devm_request_irq(&dpio_dev->dev,
+ irq->msi_desc->irq,
+ dpio_irq_handler,
+ 0,
+ dev_name(&dpio_dev->dev),
+ &dpio_dev->dev);
+ if (error < 0) {
+ dev_err(&dpio_dev->dev,
+ "devm_request_irq() failed: %d\n",
+ error);
+ return error;
+ }
+
+ /* set the affinity hint */
+ cpumask_clear(&mask);
+ cpumask_set_cpu(cpu, &mask);
+ if (irq_set_affinity_hint(irq->msi_desc->irq, &mask))
+ dev_err(&dpio_dev->dev,
+ "irq_set_affinity failed irq %d cpu %d\n",
+ irq->msi_desc->irq, cpu);
+
+ return 0;
+}
+
+static int dpaa2_dpio_probe(struct fsl_mc_device *dpio_dev)
+{
+ struct dpio_attr dpio_attrs;
+ struct dpaa2_io_desc desc;
+ struct dpio_priv *priv;
+ int err = -ENOMEM;
+ struct device *dev = &dpio_dev->dev;
+ static int next_cpu = -1;
+
+ priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+ if (!priv)
+ goto err_priv_alloc;
+
+ dev_set_drvdata(dev, priv);
+
+ err = fsl_mc_portal_allocate(dpio_dev, 0, &dpio_dev->mc_io);
+ if (err) {
+ dev_dbg(dev, "MC portal allocation failed\n");
+ err = -EPROBE_DEFER;
+ goto err_mcportal;
+ }
+
+ err = dpio_open(dpio_dev->mc_io, 0, dpio_dev->obj_desc.id,
+ &dpio_dev->mc_handle);
+ if (err) {
+ dev_err(dev, "dpio_open() failed\n");
+ goto err_open;
+ }
+
+ err = dpio_get_attributes(dpio_dev->mc_io, 0, dpio_dev->mc_handle,
+ &dpio_attrs);
+ if (err) {
+ dev_err(dev, "dpio_get_attributes() failed %d\n", err);
+ goto err_get_attr;
+ }
+ desc.qman_version = dpio_attrs.qbman_version;
+
+ err = dpio_enable(dpio_dev->mc_io, 0, dpio_dev->mc_handle);
+ if (err) {
+ dev_err(dev, "dpio_enable() failed %d\n", err);
+ goto err_get_attr;
+ }
+
+ /* initialize DPIO descriptor */
+ desc.receives_notifications = dpio_attrs.num_priorities ? 1 : 0;
+ desc.has_8prio = dpio_attrs.num_priorities == 8 ? 1 : 0;
+ desc.dpio_id = dpio_dev->obj_desc.id;
+
+ /* get the cpu to use for the affinity hint */
+ if (next_cpu == -1)
+ next_cpu = cpumask_first(cpu_online_mask);
+ else
+ next_cpu = cpumask_next(next_cpu, cpu_online_mask);
+ desc.cpu = next_cpu;
+
+ /*
+ * Set the CENA regs to be the cache inhibited area of the portal to
+ * avoid coherency issues if a user migrates to another core.
+ */
+ desc.regs_cena = ioremap_wc(dpio_dev->regions[1].start,
+ resource_size(&dpio_dev->regions[1]));
+ desc.regs_cinh = ioremap(dpio_dev->regions[1].start,
+ resource_size(&dpio_dev->regions[1]));
+
+ err = fsl_mc_allocate_irqs(dpio_dev);
+ if (err) {
+ dev_err(dev, "fsl_mc_allocate_irqs failed. err=%d\n", err);
+ goto err_allocate_irqs;
+ }
+
+ err = register_dpio_irq_handlers(dpio_dev, desc.cpu);
+ if (err)
+ goto err_register_dpio_irq;
+
+ priv->io = dpaa2_io_create(&desc);
+ if (!priv->io) {
+ dev_err(dev, "dpaa2_io_create failed\n");
+ goto err_dpaa2_io_create;
+ }
+
+ dev_info(dev, "probed\n");
+ dev_dbg(dev, " receives_notifications = %d\n",
+ desc.receives_notifications);
+ dpio_close(dpio_dev->mc_io, 0, dpio_dev->mc_handle);
+ fsl_mc_portal_free(dpio_dev->mc_io);
+
+ return 0;
+
+err_dpaa2_io_create:
+ unregister_dpio_irq_handlers(dpio_dev);
+err_register_dpio_irq:
+ fsl_mc_free_irqs(dpio_dev);
+err_allocate_irqs:
+ dpio_disable(dpio_dev->mc_io, 0, dpio_dev->mc_handle);
+err_get_attr:
+ dpio_close(dpio_dev->mc_io, 0, dpio_dev->mc_handle);
+err_open:
+ fsl_mc_portal_free(dpio_dev->mc_io);
+err_mcportal:
+ dev_set_drvdata(dev, NULL);
+err_priv_alloc:
+ return err;
+}
+
+/* Tear down interrupts for a given DPIO object */
+static void dpio_teardown_irqs(struct fsl_mc_device *dpio_dev)
+{
+ unregister_dpio_irq_handlers(dpio_dev);
+ fsl_mc_free_irqs(dpio_dev);
+}
+
+static int dpaa2_dpio_remove(struct fsl_mc_device *dpio_dev)
+{
+ struct device *dev;
+ struct dpio_priv *priv;
+ int err;
+
+ dev = &dpio_dev->dev;
+ priv = dev_get_drvdata(dev);
+
+ dpaa2_io_down(priv->io);
+
+ dpio_teardown_irqs(dpio_dev);
+
+ err = fsl_mc_portal_allocate(dpio_dev, 0, &dpio_dev->mc_io);
+ if (err) {
+ dev_err(dev, "MC portal allocation failed\n");
+ goto err_mcportal;
+ }
+
+ err = dpio_open(dpio_dev->mc_io, 0, dpio_dev->obj_desc.id,
+ &dpio_dev->mc_handle);
+ if (err) {
+ dev_err(dev, "dpio_open() failed\n");
+ goto err_open;
+ }
+
+ dpio_disable(dpio_dev->mc_io, 0, dpio_dev->mc_handle);
+
+ dpio_close(dpio_dev->mc_io, 0, dpio_dev->mc_handle);
+
+ fsl_mc_portal_free(dpio_dev->mc_io);
+
+ dev_set_drvdata(dev, NULL);
+
+ return 0;
+
+err_open:
+ fsl_mc_portal_free(dpio_dev->mc_io);
+err_mcportal:
+ return err;
+}
+
+static const struct fsl_mc_device_id dpaa2_dpio_match_id_table[] = {
+ {
+ .vendor = FSL_MC_VENDOR_FREESCALE,
+ .obj_type = "dpio",
+ },
+ { .vendor = 0x0 }
+};
+
+static struct fsl_mc_driver dpaa2_dpio_driver = {
+ .driver = {
+ .name = KBUILD_MODNAME,
+ .owner = THIS_MODULE,
+ },
+ .probe = dpaa2_dpio_probe,
+ .remove = dpaa2_dpio_remove,
+ .match_id_table = dpaa2_dpio_match_id_table
+};
+
+static int dpio_driver_init(void)
+{
+ return fsl_mc_driver_register(&dpaa2_dpio_driver);
+}
+
+static void dpio_driver_exit(void)
+{
+ fsl_mc_driver_unregister(&dpaa2_dpio_driver);
+}
+module_init(dpio_driver_init);
+module_exit(dpio_driver_exit);
--
1.9.0
Hi Stuart,
On 10/21/2016 04:01 PM, Stuart Yoder wrote:
> This patch series: A) addresses the final item in the staging
> TODO list for the fsl-mc bus driver-- adding a functional driver
> on top of the bus driver, and B) requests that the fsl-mc bus driver
> be moved out of staging.
Awesome, it's great to see progress again! :)
> The proposed destination for the bus driver is drivers/bus.
> Proposed location for global header files for fsl-mc and dpaa2
> is include/linux/fsl.
>
> The functional driver added is for the DPIO object which provides
> queuing services for other DPAA2 drivers. An overview of the
I thought the idea of the TODO item was to have a full-fledged user of
the bus, like a full network driver. The TODO item reads:
> -* Add at least one device driver for a DPAA2 object (child device of the
> - fsl-mc bus). Most likely candidate for this is adding DPAA2 Ethernet
> - driver support, which depends on drivers for several objects: DPNI,
> - DPIO, DPMAC. Other pre-requisites include:
which to me indicates that DPIO is only part of that goal. Of course I'm
the last person blocking progress to move the driver out of staging. But
are we at the right point yet?
To me the topmost important bit of having this outside of staging is
actually missing in the TODO list (probably since it's obvious): Have
stable, reliable, responsible maintainership for the code.
So far I've seen German do the initial push upstream, then there was
silence for a while. Now some time passed and you push a few bits here
and there again. All of the efforts are great and very appreciated, but
I'm missing the "maintainer" figure. Some peer to German and you who
oversees the whole thing, reviews your patches and devotes at least 2-3
days a week to only upstream fsl-mc work. Someone like York for U-Boot
or Scott for general Linux work.
Without that, there's too much of a chance that the code will stay
incomplete, bitrot, etc. And that'd be bad for everyone involved. I
think the concept behind fsl-mc is great and exactly what people need,
so we should make sure it succeeds.
Alex
> -----Original Message-----
> From: Alexander Graf [mailto:[email protected]]
> Sent: Monday, October 24, 2016 9:34 AM
> To: Stuart Yoder <[email protected]>; [email protected]
> Cc: German Rivera <[email protected]>; [email protected]; [email protected];
> [email protected]; Leo Li <[email protected]>
> Subject: Re: [PATCH 0/9] staging: fsl-mc: move bus driver out of staging, add dpio
>
> Hi Stuart,
>
> On 10/21/2016 04:01 PM, Stuart Yoder wrote:
> > This patch series: A) addresses the final item in the staging
> > TODO list for the fsl-mc bus driver-- adding a functional driver
> > on top of the bus driver, and B) requests that the fsl-mc bus driver
> > be moved out of staging.
>
> Awesome, it's great to see progress again! :)
>
> > The proposed destination for the bus driver is drivers/bus.
> > Proposed location for global header files for fsl-mc and dpaa2
> > is include/linux/fsl.
> >
> > The functional driver added is for the DPIO object which provides
> > queuing services for other DPAA2 drivers. An overview of the
>
> I thought the idea of the TODO item was to have a full-fledged user of
> the bus, like a full network driver. The TODO item reads:
>
> > -* Add at least one device driver for a DPAA2 object (child device of the
> > - fsl-mc bus). Most likely candidate for this is adding DPAA2 Ethernet
> > - driver support, which depends on drivers for several objects: DPNI,
> > - DPIO, DPMAC. Other pre-requisites include:
DPIO is a "full fleged user" of the bus. But, yes, it does provide
infrastructure services and so does not have a standalone I/O function.
> which to me indicates that DPIO is only part of that goal. Of course I'm
> the last person blocking progress to move the driver out of staging. But
> are we at the right point yet?
I thought the goal was to demonstrate a driver on top of the fsl-mc
bus driver because without that it would have been difficult to validate/review
that the bus infrastructure was correct.
The DPIO driver demonstrates full use of the bus driver infrastructure--
getting probed, discovering and mapping mmio regions, initializing the
device, initializing interrupts.
> To me the topmost important bit of having this outside of staging is
> actually missing in the TODO list (probably since it's obvious): Have
> stable, reliable, responsible maintainership for the code.
>
> So far I've seen German do the initial push upstream, then there was
> silence for a while. Now some time passed and you push a few bits here
> and there again. All of the efforts are great and very appreciated, but
> I'm missing the "maintainer" figure. Some peer to German and you who
> oversees the whole thing, reviews your patches and devotes at least 2-3
> days a week to only upstream fsl-mc work. Someone like York for U-Boot
> or Scott for general Linux work.
>
> Without that, there's too much of a chance that the code will stay
> incomplete, bitrot, etc. And that'd be bad for everyone involved. I
> think the concept behind fsl-mc is great and exactly what people need,
> so we should make sure it succeeds.
I agree we need that. We are actively working on getting an additional
maintainer (or two), and until we can get the right person(s) I'm willing
to fill that role. We're not going to let this code bitrot.
I actually think getting the bus driver out of staging will help spur
broader involvment by NXP engineers in the fsl-mc bus support. There
are enhancements like a resource management interface for user space,
an interface to see the MC log buffer, SMMU-related hooks for the fsl-mc
bus, and vfio for the fsl-mc bus. All that stuff is on hold until we
get the bus driver out of staging. The directive we have is to add no
new features until the bus driver is out.
For example, the ARM SMMU driver has an include of <linux/pci.h>,
but I don't see the SMMU maintainers accepting the following in
arm-smmu.c:
#include <../drivers/staging/fsl-mc/include/mc.h>
Given that the fsl-mc bus TODO list is done, there is not a whole lot
for a new maintainer to do to the bus driver itself until we get the
driver out of staging (aside from reviewing another DPAA2 object driver
that would also go into staging).
Once the bus driver + dpio is out staging it also opens up the door
for other DPAA2 drivers-- network, crypto, DMA, L2 switch,
decompression/compression, and others to be upstreamed. I didn't think
we wanted all of those to go into staging, but we were waiting until
some 1 driver was accepted first, proving the bus infrastructure is
sound. I was hoping DPI could be that proof of concept.
So, in short, I think getting the bus driver and DPIO out of staging
will open some parallel development and will also provide more
opportunities for some new maintainers to get involved, because there
will be more to review and do.
However, if you want things to stay in staging for now, I will resubmit
and put DPIO there.
Thanks,
Stuart
On 10/26/2016 04:35 AM, Stuart Yoder wrote:
>
>> -----Original Message-----
>> From: Alexander Graf [mailto:[email protected]]
>> Sent: Monday, October 24, 2016 9:34 AM
>> To: Stuart Yoder <[email protected]>; [email protected]
>> Cc: German Rivera <[email protected]>; [email protected]; [email protected];
>> [email protected]; Leo Li <[email protected]>
>> Subject: Re: [PATCH 0/9] staging: fsl-mc: move bus driver out of staging, add dpio
>>
>> Hi Stuart,
>>
>> On 10/21/2016 04:01 PM, Stuart Yoder wrote:
>>> This patch series: A) addresses the final item in the staging
>>> TODO list for the fsl-mc bus driver-- adding a functional driver
>>> on top of the bus driver, and B) requests that the fsl-mc bus driver
>>> be moved out of staging.
>> Awesome, it's great to see progress again! :)
>>
>>> The proposed destination for the bus driver is drivers/bus.
>>> Proposed location for global header files for fsl-mc and dpaa2
>>> is include/linux/fsl.
>>>
>>> The functional driver added is for the DPIO object which provides
>>> queuing services for other DPAA2 drivers. An overview of the
>> I thought the idea of the TODO item was to have a full-fledged user of
>> the bus, like a full network driver. The TODO item reads:
>>
>>> -* Add at least one device driver for a DPAA2 object (child device of the
>>> - fsl-mc bus). Most likely candidate for this is adding DPAA2 Ethernet
>>> - driver support, which depends on drivers for several objects: DPNI,
>>> - DPIO, DPMAC. Other pre-requisites include:
> DPIO is a "full fleged user" of the bus. But, yes, it does provide
> infrastructure services and so does not have a standalone I/O function.
>
>> which to me indicates that DPIO is only part of that goal. Of course I'm
>> the last person blocking progress to move the driver out of staging. But
>> are we at the right point yet?
> I thought the goal was to demonstrate a driver on top of the fsl-mc
> bus driver because without that it would have been difficult to validate/review
> that the bus infrastructure was correct.
>
> The DPIO driver demonstrates full use of the bus driver infrastructure--
> getting probed, discovering and mapping mmio regions, initializing the
> device, initializing interrupts.
>
>> To me the topmost important bit of having this outside of staging is
>> actually missing in the TODO list (probably since it's obvious): Have
>> stable, reliable, responsible maintainership for the code.
>>
>> So far I've seen German do the initial push upstream, then there was
>> silence for a while. Now some time passed and you push a few bits here
>> and there again. All of the efforts are great and very appreciated, but
>> I'm missing the "maintainer" figure. Some peer to German and you who
>> oversees the whole thing, reviews your patches and devotes at least 2-3
>> days a week to only upstream fsl-mc work. Someone like York for U-Boot
>> or Scott for general Linux work.
>>
>> Without that, there's too much of a chance that the code will stay
>> incomplete, bitrot, etc. And that'd be bad for everyone involved. I
>> think the concept behind fsl-mc is great and exactly what people need,
>> so we should make sure it succeeds.
> I agree we need that. We are actively working on getting an additional
> maintainer (or two), and until we can get the right person(s) I'm willing
> to fill that role. We're not going to let this code bitrot.
>
> I actually think getting the bus driver out of staging will help spur
> broader involvment by NXP engineers in the fsl-mc bus support. There
> are enhancements like a resource management interface for user space,
> an interface to see the MC log buffer, SMMU-related hooks for the fsl-mc
> bus, and vfio for the fsl-mc bus. All that stuff is on hold until we
> get the bus driver out of staging. The directive we have is to add no
> new features until the bus driver is out.
>
> For example, the ARM SMMU driver has an include of <linux/pci.h>,
> but I don't see the SMMU maintainers accepting the following in
> arm-smmu.c:
> #include <../drivers/staging/fsl-mc/include/mc.h>
>
> Given that the fsl-mc bus TODO list is done, there is not a whole lot
> for a new maintainer to do to the bus driver itself until we get the
> driver out of staging (aside from reviewing another DPAA2 object driver
> that would also go into staging).
>
> Once the bus driver + dpio is out staging it also opens up the door
> for other DPAA2 drivers-- network, crypto, DMA, L2 switch,
> decompression/compression, and others to be upstreamed. I didn't think
> we wanted all of those to go into staging, but we were waiting until
> some 1 driver was accepted first, proving the bus infrastructure is
> sound. I was hoping DPI could be that proof of concept.
>
> So, in short, I think getting the bus driver and DPIO out of staging
> will open some parallel development and will also provide more
> opportunities for some new maintainers to get involved, because there
> will be more to review and do.
>
> However, if you want things to stay in staging for now, I will resubmit
> and put DPIO there.
As long as Greg is ok with your approach, I'm fine moving it out of
staging too of course. And consider me eager to see the other drivers
pop up :).
Alex
> -----Original Message-----
> From: Stuart Yoder [mailto:[email protected]]
> Sent: Friday, October 21, 2016 5:02 PM
> To: [email protected]
> Cc: German Rivera <[email protected]>; [email protected];
> [email protected]; [email protected]; [email protected]; Leo Li
> <[email protected]>; Ruxandra Ioana Radulescu
> <[email protected]>; Roy Pledge <[email protected]>; Stuart
> Yoder <[email protected]>
> Subject: [PATCH 3/9] bus: fsl-mc: dpio: add APIs for DPIO objects
>
> From: Ioana Radulescu <[email protected]>
>
> Add the command build/parse APIs for operating on DPIO objects through
> the DPAA2 Management Complex.
>
> Signed-off-by: Ioana Radulescu <[email protected]>
> Signed-off-by: Roy Pledge <[email protected]>
> Signed-off-by: Stuart Yoder <[email protected]>
> ---
> drivers/bus/fsl-mc/Kconfig | 10 ++
> drivers/bus/fsl-mc/Makefile | 3 +
> drivers/bus/fsl-mc/dpio/Makefile | 9 ++
> drivers/bus/fsl-mc/dpio/dpio-cmd.h | 198
> ++++++++++++++++++++++++++++++++
> drivers/bus/fsl-mc/dpio/dpio.c | 229
> +++++++++++++++++++++++++++++++++++++
> drivers/bus/fsl-mc/dpio/dpio.h | 108 +++++++++++++++++
> 6 files changed, 557 insertions(+)
> create mode 100644 drivers/bus/fsl-mc/dpio/Makefile
> create mode 100644 drivers/bus/fsl-mc/dpio/dpio-cmd.h
> create mode 100644 drivers/bus/fsl-mc/dpio/dpio.c
> create mode 100644 drivers/bus/fsl-mc/dpio/dpio.h
>
> diff --git a/drivers/bus/fsl-mc/Kconfig b/drivers/bus/fsl-mc/Kconfig
> index 5c009ab..a10aaf0 100644
> --- a/drivers/bus/fsl-mc/Kconfig
> +++ b/drivers/bus/fsl-mc/Kconfig
> @@ -15,3 +15,13 @@ config FSL_MC_BUS
> architecture. The fsl-mc bus driver handles discovery of
> DPAA2 objects (which are represented as Linux devices) and
> binding objects to drivers.
> +
> +config FSL_MC_DPIO
> + tristate "QorIQ DPAA2 DPIO driver"
> + depends on FSL_MC_BUS
> + help
> + Driver for the DPAA2 DPIO object. A DPIO provides queue and
> + buffer management facilities for software to interact with
> + other DPAA2 objects. This driver does not expose the DPIO
> + objects individually, but groups them under a service layer
> + API.
> diff --git a/drivers/bus/fsl-mc/Makefile b/drivers/bus/fsl-mc/Makefile
> index d56afee..d18df72 100644
> --- a/drivers/bus/fsl-mc/Makefile
> +++ b/drivers/bus/fsl-mc/Makefile
> @@ -17,3 +17,6 @@ mc-bus-driver-objs := fsl-mc-bus.o \
> fsl-mc-msi.o \
> dpmcp.o \
> dpbp.o
> +
> +# MC DPIO driver
> +obj-$(CONFIG_FSL_MC_DPIO) += dpio/
> diff --git a/drivers/bus/fsl-mc/dpio/Makefile b/drivers/bus/fsl-
> mc/dpio/Makefile
> new file mode 100644
> index 0000000..128befc
> --- /dev/null
> +++ b/drivers/bus/fsl-mc/dpio/Makefile
> @@ -0,0 +1,9 @@
> +#
> +# QorIQ DPAA2 DPIO driver
> +#
> +
> +subdir-ccflags-y := -Werror
> +
> +obj-$(CONFIG_FSL_MC_DPIO) += fsl-mc-dpio.o
> +
> +fsl-mc-dpio-objs := dpio.o
> diff --git a/drivers/bus/fsl-mc/dpio/dpio-cmd.h b/drivers/bus/fsl-
> mc/dpio/dpio-cmd.h
> new file mode 100644
> index 0000000..b25a4cc
> --- /dev/null
> +++ b/drivers/bus/fsl-mc/dpio/dpio-cmd.h
> @@ -0,0 +1,198 @@
> +/*
> + * Copyright 2013-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:
> + * * Redistributions of source code must retain the above copyright
> + * notice, this list of conditions and the following disclaimer.
> + * * Redistributions in binary form must reproduce the above copyright
> + * notice, this list of conditions and the following disclaimer in the
> + * documentation and/or other materials provided with the distribution.
> + * * Neither the name of the above-listed copyright holders nor the
> + * names of any contributors may be used to endorse or promote products
> + * derived from this software without specific prior written permission.
> + *
> + * ALTERNATIVELY, this software may be distributed under the terms of the
> + * GNU General Public License ("GPL") as published by the Free Software
> + * Foundation, either version 2 of that License or (at your option) any
> + * later version.
> + *
> + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
> CONTRIBUTORS "AS IS"
> + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
> LIMITED TO, THE
> + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
> PARTICULAR PURPOSE
> + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR
> CONTRIBUTORS BE
> + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
> OR
> + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
> PROCUREMENT OF
> + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
> BUSINESS
> + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
> WHETHER IN
> + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
> OTHERWISE)
> + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
> ADVISED OF THE
> + * POSSIBILITY OF SUCH DAMAGE.
> + */
> +#ifndef _FSL_DPIO_CMD_H
> +#define _FSL_DPIO_CMD_H
> +
> +/* DPIO Version */
> +#define DPIO_VER_MAJOR 4
> +#define DPIO_VER_MINOR 2
> +
> +/* Command Versioning */
> +
> +#define DPIO_CMD_ID_OFFSET 4
> +#define DPIO_CMD_BASE_VERSION 1
> +
> +#define DPIO_CMD(id) ((id << DPIO_CMD_ID_OFFSET) |
> DPIO_CMD_BASE_VERSION)
> +
> +/* Command IDs */
> +#define DPIO_CMDID_CLOSE DPIO_CMD(0x800)
> +#define DPIO_CMDID_OPEN
> DPIO_CMD(0x803)
> +#define DPIO_CMDID_CREATE
> DPIO_CMD(0x903)
> +#define DPIO_CMDID_DESTROY
> DPIO_CMD(0x983)
> +#define DPIO_CMDID_GET_API_VERSION
> DPIO_CMD(0xa03)
> +
> +#define DPIO_CMDID_ENABLE
> DPIO_CMD(0x002)
> +#define DPIO_CMDID_DISABLE
> DPIO_CMD(0x003)
> +#define DPIO_CMDID_GET_ATTR
> DPIO_CMD(0x004)
> +#define DPIO_CMDID_RESET DPIO_CMD(0x005)
> +#define DPIO_CMDID_IS_ENABLED
> DPIO_CMD(0x006)
> +
> +#define DPIO_CMDID_SET_IRQ
> DPIO_CMD(0x010)
> +#define DPIO_CMDID_GET_IRQ
> DPIO_CMD(0x011)
> +#define DPIO_CMDID_SET_IRQ_ENABLE
> DPIO_CMD(0x012)
> +#define DPIO_CMDID_GET_IRQ_ENABLE
> DPIO_CMD(0x013)
> +#define DPIO_CMDID_SET_IRQ_MASK
> DPIO_CMD(0x014)
> +#define DPIO_CMDID_GET_IRQ_MASK
> DPIO_CMD(0x015)
> +#define DPIO_CMDID_GET_IRQ_STATUS
> DPIO_CMD(0x016)
> +#define DPIO_CMDID_CLEAR_IRQ_STATUS
> DPIO_CMD(0x017)
> +
> +#define DPIO_CMDID_SET_STASHING_DEST
> DPIO_CMD(0x120)
> +#define DPIO_CMDID_GET_STASHING_DEST
> DPIO_CMD(0x121)
> +#define DPIO_CMDID_ADD_STATIC_DEQUEUE_CHANNEL
> DPIO_CMD(0x122)
> +#define DPIO_CMDID_REMOVE_STATIC_DEQUEUE_CHANNEL
> DPIO_CMD(0x123)
> +
> +struct dpio_cmd_open {
> + __le32 dpio_id;
> +};
> +
> +#define DPIO_CHANNEL_MODE_MASK 0x3
> +
> +struct dpio_cmd_create {
> + __le16 pad0;
> + u8 channel_mode;
> + u8 pad1;
> + u8 num_priorities;
> +
> +};
> +
> +#define DPIO_ENABLE 1
> +
> +struct dpio_rsp_is_enabled {
> + u8 enabled;
> +};
> +
> +struct dpio_cmd_set_irq {
> + /* cmd word 0 */
> + u8 irq_index;
> + u8 pad[3];
> + __le32 irq_val;
> + /* cmd word 1 */
> + __le64 irq_addr;
> + /* cmd word 2 */
> + __le32 irq_num;
> +};
> +
> +struct dpio_cmd_get_irq {
> + __le32 pad;
> + u8 irq_index;
> +};
> +
> +struct dpio_rsp_get_irq {
> + /* response word 0 */
> + __le32 irq_val;
> + __le32 pad;
> + /* response word 1 */
> + __le64 irq_addr;
> + /* response word 2 */
> + __le32 irq_num;
> + __le32 type;
> +};
> +
> +struct dpio_cmd_set_irq_enable {
> + u8 enable;
> + u8 pad[3];
> + u8 irq_index;
> +};
> +
> +struct dpio_cmd_get_irq_enable {
> + __le32 pad;
> + u8 irq_index;
> +};
> +
> +struct dpio_rsp_get_irq_enable {
> + u8 enabled;
> +};
> +
> +struct dpio_cmd_set_irq_mask {
> + __le32 mask;
> + u8 irq_index;
> +};
> +
> +struct dpio_cmd_get_irq_mask {
> + __le32 pad;
> + u8 irq_index;
> +};
> +
> +struct dpio_rsp_get_irq_mask {
> + __le32 mask;
> +};
> +
> +struct dpio_cmd_get_irq_status {
> + __le32 status;
> + u8 irq_index;
> +};
> +
> +struct dpio_rsp_get_irq_status {
> + __le32 status;
> +};
> +
> +struct dpio_cmd_clear_irq_status {
> + __le32 status;
> + u8 irq_index;
> +};
> +
> +struct dpio_rsp_get_attr {
> + /* cmd word 0 */
> + __le32 id;
> + __le16 qbman_portal_id;
> + u8 num_priorities;
> + u8 channel_mode;
> + /* cmd word 1 */
> + __le64 qbman_portal_ce_addr;
> + /* cmd word 2 */
> + __le64 qbman_portal_ci_addr;
> + /* cmd word 3 */
> + __le32 pad;
> + __le32 qbman_version;
> +};
> +
> +struct dpio_cmd_set_stashing_dest {
> + u8 sdest;
> +};
> +
> +struct dpio_rsp_get_stashing_dest {
> + u8 sdest;
> +};
> +
> +struct dpio_cmd_add_static_dequeue_channel {
> + __le32 dpcon_id;
> +};
> +
> +struct dpio_rsp_add_static_dequeue_channel {
> + u8 channel_index;
> +};
> +
> +struct dpio_cmd_remove_static_dequeue_channel {
> + __le32 dpcon_id;
> +};
Hi Stuart, looks like you removed unused API functions from dpio.h
and dpio.c, but not the structures and CMDID defines associated with
them, which are now dead code.
Thanks,
Ioana
> -----Original Message-----
> From: Stuart Yoder [mailto:[email protected]]
> Sent: Friday, October 21, 2016 9:02 AM
> To: [email protected]
> Cc: German Rivera <[email protected]>; [email protected];
> [email protected]; [email protected]; [email protected]; Leo Li
> <[email protected]>; Roy Pledge <[email protected]>; Stuart Yoder
> <[email protected]>
> Subject: [PATCH 4/9] bus: fsl-mc: dpio: add frame descriptor and
> scatter/gather APIs
>
> From: Roy Pledge <[email protected]>
>
> Add global definitions for DPAA2 frame descriptors and scatter
> gather entries.
>
> Signed-off-by: Roy Pledge <[email protected]>
> Signed-off-by: Stuart Yoder <[email protected]>
> ---
> include/linux/fsl/dpaa2-fd.h | 415
> +++++++++++++++++++++++++++++++++++++++++++
> 1 file changed, 415 insertions(+)
> create mode 100644 include/linux/fsl/dpaa2-fd.h
>
> diff --git a/include/linux/fsl/dpaa2-fd.h b/include/linux/fsl/dpaa2-fd.h
> new file mode 100644
> index 0000000..b3fa9ff
> --- /dev/null
> +++ b/include/linux/fsl/dpaa2-fd.h
> @@ -0,0 +1,415 @@
> +/*
> + * Copyright 2014-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:
> + * * Redistributions of source code must retain the above copyright
> + * notice, this list of conditions and the following disclaimer.
> + * * Redistributions in binary form must reproduce the above copyright
> + * notice, this list of conditions and the following disclaimer in the
> + * documentation and/or other materials provided with the distribution.
> + * * Neither the name of Freescale Semiconductor nor the
> + * names of its contributors may be used to endorse or promote
> products
> + * derived from this software without specific prior written permission.
> + *
> + * ALTERNATIVELY, this software may be distributed under the terms of the
> + * GNU General Public License ("GPL") as published by the Free Software
> + * Foundation, either version 2 of that License or (at your option) any
> + * later version.
> + *
> + * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND
> ANY
> + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
> THE IMPLIED
> + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
> PURPOSE ARE
> + * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR
> ANY
> + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
> CONSEQUENTIAL DAMAGES
> + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
> GOODS OR SERVICES;
> + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
> HOWEVER CAUSED AND
> + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
> OR TORT
> + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
> THE USE OF THIS
> + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
> + */
> +#ifndef __FSL_DPAA2_FD_H
> +#define __FSL_DPAA2_FD_H
> +
> +#include <linux/kernel.h>
> +
> +/**
> + * DOC: DPAA2 FD - Frame Descriptor APIs for DPAA2
> + *
> + * Frame Descriptors (FDs) are used to describe frame data in the DPAA2.
> + * Frames can be enqueued and dequeued to Frame Queues (FQs) which
> are consumed
> + * by the various DPAA accelerators (WRIOP, SEC, PME, DCE)
> + *
> + * There are three types of frames: single, scatter gather, and frame lists.
> + *
> + * The set of APIs in this file must be used to create, manipulate and
> + * query Frame Descriptors.
> + */
> +
> +/**
> + * struct dpaa2_fd - Struct describing FDs
> + * @words: for easier/faster copying the whole FD structure
> + * @addr: address in the FD
> + * @len: length in the FD
> + * @bpid: buffer pool ID
> + * @format_offset: format and offset fields
> + * @frc: frame context
> + * @ctrl: control bits...including dd, sc, va, err, etc
> + * @flc: flow context address
> + *
> + * This structure represents the basic Frame Descriptor used in the system.
> + */
> +struct dpaa2_fd {
> + union {
> + u32 words[8];
> + struct dpaa2_fd_simple {
> + __le64 addr;
> + __le32 len;
> + __le16 bpid;
> + __le16 format_offset;
> + __le32 frc;
> + __le32 ctrl;
> + __le64 flc;
> + } simple;
> + };
> +};
> +
> +#define FD_OFFSET_MASK 0x0FFF
> +#define FD_FORMAT_MASK 0x3
> +#define FD_FORMAT_SHIFT 12
> +#define SG_SHORT_LEN_FLAG_MASK 0x1
> +#define SG_SHORT_LEN_FLAG_SHIFT 14
> +#define SG_SHORT_LEN_MASK 0x1FFFF
> +#define SG_OFFSET_MASK 0x0FFF
> +#define SG_FORMAT_MASK 0x3
> +#define SG_FORMAT_SHIFT 12
> +#define SG_BPID_MASK 0x3FFF
> +#define SG_FINAL_FLAG_MASK 0x1
> +#define SG_FINAL_FLAG_SHIFT 15
> +
> +enum dpaa2_fd_format {
> + dpaa2_fd_single = 0,
> + dpaa2_fd_list,
> + dpaa2_fd_sg
> +};
> +
> +/**
> + * dpaa2_fd_get_addr() - get the addr field of frame descriptor
> + * @fd: the given frame descriptor
> + *
> + * Return the address in the frame descriptor.
> + */
> +static inline dma_addr_t dpaa2_fd_get_addr(const struct dpaa2_fd *fd)
> +{
> +
> + return (dma_addr_t)fd->simple.addr;
> +}
> +
> +/**
> + * dpaa2_fd_set_addr() - Set the addr field of frame descriptor
> + * @fd: the given frame descriptor
> + * @addr: the address needs to be set in frame descriptor
> + */
> +static inline void dpaa2_fd_set_addr(struct dpaa2_fd *fd, dma_addr_t
> addr)
> +{
> + fd->simple.addr = addr;
> +}
> +
> +/**
> + * dpaa2_fd_get_frc() - Get the frame context in the frame descriptor
> + * @fd: the given frame descriptor
> + *
> + * Return the frame context field in the frame descriptor.
> + */
> +static inline u32 dpaa2_fd_get_frc(const struct dpaa2_fd *fd)
> +{
> + return fd->simple.frc;
> +}
> +
> +/**
> + * dpaa2_fd_set_frc() - Set the frame context in the frame descriptor
> + * @fd: the given frame descriptor
> + * @frc: the frame context needs to be set in frame descriptor
> + */
> +static inline void dpaa2_fd_set_frc(struct dpaa2_fd *fd, u32 frc)
> +{
> + fd->simple.frc = frc;
> +}
> +
> +/**
> + * dpaa2_fd_get_flc() - Get the flow context in the frame descriptor
> + * @fd: the given frame descriptor
> + *
> + * Return the flow context in the frame descriptor.
> + */
> +static inline dma_addr_t dpaa2_fd_get_flc(const struct dpaa2_fd *fd)
> +{
> + return (dma_addr_t)fd->simple.flc;
> +}
> +
> +/**
> + * dpaa2_fd_set_flc() - Set the flow context field of frame descriptor
> + * @fd: the given frame descriptor
> + * @flc_addr: the flow context needs to be set in frame descriptor
> + */
> +static inline void dpaa2_fd_set_flc(struct dpaa2_fd *fd, dma_addr_t
> flc_addr)
> +{
> + fd->simple.flc = flc_addr;
> +}
> +
> +/**
> + * dpaa2_fd_get_len() - Get the length in the frame descriptor
> + * @fd: the given frame descriptor
> + *
> + * Return the length field in the frame descriptor.
> + */
> +static inline u32 dpaa2_fd_get_len(const struct dpaa2_fd *fd)
> +{
> + return fd->simple.len;
> +}
> +
> +/**
> + * dpaa2_fd_set_len() - Set the length field of frame descriptor
> + * @fd: the given frame descriptor
> + * @len: the length needs to be set in frame descriptor
> + */
> +static inline void dpaa2_fd_set_len(struct dpaa2_fd *fd, u32 len)
> +{
> + fd->simple.len = len;
> +}
> +
> +/**
> + * dpaa2_fd_get_offset() - Get the offset field in the frame descriptor
> + * @fd: the given frame descriptor
> + *
> + * Return the offset.
> + */
> +static inline uint16_t dpaa2_fd_get_offset(const struct dpaa2_fd *fd)
> +{
> + return fd->simple.format_offset & FD_OFFSET_MASK;
> +}
> +
> +/**
> + * dpaa2_fd_set_offset() - Set the offset field of frame descriptor
> + * @fd: the given frame descriptor
> + * @offset: the offset needs to be set in frame descriptor
> + */
> +static inline void dpaa2_fd_set_offset(struct dpaa2_fd *fd, uint16_t offset)
> +{
> + fd->simple.format_offset &= ~(FD_OFFSET_MASK);
> + fd->simple.format_offset |= offset;
> +}
> +
> +/**
> + * dpaa2_fd_get_format() - Get the format field in the frame descriptor
> + * @fd: the given frame descriptor
> + *
> + * Return the format.
> + */
> +static inline enum dpaa2_fd_format dpaa2_fd_get_format(
> + const struct dpaa2_fd *fd)
> +{
> + return (enum dpaa2_fd_format)((fd->simple.format_offset
> + >> FD_FORMAT_SHIFT) &
> FD_FORMAT_MASK);
> +}
> +
> +/**
> + * dpaa2_fd_set_format() - Set the format field of frame descriptor
> + * @fd: the given frame descriptor
> + * @format: the format needs to be set in frame descriptor
> + */
> +static inline void dpaa2_fd_set_format(struct dpaa2_fd *fd,
> + enum dpaa2_fd_format format)
> +{
> + fd->simple.format_offset &= ~(FD_FORMAT_MASK <<
> FD_FORMAT_SHIFT);
> + fd->simple.format_offset |= format << FD_FORMAT_SHIFT;
> +}
> +
> +/**
> + * dpaa2_fd_get_bpid() - Get the bpid field in the frame descriptor
> + * @fd: the given frame descriptor
> + *
> + * Return the buffer pool id.
> + */
> +static inline uint16_t dpaa2_fd_get_bpid(const struct dpaa2_fd *fd)
> +{
> + return fd->simple.bpid;
> +}
> +
> +/**
> + * dpaa2_fd_set_bpid() - Set the bpid field of frame descriptor
> + * @fd: the given frame descriptor
> + * @bpid: buffer pool id to be set
> + */
> +static inline void dpaa2_fd_set_bpid(struct dpaa2_fd *fd, uint16_t bpid)
> +{
> + fd->simple.bpid = bpid;
> +}
The setter/getter functions for fd.ctrl are missing.
> +
> +/**
> + * struct dpaa2_sg_entry - the scatter-gathering structure
> + * @addr: address of the sg entry
> + * @len: length in this sg entry
> + * @bpid: buffer pool id
> + * @format_offset: offset in the MS 16 bits, BPID in the LS 16 bits
Description of the format_offset field is incorrect, it shouldn't
contain the reference to BPID.
> + */
> +struct dpaa2_sg_entry {
> + __le64 addr;
> + __le32 len;
> + __le16 bpid;
> + __le16 format_offset;
> +};
> +
> +enum dpaa2_sg_format {
> + dpaa2_sg_single = 0,
> + dpaa2_sg_frame_data,
> + dpaa2_sg_sgt_ext
> +};
> +
> +/* Accessors for SG entry fields */
> +
> +/**
> + * dpaa2_sg_get_addr() - Get the address from SG entry
> + * @sg: the given scatter-gathering object
> + *
> + * Return the address.
> + */
> +static inline dma_addr_t dpaa2_sg_get_addr(const struct dpaa2_sg_entry
> *sg)
> +{
> + return le64_to_cpu((dma_addr_t)sg->addr);
> +}
> +
> +/**
> + * dpaa2_sg_set_addr() - Set the address in SG entry
> + * @sg: the given scatter-gathering object
> + * @addr: the address to be set
> + */
> +static inline void dpaa2_sg_set_addr(struct dpaa2_sg_entry *sg,
> dma_addr_t addr)
> +{
> + sg->addr = cpu_to_le64(addr);
> +}
> +
> +static inline bool dpaa2_sg_short_len(const struct dpaa2_sg_entry *sg)
> +{
> + return (le16_to_cpu(sg->format_offset) >>
> SG_SHORT_LEN_FLAG_SHIFT)
> + & SG_SHORT_LEN_FLAG_MASK;
> +}
> +
> +/**
> + * dpaa2_sg_get_len() - Get the length in SG entry
> + * @sg: the given scatter-gathering object
> + *
> + * Return the length.
> + */
> +static inline u32 dpaa2_sg_get_len(const struct dpaa2_sg_entry *sg)
> +{
> + if (dpaa2_sg_short_len(sg))
> + return le32_to_cpu(sg->len) & SG_SHORT_LEN_MASK;
> +
> + return le32_to_cpu(sg->len);
> +}
We should do this in dpaa2_fd_get_len() as well. Hardware is capable of
generating FDs with SL bit set for single frame format too, although in
practice I've never actually seen it.
Thanks,
Ioana
> -----Original Message-----
> From: Ruxandra Ioana Radulescu
> Sent: Wednesday, November 02, 2016 9:50 AM
> To: Stuart Yoder <[email protected]>; [email protected]
> Cc: German Rivera <[email protected]>; [email protected]; [email protected];
> [email protected]; [email protected]; Leo Li <[email protected]>; Roy Pledge <[email protected]>; Stuart Yoder
> <[email protected]>
> Subject: RE: [PATCH 3/9] bus: fsl-mc: dpio: add APIs for DPIO objects
>
> > -----Original Message-----
> > From: Stuart Yoder [mailto:[email protected]]
> > Sent: Friday, October 21, 2016 5:02 PM
> > To: [email protected]
> > Cc: German Rivera <[email protected]>; [email protected];
> > [email protected]; [email protected]; [email protected]; Leo Li
> > <[email protected]>; Ruxandra Ioana Radulescu
> > <[email protected]>; Roy Pledge <[email protected]>; Stuart
> > Yoder <[email protected]>
> > Subject: [PATCH 3/9] bus: fsl-mc: dpio: add APIs for DPIO objects
> >
> > From: Ioana Radulescu <[email protected]>
> >
> > Add the command build/parse APIs for operating on DPIO objects through
> > the DPAA2 Management Complex.
> >
> > Signed-off-by: Ioana Radulescu <[email protected]>
> > Signed-off-by: Roy Pledge <[email protected]>
> > Signed-off-by: Stuart Yoder <[email protected]>
> > ---
> > drivers/bus/fsl-mc/Kconfig | 10 ++
> > drivers/bus/fsl-mc/Makefile | 3 +
> > drivers/bus/fsl-mc/dpio/Makefile | 9 ++
> > drivers/bus/fsl-mc/dpio/dpio-cmd.h | 198
> > ++++++++++++++++++++++++++++++++
> > drivers/bus/fsl-mc/dpio/dpio.c | 229
> > +++++++++++++++++++++++++++++++++++++
> > drivers/bus/fsl-mc/dpio/dpio.h | 108 +++++++++++++++++
> > 6 files changed, 557 insertions(+)
> > create mode 100644 drivers/bus/fsl-mc/dpio/Makefile
> > create mode 100644 drivers/bus/fsl-mc/dpio/dpio-cmd.h
> > create mode 100644 drivers/bus/fsl-mc/dpio/dpio.c
> > create mode 100644 drivers/bus/fsl-mc/dpio/dpio.h
> >
> > diff --git a/drivers/bus/fsl-mc/Kconfig b/drivers/bus/fsl-mc/Kconfig
> > index 5c009ab..a10aaf0 100644
> > --- a/drivers/bus/fsl-mc/Kconfig
> > +++ b/drivers/bus/fsl-mc/Kconfig
> > @@ -15,3 +15,13 @@ config FSL_MC_BUS
> > architecture. The fsl-mc bus driver handles discovery of
> > DPAA2 objects (which are represented as Linux devices) and
> > binding objects to drivers.
> > +
> > +config FSL_MC_DPIO
> > + tristate "QorIQ DPAA2 DPIO driver"
> > + depends on FSL_MC_BUS
> > + help
> > + Driver for the DPAA2 DPIO object. A DPIO provides queue and
> > + buffer management facilities for software to interact with
> > + other DPAA2 objects. This driver does not expose the DPIO
> > + objects individually, but groups them under a service layer
> > + API.
> > diff --git a/drivers/bus/fsl-mc/Makefile b/drivers/bus/fsl-mc/Makefile
> > index d56afee..d18df72 100644
> > --- a/drivers/bus/fsl-mc/Makefile
> > +++ b/drivers/bus/fsl-mc/Makefile
> > @@ -17,3 +17,6 @@ mc-bus-driver-objs := fsl-mc-bus.o \
> > fsl-mc-msi.o \
> > dpmcp.o \
> > dpbp.o
> > +
> > +# MC DPIO driver
> > +obj-$(CONFIG_FSL_MC_DPIO) += dpio/
> > diff --git a/drivers/bus/fsl-mc/dpio/Makefile b/drivers/bus/fsl-
> > mc/dpio/Makefile
> > new file mode 100644
> > index 0000000..128befc
> > --- /dev/null
> > +++ b/drivers/bus/fsl-mc/dpio/Makefile
> > @@ -0,0 +1,9 @@
> > +#
> > +# QorIQ DPAA2 DPIO driver
> > +#
> > +
> > +subdir-ccflags-y := -Werror
> > +
> > +obj-$(CONFIG_FSL_MC_DPIO) += fsl-mc-dpio.o
> > +
> > +fsl-mc-dpio-objs := dpio.o
> > diff --git a/drivers/bus/fsl-mc/dpio/dpio-cmd.h b/drivers/bus/fsl-
> > mc/dpio/dpio-cmd.h
> > new file mode 100644
> > index 0000000..b25a4cc
> > --- /dev/null
> > +++ b/drivers/bus/fsl-mc/dpio/dpio-cmd.h
> > @@ -0,0 +1,198 @@
> > +/*
> > + * Copyright 2013-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:
> > + * * Redistributions of source code must retain the above copyright
> > + * notice, this list of conditions and the following disclaimer.
> > + * * Redistributions in binary form must reproduce the above copyright
> > + * notice, this list of conditions and the following disclaimer in the
> > + * documentation and/or other materials provided with the distribution.
> > + * * Neither the name of the above-listed copyright holders nor the
> > + * names of any contributors may be used to endorse or promote products
> > + * derived from this software without specific prior written permission.
> > + *
> > + * ALTERNATIVELY, this software may be distributed under the terms of the
> > + * GNU General Public License ("GPL") as published by the Free Software
> > + * Foundation, either version 2 of that License or (at your option) any
> > + * later version.
> > + *
> > + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
> > CONTRIBUTORS "AS IS"
> > + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
> > LIMITED TO, THE
> > + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
> > PARTICULAR PURPOSE
> > + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR
> > CONTRIBUTORS BE
> > + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
> > OR
> > + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
> > PROCUREMENT OF
> > + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
> > BUSINESS
> > + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
> > WHETHER IN
> > + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
> > OTHERWISE)
> > + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
> > ADVISED OF THE
> > + * POSSIBILITY OF SUCH DAMAGE.
> > + */
> > +#ifndef _FSL_DPIO_CMD_H
> > +#define _FSL_DPIO_CMD_H
> > +
> > +/* DPIO Version */
> > +#define DPIO_VER_MAJOR 4
> > +#define DPIO_VER_MINOR 2
> > +
> > +/* Command Versioning */
> > +
> > +#define DPIO_CMD_ID_OFFSET 4
> > +#define DPIO_CMD_BASE_VERSION 1
> > +
> > +#define DPIO_CMD(id) ((id << DPIO_CMD_ID_OFFSET) |
> > DPIO_CMD_BASE_VERSION)
> > +
> > +/* Command IDs */
> > +#define DPIO_CMDID_CLOSE DPIO_CMD(0x800)
> > +#define DPIO_CMDID_OPEN
> > DPIO_CMD(0x803)
> > +#define DPIO_CMDID_CREATE
> > DPIO_CMD(0x903)
> > +#define DPIO_CMDID_DESTROY
> > DPIO_CMD(0x983)
> > +#define DPIO_CMDID_GET_API_VERSION
> > DPIO_CMD(0xa03)
> > +
> > +#define DPIO_CMDID_ENABLE
> > DPIO_CMD(0x002)
> > +#define DPIO_CMDID_DISABLE
> > DPIO_CMD(0x003)
> > +#define DPIO_CMDID_GET_ATTR
> > DPIO_CMD(0x004)
> > +#define DPIO_CMDID_RESET DPIO_CMD(0x005)
> > +#define DPIO_CMDID_IS_ENABLED
> > DPIO_CMD(0x006)
> > +
> > +#define DPIO_CMDID_SET_IRQ
> > DPIO_CMD(0x010)
> > +#define DPIO_CMDID_GET_IRQ
> > DPIO_CMD(0x011)
> > +#define DPIO_CMDID_SET_IRQ_ENABLE
> > DPIO_CMD(0x012)
> > +#define DPIO_CMDID_GET_IRQ_ENABLE
> > DPIO_CMD(0x013)
> > +#define DPIO_CMDID_SET_IRQ_MASK
> > DPIO_CMD(0x014)
> > +#define DPIO_CMDID_GET_IRQ_MASK
> > DPIO_CMD(0x015)
> > +#define DPIO_CMDID_GET_IRQ_STATUS
> > DPIO_CMD(0x016)
> > +#define DPIO_CMDID_CLEAR_IRQ_STATUS
> > DPIO_CMD(0x017)
> > +
> > +#define DPIO_CMDID_SET_STASHING_DEST
> > DPIO_CMD(0x120)
> > +#define DPIO_CMDID_GET_STASHING_DEST
> > DPIO_CMD(0x121)
> > +#define DPIO_CMDID_ADD_STATIC_DEQUEUE_CHANNEL
> > DPIO_CMD(0x122)
> > +#define DPIO_CMDID_REMOVE_STATIC_DEQUEUE_CHANNEL
> > DPIO_CMD(0x123)
> > +
> > +struct dpio_cmd_open {
> > + __le32 dpio_id;
> > +};
> > +
> > +#define DPIO_CHANNEL_MODE_MASK 0x3
> > +
> > +struct dpio_cmd_create {
> > + __le16 pad0;
> > + u8 channel_mode;
> > + u8 pad1;
> > + u8 num_priorities;
> > +
> > +};
> > +
> > +#define DPIO_ENABLE 1
> > +
> > +struct dpio_rsp_is_enabled {
> > + u8 enabled;
> > +};
> > +
> > +struct dpio_cmd_set_irq {
> > + /* cmd word 0 */
> > + u8 irq_index;
> > + u8 pad[3];
> > + __le32 irq_val;
> > + /* cmd word 1 */
> > + __le64 irq_addr;
> > + /* cmd word 2 */
> > + __le32 irq_num;
> > +};
> > +
> > +struct dpio_cmd_get_irq {
> > + __le32 pad;
> > + u8 irq_index;
> > +};
> > +
> > +struct dpio_rsp_get_irq {
> > + /* response word 0 */
> > + __le32 irq_val;
> > + __le32 pad;
> > + /* response word 1 */
> > + __le64 irq_addr;
> > + /* response word 2 */
> > + __le32 irq_num;
> > + __le32 type;
> > +};
> > +
> > +struct dpio_cmd_set_irq_enable {
> > + u8 enable;
> > + u8 pad[3];
> > + u8 irq_index;
> > +};
> > +
> > +struct dpio_cmd_get_irq_enable {
> > + __le32 pad;
> > + u8 irq_index;
> > +};
> > +
> > +struct dpio_rsp_get_irq_enable {
> > + u8 enabled;
> > +};
> > +
> > +struct dpio_cmd_set_irq_mask {
> > + __le32 mask;
> > + u8 irq_index;
> > +};
> > +
> > +struct dpio_cmd_get_irq_mask {
> > + __le32 pad;
> > + u8 irq_index;
> > +};
> > +
> > +struct dpio_rsp_get_irq_mask {
> > + __le32 mask;
> > +};
> > +
> > +struct dpio_cmd_get_irq_status {
> > + __le32 status;
> > + u8 irq_index;
> > +};
> > +
> > +struct dpio_rsp_get_irq_status {
> > + __le32 status;
> > +};
> > +
> > +struct dpio_cmd_clear_irq_status {
> > + __le32 status;
> > + u8 irq_index;
> > +};
> > +
> > +struct dpio_rsp_get_attr {
> > + /* cmd word 0 */
> > + __le32 id;
> > + __le16 qbman_portal_id;
> > + u8 num_priorities;
> > + u8 channel_mode;
> > + /* cmd word 1 */
> > + __le64 qbman_portal_ce_addr;
> > + /* cmd word 2 */
> > + __le64 qbman_portal_ci_addr;
> > + /* cmd word 3 */
> > + __le32 pad;
> > + __le32 qbman_version;
> > +};
> > +
> > +struct dpio_cmd_set_stashing_dest {
> > + u8 sdest;
> > +};
> > +
> > +struct dpio_rsp_get_stashing_dest {
> > + u8 sdest;
> > +};
> > +
> > +struct dpio_cmd_add_static_dequeue_channel {
> > + __le32 dpcon_id;
> > +};
> > +
> > +struct dpio_rsp_add_static_dequeue_channel {
> > + u8 channel_index;
> > +};
> > +
> > +struct dpio_cmd_remove_static_dequeue_channel {
> > + __le32 dpcon_id;
> > +};
>
> Hi Stuart, looks like you removed unused API functions from dpio.h
> and dpio.c, but not the structures and CMDID defines associated with
> them, which are now dead code.
I didn't modify this particular file when I sent it out, but agree that
we should clean that up. Will remove unused structs/defines
in v2 of this series.
Thanks,
Stuart
> +/**
> > + * dpaa2_fd_set_bpid() - Set the bpid field of frame descriptor
> > + * @fd: the given frame descriptor
> > + * @bpid: buffer pool id to be set
> > + */
> > +static inline void dpaa2_fd_set_bpid(struct dpaa2_fd *fd, uint16_t bpid)
> > +{
> > + fd->simple.bpid = bpid;
> > +}
>
> The setter/getter functions for fd.ctrl are missing.
Ok, will add those. Does the ethernet driver use that field?
> > +
> > +/**
> > + * struct dpaa2_sg_entry - the scatter-gathering structure
> > + * @addr: address of the sg entry
> > + * @len: length in this sg entry
> > + * @bpid: buffer pool id
> > + * @format_offset: offset in the MS 16 bits, BPID in the LS 16 bits
>
> Description of the format_offset field is incorrect, it shouldn't
> contain the reference to BPID.
Thanks, will fix.
> > +/**
> > + * dpaa2_sg_get_len() - Get the length in SG entry
> > + * @sg: the given scatter-gathering object
> > + *
> > + * Return the length.
> > + */
> > +static inline u32 dpaa2_sg_get_len(const struct dpaa2_sg_entry *sg)
> > +{
> > + if (dpaa2_sg_short_len(sg))
> > + return le32_to_cpu(sg->len) & SG_SHORT_LEN_MASK;
> > +
> > + return le32_to_cpu(sg->len);
> > +}
>
> We should do this in dpaa2_fd_get_len() as well. Hardware is capable of
> generating FDs with SL bit set for single frame format too, although in
> practice I've never actually seen it.
Any suggestion on how to test this case?
Thanks,
Stuart
> -----Original Message-----
> From: Stuart Yoder [mailto:[email protected]]
> Sent: Friday, October 21, 2016 9:02 AM
> To: [email protected]
> Cc: German Rivera <[email protected]>; [email protected];
> [email protected]; [email protected]; [email protected]; Leo Li
> <[email protected]>; Roy Pledge <[email protected]>; Roy Pledge
> <[email protected]>; Haiying Wang <[email protected]>; Stuart
> Yoder <[email protected]>
> Subject: [PATCH 7/9] bus: fsl-mc: dpio: add the DPAA2 DPIO service interface
>
> From: Roy Pledge <[email protected]>
>
> The DPIO service interface handles initialization of DPIO objects
> and exports APIs to be used by other DPAA2 object drivers to perform
> queuing and buffer management related operations. The service allows
> registration of callbacks when frames or notifications are received.
>
> Signed-off-by: Roy Pledge <[email protected]>
> Signed-off-by: Haiying Wang <[email protected]>
> Signed-off-by: Stuart Yoder <[email protected]>
> ---
> drivers/bus/fsl-mc/dpio/Makefile | 2 +-
> drivers/bus/fsl-mc/dpio/dpio-service.c | 614
> +++++++++++++++++++++++++++++++++
> include/linux/fsl/dpaa2-io.h | 138 ++++++++
> 3 files changed, 753 insertions(+), 1 deletion(-)
> create mode 100644 drivers/bus/fsl-mc/dpio/dpio-service.c
> create mode 100644 include/linux/fsl/dpaa2-io.h
>
> diff --git a/drivers/bus/fsl-mc/dpio/Makefile b/drivers/bus/fsl-
> mc/dpio/Makefile
> index 6588498..0778da7 100644
> --- a/drivers/bus/fsl-mc/dpio/Makefile
> +++ b/drivers/bus/fsl-mc/dpio/Makefile
> @@ -6,4 +6,4 @@ subdir-ccflags-y := -Werror
>
> obj-$(CONFIG_FSL_MC_DPIO) += fsl-mc-dpio.o
>
> -fsl-mc-dpio-objs := dpio.o qbman-portal.o
> +fsl-mc-dpio-objs := dpio.o qbman-portal.o dpio-service.o
> diff --git a/drivers/bus/fsl-mc/dpio/dpio-service.c b/drivers/bus/fsl-
> mc/dpio/dpio-service.c
> new file mode 100644
> index 0000000..7a455a7
> --- /dev/null
> +++ b/drivers/bus/fsl-mc/dpio/dpio-service.c
> @@ -0,0 +1,614 @@
> +/*
> + * Copyright 2014-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:
> + * * Redistributions of source code must retain the above copyright
> + * notice, this list of conditions and the following disclaimer.
> + * * Redistributions in binary form must reproduce the above copyright
> + * notice, this list of conditions and the following disclaimer in the
> + * documentation and/or other materials provided with the
> distribution.
> + * * Neither the name of Freescale Semiconductor nor the
> + * names of its contributors may be used to endorse or promote
> products
> + * derived from this software without specific prior written permission.
> + *
> + *
> + * ALTERNATIVELY, this software may be distributed under the terms of the
> + * GNU General Public License ("GPL") as published by the Free Software
> + * Foundation, either version 2 of that License or (at your option) any
> + * later version.
> + *
> + * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND
> ANY
> + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
> THE IMPLIED
> + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
> PURPOSE ARE
> + * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR
> ANY
> + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
> CONSEQUENTIAL DAMAGES
> + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
> GOODS OR SERVICES;
> + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
> HOWEVER CAUSED AND
> + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
> OR TORT
> + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
> THE USE OF THIS
> + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
> + */
> +#include <linux/types.h>
> +#include <linux/fsl/mc.h>
> +#include <linux/fsl/dpaa2-io.h>
> +#include <linux/init.h>
> +#include <linux/module.h>
> +#include <linux/platform_device.h>
> +#include <linux/interrupt.h>
> +#include <linux/dma-mapping.h>
> +#include <linux/slab.h>
> +
> +#include "dpio.h"
> +#include "qbman-portal.h"
> +
> +struct dpaa2_io {
> + atomic_t refs;
> + struct dpaa2_io_desc dpio_desc;
> + struct qbman_swp_desc swp_desc;
> + struct qbman_swp *swp;
> + struct list_head node;
> + spinlock_t lock_mgmt_cmd;
> + spinlock_t lock_notifications;
> + struct list_head notifications;
> +};
> +
> +struct dpaa2_io_store {
> + unsigned int max;
> + dma_addr_t paddr;
> + struct dpaa2_dq *vaddr;
> + void *alloced_addr; /* unaligned value from kmalloc() */
> + unsigned int idx; /* position of the next-to-be-returned entry */
> + struct qbman_swp *swp; /* portal used to issue VDQCR */
> + struct device *dev; /* device used for DMA mapping */
> +};
> +
> +/* keep a per cpu array of DPIOs for fast access */
> +static struct dpaa2_io *dpio_by_cpu[NR_CPUS];
> +static struct list_head dpio_list = LIST_HEAD_INIT(dpio_list);
> +static DEFINE_SPINLOCK(dpio_list_lock);
> +
> +static inline struct dpaa2_io *service_select_by_cpu(struct dpaa2_io *d,
> + int cpu)
> +{
> + if (d)
> + return d;
> +
> + if (unlikely(cpu >= NR_CPUS))
> + return NULL;
> +
> + /*
> + * If cpu == -1, choose the current cpu, with no guarantees about
> + * potentially being migrated away.
> + */
> + if (unlikely(cpu < 0))
> + cpu = smp_processor_id();
> +
> + /* If a specific cpu was requested, pick it up immediately */
> + return dpio_by_cpu[cpu];
> +}
> +
> +static inline struct dpaa2_io *service_select(struct dpaa2_io *d)
> +{
> + if (d)
> + return d;
> +
> + spin_lock(&dpio_list_lock);
> + d = list_entry(dpio_list.next, struct dpaa2_io, node);
> + list_del(&d->node);
> + list_add_tail(&d->node, &dpio_list);
> + spin_unlock(&dpio_list_lock);
> +
> + return d;
> +}
> +
> +/**
> + * dpaa2_io_create() - create a dpaa2_io object.
> + * @desc: the dpaa2_io descriptor
> + *
> + * Activates a "struct dpaa2_io" corresponding to the given config of an
> actual
> + * DPIO object.
> + *
> + * Return a valid dpaa2_io object for success, or NULL for failure.
> + */
> +struct dpaa2_io *dpaa2_io_create(const struct dpaa2_io_desc *desc)
> +{
> + struct dpaa2_io *obj = kmalloc(sizeof(*obj), GFP_KERNEL);
> +
> + if (!obj)
> + return NULL;
> +
> + /* check if CPU is out of range (-1 means any cpu) */
> + if (desc->cpu >= NR_CPUS)
> + return NULL;
> +
> + atomic_set(&obj->refs, 1);
> + obj->dpio_desc = *desc;
> + obj->swp_desc.cena_bar = obj->dpio_desc.regs_cena;
> + obj->swp_desc.cinh_bar = obj->dpio_desc.regs_cinh;
> + obj->swp_desc.qman_version = obj->dpio_desc.qman_version;
> + obj->swp = qbman_swp_init(&obj->swp_desc);
> +
> + if (!obj->swp) {
> + kfree(obj);
> + return NULL;
> + }
> +
> + INIT_LIST_HEAD(&obj->node);
> + spin_lock_init(&obj->lock_mgmt_cmd);
> + spin_lock_init(&obj->lock_notifications);
> + INIT_LIST_HEAD(&obj->notifications);
> +
> + /* For now only enable DQRR interrupts */
> + qbman_swp_interrupt_set_trigger(obj->swp,
> + QBMAN_SWP_INTERRUPT_DQRI);
> + qbman_swp_interrupt_clear_status(obj->swp, 0xffffffff);
> + if (obj->dpio_desc.receives_notifications)
> + qbman_swp_push_set(obj->swp, 0, 1);
> +
> + spin_lock(&dpio_list_lock);
> + list_add_tail(&obj->node, &dpio_list);
> + if (desc->cpu >= 0 && !dpio_by_cpu[desc->cpu])
> + dpio_by_cpu[desc->cpu] = obj;
> + spin_unlock(&dpio_list_lock);
> +
> + return obj;
> +}
> +EXPORT_SYMBOL(dpaa2_io_create);
> +
> +/**
> + * dpaa2_io_down() - release the dpaa2_io object.
> + * @d: the dpaa2_io object to be released.
> + *
> + * The "struct dpaa2_io" type can represent an individual DPIO object (as
> + * described by "struct dpaa2_io_desc") or an instance of a "DPIO service",
> + * which can be used to group/encapsulate multiple DPIO objects. In all
> cases,
> + * each handle obtained should be released using this function.
> + */
> +void dpaa2_io_down(struct dpaa2_io *d)
> +{
> + if (!atomic_dec_and_test(&d->refs))
> + return;
> + kfree(d);
> +}
> +EXPORT_SYMBOL(dpaa2_io_down);
> +
> +#define DPAA_POLL_MAX 32
> +
> +/**
> + * dpaa2_io_irq() - ISR for DPIO interrupts
> + *
> + * @obj: the given DPIO object.
> + *
> + * Return IRQ_HANDLED for success or IRQ_NONE if there
> + * were no pending interrupts.
> + */
> +irqreturn_t dpaa2_io_irq(struct dpaa2_io *obj)
> +{
> + const struct dpaa2_dq *dq;
> + int max = 0;
> + struct qbman_swp *swp;
> + u32 status;
> +
> + swp = obj->swp;
> + status = qbman_swp_interrupt_read_status(swp);
> + if (!status)
> + return IRQ_NONE;
> +
> + dq = qbman_swp_dqrr_next(swp);
> + while (dq) {
> + if (qbman_result_is_SCN(dq)) {
> + struct dpaa2_io_notification_ctx *ctx;
> + u64 q64;
> +
> + q64 = qbman_result_SCN_ctx(dq);
> + ctx = (void *)q64;
> + ctx->cb(ctx);
> + } else {
> + pr_crit("fsl-mc-dpio: Unrecognised/ignored DQRR
> entry\n");
> + }
> + qbman_swp_dqrr_consume(swp, dq);
> + ++max;
> + if (max > DPAA_POLL_MAX)
> + goto done;
> + dq = qbman_swp_dqrr_next(swp);
> + }
> +done:
> + qbman_swp_interrupt_clear_status(swp, status);
> + qbman_swp_interrupt_set_inhibit(swp, 0);
> + return IRQ_HANDLED;
> +}
> +EXPORT_SYMBOL(dpaa2_io_irq);
> +
> +/**
> + * dpaa2_io_service_register() - Prepare for servicing of FQDAN or CDAN
> + * notifications on the given DPIO service.
> + * @d: the given DPIO service.
> + * @ctx: the notification context.
> + *
> + * The caller should make the MC command to attach a DPAA2 object to
> + * a DPIO after this function completes successfully. In that way:
> + * (a) The DPIO service is "ready" to handle a notification arrival
> + * (which might happen before the "attach" command to MC has
> + * returned control of execution back to the caller)
> + * (b) The DPIO service can provide back to the caller the 'dpio_id' and
> + * 'qman64' parameters that it should pass along in the MC command
> + * in order for the object to be configured to produce the right
> + * notification fields to the DPIO service.
> + *
> + * Return 0 for success, or -ENODEV for failure.
> + */
> +int dpaa2_io_service_register(struct dpaa2_io *d,
> + struct dpaa2_io_notification_ctx *ctx)
> +{
> + unsigned long irqflags;
> +
> + d = service_select_by_cpu(d, ctx->desired_cpu);
> + if (!d)
> + return -ENODEV;
> +
> + ctx->dpio_id = d->dpio_desc.dpio_id;
> + ctx->qman64 = (u64)ctx;
> + ctx->dpio_private = d;
> + spin_lock_irqsave(&d->lock_notifications, irqflags);
> + list_add(&ctx->node, &d->notifications);
> + spin_unlock_irqrestore(&d->lock_notifications, irqflags);
> +
> + /* Enable the generation of CDAN notifications */
> + if (ctx->is_cdan)
> + qbman_swp_CDAN_set_context_enable(d->swp,
> + (u16)ctx->id,
> + ctx->qman64);
> + return 0;
> +}
> +EXPORT_SYMBOL(dpaa2_io_service_register);
> +
> +/**
> + * dpaa2_io_service_deregister - The opposite of 'register'.
> + * @service: the given DPIO service.
> + * @ctx: the notification context.
> + *
> + * This function should be called only after sending the MC command to
> + * to detach the notification-producing device from the DPIO.
> + */
> +void dpaa2_io_service_deregister(struct dpaa2_io *service,
> + struct dpaa2_io_notification_ctx *ctx)
> +{
> + struct dpaa2_io *d = ctx->dpio_private;
> + unsigned long irqflags;
> +
> + if (ctx->is_cdan)
> + qbman_swp_CDAN_disable(d->swp, (u16)ctx->id);
> +
> + spin_lock_irqsave(&d->lock_notifications, irqflags);
> + list_del(&ctx->node);
> + spin_unlock_irqrestore(&d->lock_notifications, irqflags);
> +}
> +EXPORT_SYMBOL(dpaa2_io_service_deregister);
> +
> +/**
> + * dpaa2_io_service_rearm() - Rearm the notification for the given DPIO
> service.
> + * @service: the given DPIO service.
> + * @ctx: the notification context.
> + *
> + * Once a FQDAN/CDAN has been produced, the corresponding FQ/channel
> is
> + * considered "disarmed". Ie. the user can issue pull dequeue operations on
> that
> + * traffic source for as long as it likes. Eventually it may wish to "rearm"
> + * that source to allow it to produce another FQDAN/CDAN, that's what this
> + * function achieves.
> + *
> + * Return 0 for success.
> + */
> +int dpaa2_io_service_rearm(struct dpaa2_io *d,
> + struct dpaa2_io_notification_ctx *ctx)
> +{
> + unsigned long irqflags;
> + int err;
> +
> + d = service_select(d);
Why not select the DPIO based on ctx->desired_cpu, like in the initial
notification register?
Thanks,
Ioana
> + if (!unlikely(d))
> + return -ENODEV;
> +
> + spin_lock_irqsave(&d->lock_mgmt_cmd, irqflags);
> + if (ctx->is_cdan)
> + err = qbman_swp_CDAN_enable(d->swp, (u16)ctx->id);
> + else
> + err = qbman_swp_fq_schedule(d->swp, ctx->id);
> + spin_unlock_irqrestore(&d->lock_mgmt_cmd, irqflags);
> +
> + return err;
> +}
> +EXPORT_SYMBOL(dpaa2_io_service_rearm);
[...]
> -----Original Message-----
> From: Stuart Yoder
> Sent: Friday, November 04, 2016 4:32 PM
> To: Ruxandra Ioana Radulescu <[email protected]>;
> [email protected]
> Cc: German Rivera <[email protected]>; [email protected];
> [email protected]; [email protected]; [email protected]; Leo Li
> <[email protected]>; Roy Pledge <[email protected]>
> Subject: RE: [PATCH 4/9] bus: fsl-mc: dpio: add frame descriptor and
> scatter/gather APIs
>
> > +/**
> > > + * dpaa2_fd_set_bpid() - Set the bpid field of frame descriptor
> > > + * @fd: the given frame descriptor
> > > + * @bpid: buffer pool id to be set
> > > + */
> > > +static inline void dpaa2_fd_set_bpid(struct dpaa2_fd *fd, uint16_t bpid)
> > > +{
> > > + fd->simple.bpid = bpid;
> > > +}
> >
> > The setter/getter functions for fd.ctrl are missing.
>
> Ok, will add those. Does the ethernet driver use that field?
Yes.
>
> > > +
> > > +/**
> > > + * struct dpaa2_sg_entry - the scatter-gathering structure
> > > + * @addr: address of the sg entry
> > > + * @len: length in this sg entry
> > > + * @bpid: buffer pool id
> > > + * @format_offset: offset in the MS 16 bits, BPID in the LS 16 bits
> >
> > Description of the format_offset field is incorrect, it shouldn't
> > contain the reference to BPID.
>
> Thanks, will fix.
>
> > > +/**
> > > + * dpaa2_sg_get_len() - Get the length in SG entry
> > > + * @sg: the given scatter-gathering object
> > > + *
> > > + * Return the length.
> > > + */
> > > +static inline u32 dpaa2_sg_get_len(const struct dpaa2_sg_entry *sg)
> > > +{
> > > + if (dpaa2_sg_short_len(sg))
> > > + return le32_to_cpu(sg->len) & SG_SHORT_LEN_MASK;
> > > +
> > > + return le32_to_cpu(sg->len);
> > > +}
> >
> > We should do this in dpaa2_fd_get_len() as well. Hardware is capable of
> > generating FDs with SL bit set for single frame format too, although in
> > practice I've never actually seen it.
>
> Any suggestion on how to test this case?
Actually, I stand corrected. Apparently WRIOP _always_ generates short
len frames, it just happens that, for the current default settings, the rest
of the bits in the 32bit word that contains the short length field are always
zero.
For FDs generated on the core both formats are accepted, and we use
long length format for the Ethernet driver TX frames.
Thanks,
Ioana
> -----Original Message-----
> From: Stuart Yoder
> Sent: Thursday, November 03, 2016 4:38 PM
> To: Ruxandra Ioana Radulescu <[email protected]>
> Subject: FW: [PATCH 8/9] bus: fsl-mc: dpio: add the DPAA2 DPIO object
> driver
>
>
>
> -----Original Message-----
> From: Stuart Yoder [mailto:[email protected]]
> Sent: Friday, October 21, 2016 9:02 AM
> To: [email protected]
> Cc: German Rivera <[email protected]>; [email protected];
> [email protected]; [email protected]; [email protected]; Leo Li
> <[email protected]>; Roy Pledge <[email protected]>; Haiying Wang
> <[email protected]>; Stuart Yoder <[email protected]>
> Subject: [PATCH 8/9] bus: fsl-mc: dpio: add the DPAA2 DPIO object driver
>
> From: Roy Pledge <[email protected]>
>
> The DPIO driver registers with the fsl-mc bus to handle bus-related
> events for DPIO objects. Key responsibility is mapping I/O
> regions, setting up interrupt handlers, and calling the DPIO
> service initialization during probe.
>
> Signed-off-by: Roy Pledge <[email protected]>
> Signed-off-by: Haiying Wang <[email protected]>
> Signed-off-by: Stuart Yoder <[email protected]>
> ---
> drivers/bus/fsl-mc/dpio/Makefile | 2 +-
> drivers/bus/fsl-mc/dpio/dpio-driver.c | 289
> ++++++++++++++++++++++++++++++++++
> 2 files changed, 290 insertions(+), 1 deletion(-)
> create mode 100644 drivers/bus/fsl-mc/dpio/dpio-driver.c
>
> diff --git a/drivers/bus/fsl-mc/dpio/Makefile b/drivers/bus/fsl-
> mc/dpio/Makefile
> index 0778da7..837d330 100644
> --- a/drivers/bus/fsl-mc/dpio/Makefile
> +++ b/drivers/bus/fsl-mc/dpio/Makefile
> @@ -6,4 +6,4 @@ subdir-ccflags-y := -Werror
>
> obj-$(CONFIG_FSL_MC_DPIO) += fsl-mc-dpio.o
>
> -fsl-mc-dpio-objs := dpio.o qbman-portal.o dpio-service.o
> +fsl-mc-dpio-objs := dpio.o qbman-portal.o dpio-service.o dpio-driver.o
> diff --git a/drivers/bus/fsl-mc/dpio/dpio-driver.c b/drivers/bus/fsl-
> mc/dpio/dpio-driver.c
> new file mode 100644
> index 0000000..ad04a2c
> --- /dev/null
> +++ b/drivers/bus/fsl-mc/dpio/dpio-driver.c
> @@ -0,0 +1,289 @@
> +/*
> + * Copyright 2014-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:
> + * * Redistributions of source code must retain the above copyright
> + * notice, this list of conditions and the following disclaimer.
> + * * Redistributions in binary form must reproduce the above copyright
> + * notice, this list of conditions and the following disclaimer in the
> + * documentation and/or other materials provided with the
> distribution.
> + * * Neither the name of Freescale Semiconductor nor the
> + * names of its contributors may be used to endorse or promote
> products
> + * derived from this software without specific prior written permission.
> + *
> + * ALTERNATIVELY, this software may be distributed under the terms of the
> + * GNU General Public License ("GPL") as published by the Free Software
> + * Foundation, either version 2 of that License or (at your option) any
> + * later version.
> + *
> + * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND
> ANY
> + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
> THE IMPLIED
> + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
> PURPOSE ARE
> + * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR
> ANY
> + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
> CONSEQUENTIAL DAMAGES
> + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
> GOODS OR SERVICES;
> + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
> HOWEVER CAUSED AND
> + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
> OR TORT
> + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
> THE USE OF THIS
> + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
> + */
> +
> +#include <linux/types.h>
> +#include <linux/init.h>
> +#include <linux/module.h>
> +#include <linux/platform_device.h>
> +#include <linux/interrupt.h>
> +#include <linux/msi.h>
> +#include <linux/dma-mapping.h>
> +#include <linux/delay.h>
> +
> +#include <linux/fsl/mc.h>
> +#include <linux/fsl/dpaa2-io.h>
> +
> +#include "qbman-portal.h"
> +#include "dpio.h"
> +#include "dpio-cmd.h"
> +
> +MODULE_LICENSE("Dual BSD/GPL");
> +MODULE_AUTHOR("Freescale Semiconductor, Inc");
> +MODULE_DESCRIPTION("DPIO Driver");
> +
> +struct dpio_priv {
> + struct dpaa2_io *io;
> +};
> +
> +static irqreturn_t dpio_irq_handler(int irq_num, void *arg)
> +{
> + struct device *dev = (struct device *)arg;
> + struct dpio_priv *priv = dev_get_drvdata(dev);
> +
> + return dpaa2_io_irq(priv->io);
> +}
> +
> +static void unregister_dpio_irq_handlers(struct fsl_mc_device *dpio_dev)
> +{
> + struct fsl_mc_device_irq *irq;
> +
> + irq = dpio_dev->irqs[0];
> +
> + /* clear the affinity hint */
> + irq_set_affinity_hint(irq->msi_desc->irq, NULL);
> +}
> +
> +static int register_dpio_irq_handlers(struct fsl_mc_device *dpio_dev, int
> cpu)
> +{
> + struct dpio_priv *priv;
> + int error;
> + struct fsl_mc_device_irq *irq;
> + cpumask_t mask;
> +
> + priv = dev_get_drvdata(&dpio_dev->dev);
> +
> + irq = dpio_dev->irqs[0];
> + error = devm_request_irq(&dpio_dev->dev,
> + irq->msi_desc->irq,
> + dpio_irq_handler,
> + 0,
> + dev_name(&dpio_dev->dev),
> + &dpio_dev->dev);
> + if (error < 0) {
> + dev_err(&dpio_dev->dev,
> + "devm_request_irq() failed: %d\n",
> + error);
> + return error;
> + }
> +
> + /* set the affinity hint */
> + cpumask_clear(&mask);
> + cpumask_set_cpu(cpu, &mask);
> + if (irq_set_affinity_hint(irq->msi_desc->irq, &mask))
> + dev_err(&dpio_dev->dev,
> + "irq_set_affinity failed irq %d cpu %d\n",
> + irq->msi_desc->irq, cpu);
> +
> + return 0;
> +}
> +
> +static int dpaa2_dpio_probe(struct fsl_mc_device *dpio_dev)
> +{
> + struct dpio_attr dpio_attrs;
> + struct dpaa2_io_desc desc;
> + struct dpio_priv *priv;
> + int err = -ENOMEM;
> + struct device *dev = &dpio_dev->dev;
> + static int next_cpu = -1;
> +
> + priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
> + if (!priv)
> + goto err_priv_alloc;
> +
> + dev_set_drvdata(dev, priv);
> +
> + err = fsl_mc_portal_allocate(dpio_dev, 0, &dpio_dev->mc_io);
> + if (err) {
> + dev_dbg(dev, "MC portal allocation failed\n");
> + err = -EPROBE_DEFER;
> + goto err_mcportal;
> + }
> +
> + err = dpio_open(dpio_dev->mc_io, 0, dpio_dev->obj_desc.id,
> + &dpio_dev->mc_handle);
> + if (err) {
> + dev_err(dev, "dpio_open() failed\n");
> + goto err_open;
> + }
> +
> + err = dpio_get_attributes(dpio_dev->mc_io, 0, dpio_dev-
> >mc_handle,
> + &dpio_attrs);
> + if (err) {
> + dev_err(dev, "dpio_get_attributes() failed %d\n", err);
> + goto err_get_attr;
> + }
> + desc.qman_version = dpio_attrs.qbman_version;
> +
> + err = dpio_enable(dpio_dev->mc_io, 0, dpio_dev->mc_handle);
> + if (err) {
> + dev_err(dev, "dpio_enable() failed %d\n", err);
> + goto err_get_attr;
> + }
> +
> + /* initialize DPIO descriptor */
> + desc.receives_notifications = dpio_attrs.num_priorities ? 1 : 0;
> + desc.has_8prio = dpio_attrs.num_priorities == 8 ? 1 : 0;
> + desc.dpio_id = dpio_dev->obj_desc.id;
> +
> + /* get the cpu to use for the affinity hint */
> + if (next_cpu == -1)
> + next_cpu = cpumask_first(cpu_online_mask);
> + else
> + next_cpu = cpumask_next(next_cpu, cpu_online_mask);
> + desc.cpu = next_cpu;
What happens if there's more DPIOs than cores and cpumask_next
returns nr_cpu_ids?
Thanks,
Ioana
> -----Original Message-----
> From: Ruxandra Ioana Radulescu
> Sent: Friday, November 04, 2016 10:04 AM
> To: Stuart Yoder <[email protected]>; [email protected]
> Cc: German Rivera <[email protected]>; [email protected]; [email protected];
> [email protected]; [email protected]; Leo Li <[email protected]>; Roy Pledge <[email protected]>
> Subject: RE: [PATCH 4/9] bus: fsl-mc: dpio: add frame descriptor and scatter/gather APIs
>
> > -----Original Message-----
> > From: Stuart Yoder
> > Sent: Friday, November 04, 2016 4:32 PM
> > To: Ruxandra Ioana Radulescu <[email protected]>;
> > [email protected]
> > Cc: German Rivera <[email protected]>; [email protected];
> > [email protected]; [email protected]; [email protected]; Leo Li
> > <[email protected]>; Roy Pledge <[email protected]>
> > Subject: RE: [PATCH 4/9] bus: fsl-mc: dpio: add frame descriptor and
> > scatter/gather APIs
> >
> > > +/**
> > > > + * dpaa2_fd_set_bpid() - Set the bpid field of frame descriptor
> > > > + * @fd: the given frame descriptor
> > > > + * @bpid: buffer pool id to be set
> > > > + */
> > > > +static inline void dpaa2_fd_set_bpid(struct dpaa2_fd *fd, uint16_t bpid)
> > > > +{
> > > > + fd->simple.bpid = bpid;
> > > > +}
> > >
> > > The setter/getter functions for fd.ctrl are missing.
> >
> > Ok, will add those. Does the ethernet driver use that field?
>
> Yes.
>
> >
> > > > +
> > > > +/**
> > > > + * struct dpaa2_sg_entry - the scatter-gathering structure
> > > > + * @addr: address of the sg entry
> > > > + * @len: length in this sg entry
> > > > + * @bpid: buffer pool id
> > > > + * @format_offset: offset in the MS 16 bits, BPID in the LS 16 bits
> > >
> > > Description of the format_offset field is incorrect, it shouldn't
> > > contain the reference to BPID.
> >
> > Thanks, will fix.
> >
> > > > +/**
> > > > + * dpaa2_sg_get_len() - Get the length in SG entry
> > > > + * @sg: the given scatter-gathering object
> > > > + *
> > > > + * Return the length.
> > > > + */
> > > > +static inline u32 dpaa2_sg_get_len(const struct dpaa2_sg_entry *sg)
> > > > +{
> > > > + if (dpaa2_sg_short_len(sg))
> > > > + return le32_to_cpu(sg->len) & SG_SHORT_LEN_MASK;
> > > > +
> > > > + return le32_to_cpu(sg->len);
> > > > +}
> > >
> > > We should do this in dpaa2_fd_get_len() as well. Hardware is capable of
> > > generating FDs with SL bit set for single frame format too, although in
> > > practice I've never actually seen it.
> >
> > Any suggestion on how to test this case?
>
> Actually, I stand corrected. Apparently WRIOP _always_ generates short
> len frames, it just happens that, for the current default settings, the rest
> of the bits in the 32bit word that contains the short length field are always
> zero.
Ok, so we were getting lucky. I'll fix that in the next respin.
Thanks,
Stuart
> -----Original Message-----
> From: Ruxandra Ioana Radulescu
> Sent: Friday, November 04, 2016 10:11 AM
> To: Stuart Yoder <[email protected]>; [email protected]
> Cc: German Rivera <[email protected]>; [email protected]; [email protected];
> [email protected]; [email protected]; Leo Li <[email protected]>; Roy Pledge <[email protected]>; Haiying Wang
> <[email protected]>; Stuart Yoder <[email protected]>
> Subject: RE: [PATCH 8/9] bus: fsl-mc: dpio: add the DPAA2 DPIO object driver
>
> > -----Original Message-----
> > From: Stuart Yoder
> > Sent: Thursday, November 03, 2016 4:38 PM
> > To: Ruxandra Ioana Radulescu <[email protected]>
> > Subject: FW: [PATCH 8/9] bus: fsl-mc: dpio: add the DPAA2 DPIO object
> > driver
> >
> >
> >
> > -----Original Message-----
> > From: Stuart Yoder [mailto:[email protected]]
> > Sent: Friday, October 21, 2016 9:02 AM
> > To: [email protected]
> > Cc: German Rivera <[email protected]>; [email protected];
> > [email protected]; [email protected]; [email protected]; Leo Li
> > <[email protected]>; Roy Pledge <[email protected]>; Haiying Wang
> > <[email protected]>; Stuart Yoder <[email protected]>
> > Subject: [PATCH 8/9] bus: fsl-mc: dpio: add the DPAA2 DPIO object driver
> >
> > From: Roy Pledge <[email protected]>
> >
> > The DPIO driver registers with the fsl-mc bus to handle bus-related
> > events for DPIO objects. Key responsibility is mapping I/O
> > regions, setting up interrupt handlers, and calling the DPIO
> > service initialization during probe.
> >
> > Signed-off-by: Roy Pledge <[email protected]>
> > Signed-off-by: Haiying Wang <[email protected]>
> > Signed-off-by: Stuart Yoder <[email protected]>
> > ---
> > drivers/bus/fsl-mc/dpio/Makefile | 2 +-
> > drivers/bus/fsl-mc/dpio/dpio-driver.c | 289
> > ++++++++++++++++++++++++++++++++++
> > 2 files changed, 290 insertions(+), 1 deletion(-)
> > create mode 100644 drivers/bus/fsl-mc/dpio/dpio-driver.c
> >
> > diff --git a/drivers/bus/fsl-mc/dpio/Makefile b/drivers/bus/fsl-
> > mc/dpio/Makefile
> > index 0778da7..837d330 100644
> > --- a/drivers/bus/fsl-mc/dpio/Makefile
> > +++ b/drivers/bus/fsl-mc/dpio/Makefile
> > @@ -6,4 +6,4 @@ subdir-ccflags-y := -Werror
> >
> > obj-$(CONFIG_FSL_MC_DPIO) += fsl-mc-dpio.o
> >
> > -fsl-mc-dpio-objs := dpio.o qbman-portal.o dpio-service.o
> > +fsl-mc-dpio-objs := dpio.o qbman-portal.o dpio-service.o dpio-driver.o
> > diff --git a/drivers/bus/fsl-mc/dpio/dpio-driver.c b/drivers/bus/fsl-
> > mc/dpio/dpio-driver.c
> > new file mode 100644
> > index 0000000..ad04a2c
> > --- /dev/null
> > +++ b/drivers/bus/fsl-mc/dpio/dpio-driver.c
> > @@ -0,0 +1,289 @@
> > +/*
> > + * Copyright 2014-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:
> > + * * Redistributions of source code must retain the above copyright
> > + * notice, this list of conditions and the following disclaimer.
> > + * * Redistributions in binary form must reproduce the above copyright
> > + * notice, this list of conditions and the following disclaimer in the
> > + * documentation and/or other materials provided with the
> > distribution.
> > + * * Neither the name of Freescale Semiconductor nor the
> > + * names of its contributors may be used to endorse or promote
> > products
> > + * derived from this software without specific prior written permission.
> > + *
> > + * ALTERNATIVELY, this software may be distributed under the terms of the
> > + * GNU General Public License ("GPL") as published by the Free Software
> > + * Foundation, either version 2 of that License or (at your option) any
> > + * later version.
> > + *
> > + * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND
> > ANY
> > + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
> > THE IMPLIED
> > + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
> > PURPOSE ARE
> > + * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR
> > ANY
> > + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
> > CONSEQUENTIAL DAMAGES
> > + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
> > GOODS OR SERVICES;
> > + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
> > HOWEVER CAUSED AND
> > + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
> > OR TORT
> > + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
> > THE USE OF THIS
> > + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
> > + */
> > +
> > +#include <linux/types.h>
> > +#include <linux/init.h>
> > +#include <linux/module.h>
> > +#include <linux/platform_device.h>
> > +#include <linux/interrupt.h>
> > +#include <linux/msi.h>
> > +#include <linux/dma-mapping.h>
> > +#include <linux/delay.h>
> > +
> > +#include <linux/fsl/mc.h>
> > +#include <linux/fsl/dpaa2-io.h>
> > +
> > +#include "qbman-portal.h"
> > +#include "dpio.h"
> > +#include "dpio-cmd.h"
> > +
> > +MODULE_LICENSE("Dual BSD/GPL");
> > +MODULE_AUTHOR("Freescale Semiconductor, Inc");
> > +MODULE_DESCRIPTION("DPIO Driver");
> > +
> > +struct dpio_priv {
> > + struct dpaa2_io *io;
> > +};
> > +
> > +static irqreturn_t dpio_irq_handler(int irq_num, void *arg)
> > +{
> > + struct device *dev = (struct device *)arg;
> > + struct dpio_priv *priv = dev_get_drvdata(dev);
> > +
> > + return dpaa2_io_irq(priv->io);
> > +}
> > +
> > +static void unregister_dpio_irq_handlers(struct fsl_mc_device *dpio_dev)
> > +{
> > + struct fsl_mc_device_irq *irq;
> > +
> > + irq = dpio_dev->irqs[0];
> > +
> > + /* clear the affinity hint */
> > + irq_set_affinity_hint(irq->msi_desc->irq, NULL);
> > +}
> > +
> > +static int register_dpio_irq_handlers(struct fsl_mc_device *dpio_dev, int
> > cpu)
> > +{
> > + struct dpio_priv *priv;
> > + int error;
> > + struct fsl_mc_device_irq *irq;
> > + cpumask_t mask;
> > +
> > + priv = dev_get_drvdata(&dpio_dev->dev);
> > +
> > + irq = dpio_dev->irqs[0];
> > + error = devm_request_irq(&dpio_dev->dev,
> > + irq->msi_desc->irq,
> > + dpio_irq_handler,
> > + 0,
> > + dev_name(&dpio_dev->dev),
> > + &dpio_dev->dev);
> > + if (error < 0) {
> > + dev_err(&dpio_dev->dev,
> > + "devm_request_irq() failed: %d\n",
> > + error);
> > + return error;
> > + }
> > +
> > + /* set the affinity hint */
> > + cpumask_clear(&mask);
> > + cpumask_set_cpu(cpu, &mask);
> > + if (irq_set_affinity_hint(irq->msi_desc->irq, &mask))
> > + dev_err(&dpio_dev->dev,
> > + "irq_set_affinity failed irq %d cpu %d\n",
> > + irq->msi_desc->irq, cpu);
> > +
> > + return 0;
> > +}
> > +
> > +static int dpaa2_dpio_probe(struct fsl_mc_device *dpio_dev)
> > +{
> > + struct dpio_attr dpio_attrs;
> > + struct dpaa2_io_desc desc;
> > + struct dpio_priv *priv;
> > + int err = -ENOMEM;
> > + struct device *dev = &dpio_dev->dev;
> > + static int next_cpu = -1;
> > +
> > + priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
> > + if (!priv)
> > + goto err_priv_alloc;
> > +
> > + dev_set_drvdata(dev, priv);
> > +
> > + err = fsl_mc_portal_allocate(dpio_dev, 0, &dpio_dev->mc_io);
> > + if (err) {
> > + dev_dbg(dev, "MC portal allocation failed\n");
> > + err = -EPROBE_DEFER;
> > + goto err_mcportal;
> > + }
> > +
> > + err = dpio_open(dpio_dev->mc_io, 0, dpio_dev->obj_desc.id,
> > + &dpio_dev->mc_handle);
> > + if (err) {
> > + dev_err(dev, "dpio_open() failed\n");
> > + goto err_open;
> > + }
> > +
> > + err = dpio_get_attributes(dpio_dev->mc_io, 0, dpio_dev-
> > >mc_handle,
> > + &dpio_attrs);
> > + if (err) {
> > + dev_err(dev, "dpio_get_attributes() failed %d\n", err);
> > + goto err_get_attr;
> > + }
> > + desc.qman_version = dpio_attrs.qbman_version;
> > +
> > + err = dpio_enable(dpio_dev->mc_io, 0, dpio_dev->mc_handle);
> > + if (err) {
> > + dev_err(dev, "dpio_enable() failed %d\n", err);
> > + goto err_get_attr;
> > + }
> > +
> > + /* initialize DPIO descriptor */
> > + desc.receives_notifications = dpio_attrs.num_priorities ? 1 : 0;
> > + desc.has_8prio = dpio_attrs.num_priorities == 8 ? 1 : 0;
> > + desc.dpio_id = dpio_dev->obj_desc.id;
> > +
> > + /* get the cpu to use for the affinity hint */
> > + if (next_cpu == -1)
> > + next_cpu = cpumask_first(cpu_online_mask);
> > + else
> > + next_cpu = cpumask_next(next_cpu, cpu_online_mask);
> > + desc.cpu = next_cpu;
>
> What happens if there's more DPIOs than cores and cpumask_next
> returns nr_cpu_ids?
We need to error out in that case. DPIO can't handle >= NR_CPUS.
Stuart
> -----Original Message-----
> From: Ruxandra Ioana Radulescu
> Sent: Thursday, November 10, 2016 9:04 AM
> To: Stuart Yoder <[email protected]>; [email protected]
> Cc: German Rivera <[email protected]>; [email protected]; [email protected];
> [email protected]; [email protected]; Leo Li <[email protected]>; Roy Pledge <[email protected]>; Haiying Wang
> <[email protected]>; Stuart Yoder <[email protected]>
> Subject: RE: [PATCH 6/9] bus: fsl-mc: dpio: add QBMan portal APIs for DPAA2
>
>
> > -----Original Message-----
> > From: Stuart Yoder [mailto:[email protected]]
> > Sent: Friday, October 21, 2016 9:02 AM
> > To: [email protected]
> > Cc: German Rivera <[email protected]>; [email protected];
> > [email protected]; [email protected]; [email protected]; Leo Li
> > <[email protected]>; Roy Pledge <[email protected]>; Roy Pledge
> > <[email protected]>; Haiying Wang <[email protected]>; Stuart
> > Yoder <[email protected]>
> > Subject: [PATCH 6/9] bus: fsl-mc: dpio: add QBMan portal APIs for DPAA2
> >
> > From: Roy Pledge <[email protected]>
> >
> > Add QBman APIs for frame queue and buffer pool operations.
> >
> > Signed-off-by: Roy Pledge <[email protected]>
> > Signed-off-by: Haiying Wang <[email protected]>
> > Signed-off-by: Stuart Yoder <[email protected]>
> > ---
> > drivers/bus/fsl-mc/dpio/Makefile | 2 +-
> > drivers/bus/fsl-mc/dpio/qbman-portal.c | 1009
> > ++++++++++++++++++++++++++++++++
> > drivers/bus/fsl-mc/dpio/qbman-portal.h | 464 +++++++++++++++
> > 3 files changed, 1474 insertions(+), 1 deletion(-)
> > create mode 100644 drivers/bus/fsl-mc/dpio/qbman-portal.c
> > create mode 100644 drivers/bus/fsl-mc/dpio/qbman-portal.h
> >
> > diff --git a/drivers/bus/fsl-mc/dpio/Makefile b/drivers/bus/fsl-
> > mc/dpio/Makefile
> > index 128befc..6588498 100644
> > --- a/drivers/bus/fsl-mc/dpio/Makefile
> > +++ b/drivers/bus/fsl-mc/dpio/Makefile
> > @@ -6,4 +6,4 @@ subdir-ccflags-y := -Werror
> >
> > obj-$(CONFIG_FSL_MC_DPIO) += fsl-mc-dpio.o
> >
> > -fsl-mc-dpio-objs := dpio.o
> > +fsl-mc-dpio-objs := dpio.o qbman-portal.o
> > diff --git a/drivers/bus/fsl-mc/dpio/qbman-portal.c b/drivers/bus/fsl-
> > mc/dpio/qbman-portal.c
> > new file mode 100644
> > index 0000000..1eb3dd9
> > --- /dev/null
> > +++ b/drivers/bus/fsl-mc/dpio/qbman-portal.c
> > @@ -0,0 +1,1009 @@
>
> [...]
>
> > +/**
> > + * qbman_swp_release() - Issue a buffer release command
> > + * @s: the software portal object
> > + * @d: the release descriptor
> > + * @buffers: a pointer pointing to the buffer address to be released
> > + * @num_buffers: number of buffers to be released, must be less than 8
> > + *
> > + * Return 0 for success, -EBUSY if the release command ring is not ready.
> > + */
> > +int qbman_swp_release(struct qbman_swp *s, const struct
> > qbman_release_desc *d,
> > + const u64 *buffers, unsigned int num_buffers)
> > +{
> > + int i;
> > + struct qbman_release_desc *p;
> > + u32 rar;
> > +
> > + if (!num_buffers || (num_buffers > 7))
> > + return -EINVAL;
> > +
> > + rar = qbman_read_register(s, QBMAN_CINH_SWP_RAR);
> > + if (!RAR_SUCCESS(rar))
> > + return -EBUSY;
> > +
> > + /* Start the release command */
> > + p = qbman_get_cmd(s, QBMAN_CENA_SWP_RCR(RAR_IDX(rar)));
> > + /* Copy the caller's buffer pointers to the command */
> > + for (i = 0; i < num_buffers; i++)
> > + p->buf[i] = cpu_to_le64(buffers[i]);
> > +
>
> Hi Stuart,
> We also need to set BPID field in the buffer release command, something like:
> + p->bpid = d->bpid;
> Without this all buffers will be released to buffer pool id 0, which is incorrect.
Will fix on next respin.
> > + /*
> > + * Set the verb byte, have to substitute in the valid-bit and the
> > number
> > + * of buffers.
> > + */
> > + dma_wmb();
> > + p->verb = d->verb | RAR_VB(rar) | num_buffers;
> > +
> > + return 0;
> > +}
> > +
> > +struct qbman_acquire_desc {
> > + u8 verb;
> > + u8 reserved;
> > + u16 bpid;
> > + u8 num;
> > + u8 reserved2[59];
> > +};
> > +
> > +struct qbman_acquire_rslt {
> > + u8 verb;
> > + u8 rslt;
> > + u16 reserved;
> > + u8 num;
> > + u8 reserved2[3];
> > + u64 buf[7];
> > +};
> > +
> > +/**
> > + * qbman_swp_acquire() - Issue a buffer acquire command
> > + * @s: the software portal object
> > + * @bpid: the buffer pool index
> > + * @buffers: a pointer pointing to the acquired buffer addresses
> > + * @num_buffers: number of buffers to be acquired, must be less than 8
> > + *
> > + * Return 0 for success, or negative error code if the acquire command
> > + * fails.
> > + */
> > +int qbman_swp_acquire(struct qbman_swp *s, u16 bpid, u64 *buffers,
> > + unsigned int num_buffers)
> > +{
> > + struct qbman_acquire_desc *p;
> > + struct qbman_acquire_rslt *r;
> > + int i;
> > +
> > + if (!num_buffers || (num_buffers > 7))
> > + return -EINVAL;
> > +
> > + /* Start the management command */
> > + p = qbman_swp_mc_start(s);
>
> qbman_swp_mc_start() returns a pointer to where the QBMan
> management command must be written, but doesn't clear any
> previous values found there.
> We should memset the area to zero before using it.
> Same comment applies to other places where this function is used.
Ok, will fix.
> > +
> > + if (!p)
> > + return -EBUSY;
> > +
> > + /* Encode the caller-provided attributes */
> > + p->bpid = cpu_to_le16(bpid);
> > + p->num = num_buffers;
> > +
> > + /* Complete the management command */
> > + r = qbman_swp_mc_complete(s, p, p->verb |
> > QBMAN_MC_ACQUIRE);
>
> qbman_swp_mc_complete() may return NULL, if for instance the hardware
> is unresponsive. We need to check this before dereferencing r.
> Same for other instances of usage throughout the code.
Ok, will fix.
Thanks for the review.
Stuart
> -----Original Message-----
> From: Stuart Yoder [mailto:[email protected]]
> Sent: Friday, October 21, 2016 9:02 AM
> To: [email protected]
> Cc: German Rivera <[email protected]>; [email protected];
> [email protected]; [email protected]; [email protected]; Leo Li
> <[email protected]>; Roy Pledge <[email protected]>; Roy Pledge
> <[email protected]>; Haiying Wang <[email protected]>; Stuart
> Yoder <[email protected]>
> Subject: [PATCH 6/9] bus: fsl-mc: dpio: add QBMan portal APIs for DPAA2
>
> From: Roy Pledge <[email protected]>
>
> Add QBman APIs for frame queue and buffer pool operations.
>
> Signed-off-by: Roy Pledge <[email protected]>
> Signed-off-by: Haiying Wang <[email protected]>
> Signed-off-by: Stuart Yoder <[email protected]>
> ---
> drivers/bus/fsl-mc/dpio/Makefile | 2 +-
> drivers/bus/fsl-mc/dpio/qbman-portal.c | 1009
> ++++++++++++++++++++++++++++++++
> drivers/bus/fsl-mc/dpio/qbman-portal.h | 464 +++++++++++++++
> 3 files changed, 1474 insertions(+), 1 deletion(-)
> create mode 100644 drivers/bus/fsl-mc/dpio/qbman-portal.c
> create mode 100644 drivers/bus/fsl-mc/dpio/qbman-portal.h
>
> diff --git a/drivers/bus/fsl-mc/dpio/Makefile b/drivers/bus/fsl-
> mc/dpio/Makefile
> index 128befc..6588498 100644
> --- a/drivers/bus/fsl-mc/dpio/Makefile
> +++ b/drivers/bus/fsl-mc/dpio/Makefile
> @@ -6,4 +6,4 @@ subdir-ccflags-y := -Werror
>
> obj-$(CONFIG_FSL_MC_DPIO) += fsl-mc-dpio.o
>
> -fsl-mc-dpio-objs := dpio.o
> +fsl-mc-dpio-objs := dpio.o qbman-portal.o
> diff --git a/drivers/bus/fsl-mc/dpio/qbman-portal.c b/drivers/bus/fsl-
> mc/dpio/qbman-portal.c
> new file mode 100644
> index 0000000..1eb3dd9
> --- /dev/null
> +++ b/drivers/bus/fsl-mc/dpio/qbman-portal.c
> @@ -0,0 +1,1009 @@
[...]
> +/**
> + * qbman_swp_release() - Issue a buffer release command
> + * @s: the software portal object
> + * @d: the release descriptor
> + * @buffers: a pointer pointing to the buffer address to be released
> + * @num_buffers: number of buffers to be released, must be less than 8
> + *
> + * Return 0 for success, -EBUSY if the release command ring is not ready.
> + */
> +int qbman_swp_release(struct qbman_swp *s, const struct
> qbman_release_desc *d,
> + const u64 *buffers, unsigned int num_buffers)
> +{
> + int i;
> + struct qbman_release_desc *p;
> + u32 rar;
> +
> + if (!num_buffers || (num_buffers > 7))
> + return -EINVAL;
> +
> + rar = qbman_read_register(s, QBMAN_CINH_SWP_RAR);
> + if (!RAR_SUCCESS(rar))
> + return -EBUSY;
> +
> + /* Start the release command */
> + p = qbman_get_cmd(s, QBMAN_CENA_SWP_RCR(RAR_IDX(rar)));
> + /* Copy the caller's buffer pointers to the command */
> + for (i = 0; i < num_buffers; i++)
> + p->buf[i] = cpu_to_le64(buffers[i]);
> +
Hi Stuart,
We also need to set BPID field in the buffer release command, something like:
+ p->bpid = d->bpid;
Without this all buffers will be released to buffer pool id 0, which is incorrect.
> + /*
> + * Set the verb byte, have to substitute in the valid-bit and the
> number
> + * of buffers.
> + */
> + dma_wmb();
> + p->verb = d->verb | RAR_VB(rar) | num_buffers;
> +
> + return 0;
> +}
> +
> +struct qbman_acquire_desc {
> + u8 verb;
> + u8 reserved;
> + u16 bpid;
> + u8 num;
> + u8 reserved2[59];
> +};
> +
> +struct qbman_acquire_rslt {
> + u8 verb;
> + u8 rslt;
> + u16 reserved;
> + u8 num;
> + u8 reserved2[3];
> + u64 buf[7];
> +};
> +
> +/**
> + * qbman_swp_acquire() - Issue a buffer acquire command
> + * @s: the software portal object
> + * @bpid: the buffer pool index
> + * @buffers: a pointer pointing to the acquired buffer addresses
> + * @num_buffers: number of buffers to be acquired, must be less than 8
> + *
> + * Return 0 for success, or negative error code if the acquire command
> + * fails.
> + */
> +int qbman_swp_acquire(struct qbman_swp *s, u16 bpid, u64 *buffers,
> + unsigned int num_buffers)
> +{
> + struct qbman_acquire_desc *p;
> + struct qbman_acquire_rslt *r;
> + int i;
> +
> + if (!num_buffers || (num_buffers > 7))
> + return -EINVAL;
> +
> + /* Start the management command */
> + p = qbman_swp_mc_start(s);
qbman_swp_mc_start() returns a pointer to where the QBMan
management command must be written, but doesn't clear any
previous values found there.
We should memset the area to zero before using it.
Same comment applies to other places where this function is used.
> +
> + if (!p)
> + return -EBUSY;
> +
> + /* Encode the caller-provided attributes */
> + p->bpid = cpu_to_le16(bpid);
> + p->num = num_buffers;
> +
> + /* Complete the management command */
> + r = qbman_swp_mc_complete(s, p, p->verb |
> QBMAN_MC_ACQUIRE);
qbman_swp_mc_complete() may return NULL, if for instance the hardware
is unresponsive. We need to check this before dereferencing r.
Same for other instances of usage throughout the code.
Thanks,
Ioana
> > +/**
> > + * dpaa2_io_service_rearm() - Rearm the notification for the given DPIO
> > service.
> > + * @service: the given DPIO service.
> > + * @ctx: the notification context.
> > + *
> > + * Once a FQDAN/CDAN has been produced, the corresponding FQ/channel
> > is
> > + * considered "disarmed". Ie. the user can issue pull dequeue operations on
> > that
> > + * traffic source for as long as it likes. Eventually it may wish to "rearm"
> > + * that source to allow it to produce another FQDAN/CDAN, that's what this
> > + * function achieves.
> > + *
> > + * Return 0 for success.
> > + */
> > +int dpaa2_io_service_rearm(struct dpaa2_io *d,
> > + struct dpaa2_io_notification_ctx *ctx)
> > +{
> > + unsigned long irqflags;
> > + int err;
> > +
> > + d = service_select(d);
>
> Why not select the DPIO based on ctx->desired_cpu, like in the initial
> notification register?
Sounds like a reasonable idea, I am going to confirm with Roy.
Stuart
> -----Original Message-----
> From: Stuart Yoder [mailto:[email protected]]
> Sent: Friday, October 21, 2016 9:02 AM
> To: [email protected]
> Cc: German Rivera <[email protected]>; [email protected];
> [email protected]; [email protected]; [email protected]; Leo Li
> <[email protected]>; Roy Pledge <[email protected]>; Roy Pledge
> <[email protected]>; Haiying Wang <[email protected]>; Stuart
> Yoder <[email protected]>
> Subject: [PATCH 6/9] bus: fsl-mc: dpio: add QBMan portal APIs for DPAA2
>
> From: Roy Pledge <[email protected]>
>
> Add QBman APIs for frame queue and buffer pool operations.
>
> Signed-off-by: Roy Pledge <[email protected]>
> Signed-off-by: Haiying Wang <[email protected]>
> Signed-off-by: Stuart Yoder <[email protected]>
> ---
> drivers/bus/fsl-mc/dpio/Makefile | 2 +-
> drivers/bus/fsl-mc/dpio/qbman-portal.c | 1009
> ++++++++++++++++++++++++++++++++
> drivers/bus/fsl-mc/dpio/qbman-portal.h | 464 +++++++++++++++
> 3 files changed, 1474 insertions(+), 1 deletion(-)
> create mode 100644 drivers/bus/fsl-mc/dpio/qbman-portal.c
> create mode 100644 drivers/bus/fsl-mc/dpio/qbman-portal.h
>
> diff --git a/drivers/bus/fsl-mc/dpio/Makefile b/drivers/bus/fsl-
> mc/dpio/Makefile
> index 128befc..6588498 100644
> --- a/drivers/bus/fsl-mc/dpio/Makefile
> +++ b/drivers/bus/fsl-mc/dpio/Makefile
> @@ -6,4 +6,4 @@ subdir-ccflags-y := -Werror
>
> obj-$(CONFIG_FSL_MC_DPIO) += fsl-mc-dpio.o
>
> -fsl-mc-dpio-objs := dpio.o
> +fsl-mc-dpio-objs := dpio.o qbman-portal.o
> diff --git a/drivers/bus/fsl-mc/dpio/qbman-portal.c b/drivers/bus/fsl-
> mc/dpio/qbman-portal.c
> new file mode 100644
> index 0000000..1eb3dd9
> --- /dev/null
> +++ b/drivers/bus/fsl-mc/dpio/qbman-portal.c
[...]
> +/**
> + * qbman_swp_pull() - Issue the pull dequeue command
> + * @s: the software portal object
> + * @d: the software portal descriptor which has been configured with
> + * the set of qbman_pull_desc_set_*() calls
> + *
> + * Return 0 for success, and -EBUSY if the software portal is not ready
> + * to do pull dequeue.
> + */
> +int qbman_swp_pull(struct qbman_swp *s, struct qbman_pull_desc *d)
> +{
> + struct qbman_pull_desc *p;
> +
> + if (!atomic_dec_and_test(&s->vdq.available)) {
> + atomic_inc(&s->vdq.available);
> + return -EBUSY;
> + }
> + s->vdq.storage = (void *)d->rsp_addr_virt;
> + d->tok = 1;
> + p = qbman_get_cmd(s, QBMAN_CENA_SWP_VDQCR);
> + *p = *d;
> + dma_wmb();
> +
> + /* Set the verb byte, have to substitute in the valid-bit */
> + p->verb |= s->vdq.valid_bit;
> + s->vdq.valid_bit ^= QB_VALID_BIT;
> +
> + return 0;
> +}
> +
[...]
> +
> +/**
> + * qbman_result_has_new_result() - Check and get the dequeue response
> from the
> + * dq storage memory set in pull dequeue command
> + * @s: the software portal object
> + * @dq: the dequeue result read from the memory
> + *
> + * Return 1 for getting a valid dequeue result, or 0 for not getting a valid
> + * dequeue result.
> + *
> + * Only used for user-provided storage of dequeue results, not DQRR. For
> + * efficiency purposes, the driver will perform any required endianness
> + * conversion to ensure that the user's dequeue result storage is in host-
> endian
> + * format. As such, once the user has called
> qbman_result_has_new_result() and
> + * been returned a valid dequeue result, they should not call it again on
> + * the same memory location (except of course if another dequeue
> command has
> + * been executed to produce a new result to that location).
> + */
> +int qbman_result_has_new_result(struct qbman_swp *s, const struct
> dpaa2_dq *dq)
> +{
> + if (!dq->dq.tok)
> + return 0;
While testing the Ethernet driver I discovered that sometimes the above
check fails.
When we check a store entry for the first time, if the hardware didn't
manage to fill it with a valid respose yet, we may find a non-null value in the
token field (because the stores have uninitialized memory). So by only
checking that token is !=0, we risk processing an uninitialized memory area
as a valid dequeue entry.
We should always compare the token field against 1, the value that is given
to the hardware on the dequeue command. It might also be a good idea
to use a define here, to make it clear 1 is a magic value.
And I think we should also zero the stores when they are first allocated,
since even with the proposed fix there's still a (much smaller) risk of finding
our exact token value in an uninitialized memory area.
Thanks,
Ioana
> -----Original Message-----
> From: Ruxandra Ioana Radulescu
> Sent: Monday, November 28, 2016 12:10 PM
> To: Stuart Yoder <[email protected]>; [email protected]
> Cc: German Rivera <[email protected]>; [email protected]; [email protected];
> [email protected]; [email protected]; Leo Li <[email protected]>; Roy Pledge <[email protected]>; Haiying Wang
> <[email protected]>
> Subject: RE: [PATCH 6/9] bus: fsl-mc: dpio: add QBMan portal APIs for DPAA2
>
> > -----Original Message-----
> > From: Stuart Yoder [mailto:[email protected]]
> > Sent: Friday, October 21, 2016 9:02 AM
> > To: [email protected]
> > Cc: German Rivera <[email protected]>; [email protected];
> > [email protected]; [email protected]; [email protected]; Leo Li
> > <[email protected]>; Roy Pledge <[email protected]>; Roy Pledge
> > <[email protected]>; Haiying Wang <[email protected]>; Stuart
> > Yoder <[email protected]>
> > Subject: [PATCH 6/9] bus: fsl-mc: dpio: add QBMan portal APIs for DPAA2
> >
> > From: Roy Pledge <[email protected]>
> >
> > Add QBman APIs for frame queue and buffer pool operations.
> >
> > Signed-off-by: Roy Pledge <[email protected]>
> > Signed-off-by: Haiying Wang <[email protected]>
> > Signed-off-by: Stuart Yoder <[email protected]>
> > ---
> > drivers/bus/fsl-mc/dpio/Makefile | 2 +-
> > drivers/bus/fsl-mc/dpio/qbman-portal.c | 1009
> > ++++++++++++++++++++++++++++++++
> > drivers/bus/fsl-mc/dpio/qbman-portal.h | 464 +++++++++++++++
> > 3 files changed, 1474 insertions(+), 1 deletion(-)
> > create mode 100644 drivers/bus/fsl-mc/dpio/qbman-portal.c
> > create mode 100644 drivers/bus/fsl-mc/dpio/qbman-portal.h
> >
> > diff --git a/drivers/bus/fsl-mc/dpio/Makefile b/drivers/bus/fsl-
> > mc/dpio/Makefile
> > index 128befc..6588498 100644
> > --- a/drivers/bus/fsl-mc/dpio/Makefile
> > +++ b/drivers/bus/fsl-mc/dpio/Makefile
> > @@ -6,4 +6,4 @@ subdir-ccflags-y := -Werror
> >
> > obj-$(CONFIG_FSL_MC_DPIO) += fsl-mc-dpio.o
> >
> > -fsl-mc-dpio-objs := dpio.o
> > +fsl-mc-dpio-objs := dpio.o qbman-portal.o
> > diff --git a/drivers/bus/fsl-mc/dpio/qbman-portal.c b/drivers/bus/fsl-
> > mc/dpio/qbman-portal.c
> > new file mode 100644
> > index 0000000..1eb3dd9
> > --- /dev/null
> > +++ b/drivers/bus/fsl-mc/dpio/qbman-portal.c
>
> [...]
>
> > +/**
> > + * qbman_swp_pull() - Issue the pull dequeue command
> > + * @s: the software portal object
> > + * @d: the software portal descriptor which has been configured with
> > + * the set of qbman_pull_desc_set_*() calls
> > + *
> > + * Return 0 for success, and -EBUSY if the software portal is not ready
> > + * to do pull dequeue.
> > + */
> > +int qbman_swp_pull(struct qbman_swp *s, struct qbman_pull_desc *d)
> > +{
> > + struct qbman_pull_desc *p;
> > +
> > + if (!atomic_dec_and_test(&s->vdq.available)) {
> > + atomic_inc(&s->vdq.available);
> > + return -EBUSY;
> > + }
> > + s->vdq.storage = (void *)d->rsp_addr_virt;
> > + d->tok = 1;
> > + p = qbman_get_cmd(s, QBMAN_CENA_SWP_VDQCR);
> > + *p = *d;
> > + dma_wmb();
> > +
> > + /* Set the verb byte, have to substitute in the valid-bit */
> > + p->verb |= s->vdq.valid_bit;
> > + s->vdq.valid_bit ^= QB_VALID_BIT;
> > +
> > + return 0;
> > +}
> > +
> [...]
> > +
> > +/**
> > + * qbman_result_has_new_result() - Check and get the dequeue response
> > from the
> > + * dq storage memory set in pull dequeue command
> > + * @s: the software portal object
> > + * @dq: the dequeue result read from the memory
> > + *
> > + * Return 1 for getting a valid dequeue result, or 0 for not getting a valid
> > + * dequeue result.
> > + *
> > + * Only used for user-provided storage of dequeue results, not DQRR. For
> > + * efficiency purposes, the driver will perform any required endianness
> > + * conversion to ensure that the user's dequeue result storage is in host-
> > endian
> > + * format. As such, once the user has called
> > qbman_result_has_new_result() and
> > + * been returned a valid dequeue result, they should not call it again on
> > + * the same memory location (except of course if another dequeue
> > command has
> > + * been executed to produce a new result to that location).
> > + */
> > +int qbman_result_has_new_result(struct qbman_swp *s, const struct
> > dpaa2_dq *dq)
> > +{
> > + if (!dq->dq.tok)
> > + return 0;
>
> While testing the Ethernet driver I discovered that sometimes the above
> check fails.
>
> When we check a store entry for the first time, if the hardware didn't
> manage to fill it with a valid respose yet, we may find a non-null value in the
> token field (because the stores have uninitialized memory). So by only
> checking that token is !=0, we risk processing an uninitialized memory area
> as a valid dequeue entry.
>
> We should always compare the token field against 1, the value that is given
> to the hardware on the dequeue command. It might also be a good idea
> to use a define here, to make it clear 1 is a magic value.
>
> And I think we should also zero the stores when they are first allocated,
> since even with the proposed fix there's still a (much smaller) risk of finding
> our exact token value in an uninitialized memory area.
Thanks. Will fix this on v3 respin.
Stuart