Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > linux.kernel > #1515196 > unrolled thread

RE: [PATCH 4/9] bus: fsl-mc: dpio: add frame descriptor and scatter/gather APIs

Started byRuxandra Ioana Radulescu <ruxandra.radulescu@nxp.com>
First post2016-11-04 14:40 +0100
Last post2016-11-08 01:20 +0100
Articles 4 — 2 participants

Back to article view | Back to linux.kernel

This discussion starts older than the indexed window; earlier articles aren't shown. The article labeled Started by below is the oldest one visible, not the original post.


Contents

  RE: [PATCH 4/9] bus: fsl-mc: dpio: add frame descriptor and  scatter/gather APIs Ruxandra Ioana Radulescu <ruxandra.radulescu@nxp.com> - 2016-11-04 14:40 +0100
    RE: [PATCH 4/9] bus: fsl-mc: dpio: add frame descriptor and  scatter/gather APIs Stuart Yoder <stuart.yoder@nxp.com> - 2016-11-04 15:50 +0100
      RE: [PATCH 4/9] bus: fsl-mc: dpio: add frame descriptor and  scatter/gather APIs Ruxandra Ioana Radulescu <ruxandra.radulescu@nxp.com> - 2016-11-04 19:40 +0100
        RE: [PATCH 4/9] bus: fsl-mc: dpio: add frame descriptor and  scatter/gather APIs Stuart Yoder <stuart.yoder@nxp.com> - 2016-11-08 01:20 +0100

#1515196 — RE: [PATCH 4/9] bus: fsl-mc: dpio: add frame descriptor and scatter/gather APIs

FromRuxandra Ioana Radulescu <ruxandra.radulescu@nxp.com>
Date2016-11-04 14:40 +0100
SubjectRE: [PATCH 4/9] bus: fsl-mc: dpio: add frame descriptor and scatter/gather APIs
Message-ID<szMSW-2gE-5@gated-at.bofh.it>
> -----Original Message-----
> From: Stuart Yoder [mailto:stuart.yoder@nxp.com]
> Sent: Friday, October 21, 2016 9:02 AM
> To: gregkh@linuxfoundation.org
> Cc: German Rivera <german.rivera@nxp.com>; devel@driverdev.osuosl.org;
> linux-kernel@vger.kernel.org; agraf@suse.de; arnd@arndb.de; Leo Li
> <leoyang.li@nxp.com>; Roy Pledge <roy.pledge@nxp.com>; Stuart Yoder
> <stuart.yoder@nxp.com>
> Subject: [PATCH 4/9] bus: fsl-mc: dpio: add frame descriptor and
> scatter/gather APIs
> 
> From: Roy Pledge <Roy.Pledge@nxp.com>
> 
> Add global definitions for DPAA2 frame descriptors and scatter
> gather entries.
> 
> Signed-off-by: Roy Pledge <Roy.Pledge@nxp.com>
> Signed-off-by: Stuart Yoder <stuart.yoder@nxp.com>
> ---
>  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

[toc] | [next] | [standalone]


#1515226

FromStuart Yoder <stuart.yoder@nxp.com>
Date2016-11-04 15:50 +0100
Message-ID<szNYB-342-19@gated-at.bofh.it>
In reply to#1515196
 > +/**
> > + * 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

[toc] | [prev] | [next] | [standalone]


#1515362

FromRuxandra Ioana Radulescu <ruxandra.radulescu@nxp.com>
Date2016-11-04 19:40 +0100
Message-ID<szRzc-5pA-17@gated-at.bofh.it>
In reply to#1515226
> -----Original Message-----
> From: Stuart Yoder
> Sent: Friday, November 04, 2016 4:32 PM
> To: Ruxandra Ioana Radulescu <ruxandra.radulescu@nxp.com>;
> gregkh@linuxfoundation.org
> Cc: German Rivera <german.rivera@nxp.com>; devel@driverdev.osuosl.org;
> linux-kernel@vger.kernel.org; agraf@suse.de; arnd@arndb.de; Leo Li
> <leoyang.li@nxp.com>; Roy Pledge <roy.pledge@nxp.com>
> 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

[toc] | [prev] | [next] | [standalone]


#1516695

FromStuart Yoder <stuart.yoder@nxp.com>
Date2016-11-08 01:20 +0100
Message-ID<sB2iR-23v-3@gated-at.bofh.it>
In reply to#1515362

> -----Original Message-----
> From: Ruxandra Ioana Radulescu
> Sent: Friday, November 04, 2016 10:04 AM
> To: Stuart Yoder <stuart.yoder@nxp.com>; gregkh@linuxfoundation.org
> Cc: German Rivera <german.rivera@nxp.com>; devel@driverdev.osuosl.org; linux-kernel@vger.kernel.org;
> agraf@suse.de; arnd@arndb.de; Leo Li <leoyang.li@nxp.com>; Roy Pledge <roy.pledge@nxp.com>
> 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 <ruxandra.radulescu@nxp.com>;
> > gregkh@linuxfoundation.org
> > Cc: German Rivera <german.rivera@nxp.com>; devel@driverdev.osuosl.org;
> > linux-kernel@vger.kernel.org; agraf@suse.de; arnd@arndb.de; Leo Li
> > <leoyang.li@nxp.com>; Roy Pledge <roy.pledge@nxp.com>
> > 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

[toc] | [prev] | [standalone]


Back to top | Article view | linux.kernel


csiph-web