0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015 #include "stmmac.h"
0016
0017 static int jumbo_frm(void *p, struct sk_buff *skb, int csum)
0018 {
0019 struct stmmac_tx_queue *tx_q = (struct stmmac_tx_queue *)p;
0020 unsigned int nopaged_len = skb_headlen(skb);
0021 struct stmmac_priv *priv = tx_q->priv_data;
0022 unsigned int entry = tx_q->cur_tx;
0023 unsigned int bmax, des2;
0024 unsigned int i = 1, len;
0025 struct dma_desc *desc;
0026
0027 desc = tx_q->dma_tx + entry;
0028
0029 if (priv->plat->enh_desc)
0030 bmax = BUF_SIZE_8KiB;
0031 else
0032 bmax = BUF_SIZE_2KiB;
0033
0034 len = nopaged_len - bmax;
0035
0036 des2 = dma_map_single(priv->device, skb->data,
0037 bmax, DMA_TO_DEVICE);
0038 desc->des2 = cpu_to_le32(des2);
0039 if (dma_mapping_error(priv->device, des2))
0040 return -1;
0041 tx_q->tx_skbuff_dma[entry].buf = des2;
0042 tx_q->tx_skbuff_dma[entry].len = bmax;
0043
0044 stmmac_prepare_tx_desc(priv, desc, 1, bmax, csum, STMMAC_CHAIN_MODE,
0045 0, false, skb->len);
0046
0047 while (len != 0) {
0048 tx_q->tx_skbuff[entry] = NULL;
0049 entry = STMMAC_GET_ENTRY(entry, priv->dma_conf.dma_tx_size);
0050 desc = tx_q->dma_tx + entry;
0051
0052 if (len > bmax) {
0053 des2 = dma_map_single(priv->device,
0054 (skb->data + bmax * i),
0055 bmax, DMA_TO_DEVICE);
0056 desc->des2 = cpu_to_le32(des2);
0057 if (dma_mapping_error(priv->device, des2))
0058 return -1;
0059 tx_q->tx_skbuff_dma[entry].buf = des2;
0060 tx_q->tx_skbuff_dma[entry].len = bmax;
0061 stmmac_prepare_tx_desc(priv, desc, 0, bmax, csum,
0062 STMMAC_CHAIN_MODE, 1, false, skb->len);
0063 len -= bmax;
0064 i++;
0065 } else {
0066 des2 = dma_map_single(priv->device,
0067 (skb->data + bmax * i), len,
0068 DMA_TO_DEVICE);
0069 desc->des2 = cpu_to_le32(des2);
0070 if (dma_mapping_error(priv->device, des2))
0071 return -1;
0072 tx_q->tx_skbuff_dma[entry].buf = des2;
0073 tx_q->tx_skbuff_dma[entry].len = len;
0074
0075 stmmac_prepare_tx_desc(priv, desc, 0, len, csum,
0076 STMMAC_CHAIN_MODE, 1, true, skb->len);
0077 len = 0;
0078 }
0079 }
0080
0081 tx_q->cur_tx = entry;
0082
0083 return entry;
0084 }
0085
0086 static unsigned int is_jumbo_frm(int len, int enh_desc)
0087 {
0088 unsigned int ret = 0;
0089
0090 if ((enh_desc && (len > BUF_SIZE_8KiB)) ||
0091 (!enh_desc && (len > BUF_SIZE_2KiB))) {
0092 ret = 1;
0093 }
0094
0095 return ret;
0096 }
0097
0098 static void init_dma_chain(void *des, dma_addr_t phy_addr,
0099 unsigned int size, unsigned int extend_desc)
0100 {
0101
0102
0103
0104
0105 int i;
0106 dma_addr_t dma_phy = phy_addr;
0107
0108 if (extend_desc) {
0109 struct dma_extended_desc *p = (struct dma_extended_desc *)des;
0110 for (i = 0; i < (size - 1); i++) {
0111 dma_phy += sizeof(struct dma_extended_desc);
0112 p->basic.des3 = cpu_to_le32((unsigned int)dma_phy);
0113 p++;
0114 }
0115 p->basic.des3 = cpu_to_le32((unsigned int)phy_addr);
0116
0117 } else {
0118 struct dma_desc *p = (struct dma_desc *)des;
0119 for (i = 0; i < (size - 1); i++) {
0120 dma_phy += sizeof(struct dma_desc);
0121 p->des3 = cpu_to_le32((unsigned int)dma_phy);
0122 p++;
0123 }
0124 p->des3 = cpu_to_le32((unsigned int)phy_addr);
0125 }
0126 }
0127
0128 static void refill_desc3(void *priv_ptr, struct dma_desc *p)
0129 {
0130 struct stmmac_rx_queue *rx_q = (struct stmmac_rx_queue *)priv_ptr;
0131 struct stmmac_priv *priv = rx_q->priv_data;
0132
0133 if (priv->hwts_rx_en && !priv->extend_desc)
0134
0135
0136
0137
0138 p->des3 = cpu_to_le32((unsigned int)(rx_q->dma_rx_phy +
0139 (((rx_q->dirty_rx) + 1) %
0140 priv->dma_conf.dma_rx_size) *
0141 sizeof(struct dma_desc)));
0142 }
0143
0144 static void clean_desc3(void *priv_ptr, struct dma_desc *p)
0145 {
0146 struct stmmac_tx_queue *tx_q = (struct stmmac_tx_queue *)priv_ptr;
0147 struct stmmac_priv *priv = tx_q->priv_data;
0148 unsigned int entry = tx_q->dirty_tx;
0149
0150 if (tx_q->tx_skbuff_dma[entry].last_segment && !priv->extend_desc &&
0151 priv->hwts_tx_en)
0152
0153
0154
0155
0156 p->des3 = cpu_to_le32((unsigned int)((tx_q->dma_tx_phy +
0157 ((tx_q->dirty_tx + 1) %
0158 priv->dma_conf.dma_tx_size))
0159 * sizeof(struct dma_desc)));
0160 }
0161
0162 const struct stmmac_mode_ops chain_mode_ops = {
0163 .init = init_dma_chain,
0164 .is_jumbo_frm = is_jumbo_frm,
0165 .jumbo_frm = jumbo_frm,
0166 .refill_desc3 = refill_desc3,
0167 .clean_desc3 = clean_desc3,
0168 };