Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit c24602ef authored by Giuseppe CAVALLARO's avatar Giuseppe CAVALLARO Committed by David S. Miller
Browse files

stmmac: support extend descriptors



This patch is to support the extend descriptors available
in the chips newer than the 3.50.

In case of the extend descriptors cannot be supported,
at runtime, the driver will continue to work using the old style.

In detail, this support extends the main descriptor structure
adding new descriptors: 4, 5, 6, 7. The desc4 gives us extra
information about the received ethernet payload when it is
carrying PTP packets or TCP/UDP/ICMP over IP packets.
The descriptors 6 and 7 are used for saving HW L/H timestamps (PTP).

V2: this new version removes the Koption added in the first implementation
because all the checks now to verify if the extended descriptors are
actually supported happen at probe time.

Signed-off-by: default avatarGiuseppe Cavallaro <peppe.cavallaro@st.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 4a7d666a
Loading
Loading
Loading
Loading
+20 −9
Original line number Diff line number Diff line
@@ -89,17 +89,27 @@ static unsigned int stmmac_is_jumbo_frm(int len, int enh_desc)
	return ret;
}

static void stmmac_init_dma_chain(struct dma_desc *des, dma_addr_t phy_addr,
				  unsigned int size)
static void stmmac_init_dma_chain(void *des, dma_addr_t phy_addr,
				  unsigned int size, unsigned int extend_desc)
{
	/*
	 * In chained mode the des3 points to the next element in the ring.
	 * The latest element has to point to the head.
	 */
	int i;
	struct dma_desc *p = des;
	dma_addr_t dma_phy = phy_addr;

	if (extend_desc) {
		struct dma_extended_desc *p = (struct dma_extended_desc *) des;
		for (i = 0; i < (size - 1); i++) {
			dma_phy += sizeof(struct dma_extended_desc);
			p->basic.des3 = (unsigned int)dma_phy;
			p++;
		}
		p->basic.des3 = (unsigned int)phy_addr;

	} else {
		struct dma_desc *p = (struct dma_desc *) des;
		for (i = 0; i < (size - 1); i++) {
			dma_phy += sizeof(struct dma_desc);
			p->des3 = (unsigned int)dma_phy;
@@ -107,9 +117,10 @@ static void stmmac_init_dma_chain(struct dma_desc *des, dma_addr_t phy_addr,
		}
		p->des3 = (unsigned int)phy_addr;
	}
}

const struct stmmac_chain_mode_ops chain_mode_ops = {
	.init = stmmac_init_dma_chain,
	.is_jumbo_frm = stmmac_is_jumbo_frm,
	.jumbo_frm = stmmac_jumbo_frm,
	.init_dma_chain = stmmac_init_dma_chain,
};
+31 −7
Original line number Diff line number Diff line
@@ -117,6 +117,29 @@ struct stmmac_extra_stats {
	unsigned long irq_rx_path_in_lpi_mode_n;
	unsigned long irq_rx_path_exit_lpi_mode_n;
	unsigned long phy_eee_wakeup_error_n;
	/* Extended RDES status */
	unsigned long ip_hdr_err;
	unsigned long ip_payload_err;
	unsigned long ip_csum_bypassed;
	unsigned long ipv4_pkt_rcvd;
	unsigned long ipv6_pkt_rcvd;
	unsigned long rx_msg_type_ext_no_ptp;
	unsigned long rx_msg_type_sync;
	unsigned long rx_msg_type_follow_up;
	unsigned long rx_msg_type_delay_req;
	unsigned long rx_msg_type_delay_resp;
	unsigned long rx_msg_type_pdelay_req;
	unsigned long rx_msg_type_pdelay_resp;
	unsigned long rx_msg_type_pdelay_follow_up;
	unsigned long ptp_frame_type;
	unsigned long ptp_ver;
	unsigned long timestamp_dropped;
	unsigned long av_pkt_rcvd;
	unsigned long av_tagged_pkt_rcvd;
	unsigned long vlan_tag_priority_val;
	unsigned long l3_filter_match;
	unsigned long l4_filter_match;
	unsigned long l3_l4_filter_no_match;
};

/* CSR Frequency Access Defines*/
@@ -260,11 +283,10 @@ struct dma_features {

struct stmmac_desc_ops {
	/* DMA RX descriptor ring initialization */
	void (*init_rx_desc) (struct dma_desc *p, unsigned int ring_size,
			      int disable_rx_ic, int mode);
	void (*init_rx_desc) (struct dma_desc *p, int disable_rx_ic, int mode,
			      int end);
	/* DMA TX descriptor ring initialization */
	void (*init_tx_desc) (struct dma_desc *p, unsigned int ring_size,
			      int mode);
	void (*init_tx_desc) (struct dma_desc *p, int mode, int end);

	/* Invoked by the xmit function to prepare the tx descriptor */
	void (*prepare_tx_desc) (struct dma_desc *p, int is_fs, int len,
@@ -294,12 +316,14 @@ struct stmmac_desc_ops {
	/* Return the reception status looking at the RDES1 */
	int (*rx_status) (void *data, struct stmmac_extra_stats *x,
			  struct dma_desc *p);
	void (*rx_extended_status) (void *data, struct stmmac_extra_stats *x,
				    struct dma_extended_desc *p);
};

struct stmmac_dma_ops {
	/* DMA core initialization */
	int (*init) (void __iomem *ioaddr, int pbl, int fb, int mb,
		     int burst_len, u32 dma_tx, u32 dma_rx);
		     int burst_len, u32 dma_tx, u32 dma_rx, int atds);
	/* Dump DMA registers */
	void (*dump_regs) (void __iomem *ioaddr);
	/* Set tx/rx threshold in the csr6 register
@@ -371,10 +395,10 @@ struct stmmac_ring_mode_ops {
};

struct stmmac_chain_mode_ops {
	void (*init) (void *des, dma_addr_t phy_addr, unsigned int size,
		      unsigned int extend_desc);
	unsigned int (*is_jumbo_frm) (int len, int ehn_desc);
	unsigned int (*jumbo_frm) (void *priv, struct sk_buff *skb, int csum);
	void (*init_dma_chain) (struct dma_desc *des, dma_addr_t phy_addr,
				unsigned int size);
};

struct mac_device_info {
+48 −3
Original line number Diff line number Diff line
@@ -24,6 +24,7 @@
#ifndef __DESCS_H__
#define __DESCS_H__

/* Basic descriptor structure for normal and alternate descriptors */
struct dma_desc {
	/* Receive descriptor */
	union {
@@ -60,7 +61,7 @@ struct dma_desc {
		} rx;
		struct {
			/* RDES0 */
			u32 payload_csum_error:1;
			u32 rx_mac_addr:1;
			u32 crc_error:1;
			u32 dribbling:1;
			u32 error_gmii:1;
@@ -162,13 +163,57 @@ struct dma_desc {
	unsigned int des3;
};

/* Extended descriptor structure (supported by new SYNP GMAC generations) */
struct dma_extended_desc {
	struct dma_desc basic;
	union {
		struct {
			u32 ip_payload_type:3;
			u32 ip_hdr_err:1;
			u32 ip_payload_err:1;
			u32 ip_csum_bypassed:1;
			u32 ipv4_pkt_rcvd:1;
			u32 ipv6_pkt_rcvd:1;
			u32 msg_type:4;
			u32 ptp_frame_type:1;
			u32 ptp_ver:1;
			u32 timestamp_dropped:1;
			u32 reserved:1;
			u32 av_pkt_rcvd:1;
			u32 av_tagged_pkt_rcvd:1;
			u32 vlan_tag_priority_val:3;
			u32 reserved3:3;
			u32 l3_filter_match:1;
			u32 l4_filter_match:1;
			u32 l3_l4_filter_no_match:2;
			u32 reserved4:4;
		} erx;
		struct {
			u32 reserved;
		} etx;
	} des4;
	unsigned int des5; /* Reserved */
	unsigned int des6; /* Tx/Rx Timestamp Low */
	unsigned int des7; /* Tx/Rx Timestamp High */
};

/* Transmit checksum insertion control */
enum tdes_csum_insertion {
	cic_disabled = 0,	/* Checksum Insertion Control */
	cic_only_ip = 1,	/* Only IP header */
	cic_no_pseudoheader = 2,	/* IP header but pseudoheader
					 * is not calculated */
	/* IP header but pseudoheader is not calculated */
	cic_no_pseudoheader = 2,
	cic_full = 3,		/* IP header and pseudoheader */
};

/* Extended RDES4 definitions */
#define RDES_EXT_NO_PTP			0
#define RDES_EXT_SYNC			0x1
#define RDES_EXT_FOLLOW_UP		0x2
#define RDES_EXT_DELAY_REQ		0x3
#define RDES_EXT_DELAY_RESP		0x4
#define RDES_EXT_PDELAY_REQ		0x5
#define RDES_EXT_PDELAY_RESP		0x6
#define RDES_EXT_PDELAY_FOLLOW_UP	0x7

#endif /* __DESCS_H__ */
+1 −0
Original line number Diff line number Diff line
@@ -155,6 +155,7 @@ enum inter_frame_gap {
/* Programmable burst length (passed thorugh platform)*/
#define DMA_BUS_MODE_PBL_MASK	0x00003f00	/* Programmable Burst Len */
#define DMA_BUS_MODE_PBL_SHIFT	8
#define DMA_BUS_MODE_ATDS	0x00000080	/* Alternate Descriptor Size */

enum rx_tx_priority_ratio {
	double_ratio = 0x00004000,	/*2:1 */
+6 −2
Original line number Diff line number Diff line
@@ -30,8 +30,8 @@
#include "dwmac1000.h"
#include "dwmac_dma.h"

static int dwmac1000_dma_init(void __iomem *ioaddr, int pbl, int fb,
			      int mb, int burst_len, u32 dma_tx, u32 dma_rx)
static int dwmac1000_dma_init(void __iomem *ioaddr, int pbl, int fb, int mb,
			      int burst_len, u32 dma_tx, u32 dma_rx, int atds)
{
	u32 value = readl(ioaddr + DMA_BUS_MODE);
	int limit;
@@ -73,6 +73,10 @@ static int dwmac1000_dma_init(void __iomem *ioaddr, int pbl, int fb,
#ifdef CONFIG_STMMAC_DA
	value |= DMA_BUS_MODE_DA;	/* Rx has priority over tx */
#endif

	if (atds)
		value |= DMA_BUS_MODE_ATDS;

	writel(value, ioaddr + DMA_BUS_MODE);

	/* In case of GMAC AXI configuration, program the DMA_AXI_BUS_MODE
Loading