2011-10-18 00:01:24 +00:00
/*******************************************************************************
Specialised functions for managing Chained mode
Copyright ( C ) 2011 STMicroelectronics Ltd
It defines all the functions used to handle the normal / enhanced
descriptors in case of the DMA is configured to work in chained or
in ring mode .
This program is free software ; you can redistribute it and / or modify it
under the terms and conditions of the GNU General Public License ,
version 2 , as published by the Free Software Foundation .
This program is distributed in the hope it will be useful , but WITHOUT
ANY WARRANTY ; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE . See the GNU General Public License for
more details .
The full GNU General Public License is included in this distribution in
the file called " COPYING " .
Author : Giuseppe Cavallaro < peppe . cavallaro @ st . com >
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
# include "stmmac.h"
2014-08-27 11:27:00 +02:00
static int stmmac_jumbo_frm ( void * p , struct sk_buff * skb , int csum )
2011-10-18 00:01:24 +00:00
{
2017-04-06 09:49:10 +01:00
struct stmmac_tx_queue * tx_q = ( struct stmmac_tx_queue * ) p ;
2011-10-18 00:01:24 +00:00
unsigned int nopaged_len = skb_headlen ( skb ) ;
2017-04-06 09:49:10 +01:00
struct stmmac_priv * priv = tx_q - > priv_data ;
unsigned int entry = tx_q - > cur_tx ;
2016-11-14 18:58:05 +01:00
unsigned int bmax , des2 ;
2011-10-18 00:01:24 +00:00
unsigned int i = 1 , len ;
2017-04-06 09:49:10 +01:00
struct dma_desc * desc ;
desc = tx_q - > dma_tx + entry ;
2011-10-18 00:01:24 +00:00
if ( priv - > plat - > enh_desc )
bmax = BUF_SIZE_8KiB ;
else
bmax = BUF_SIZE_2KiB ;
len = nopaged_len - bmax ;
2016-11-14 18:58:05 +01:00
des2 = dma_map_single ( priv - > device , skb - > data ,
bmax , DMA_TO_DEVICE ) ;
desc - > des2 = cpu_to_le32 ( des2 ) ;
if ( dma_mapping_error ( priv - > device , des2 ) )
2014-08-27 11:27:00 +02:00
return - 1 ;
2017-04-06 09:49:10 +01:00
tx_q - > tx_skbuff_dma [ entry ] . buf = des2 ;
tx_q - > tx_skbuff_dma [ entry ] . len = bmax ;
2016-02-29 14:27:35 +01:00
/* do not close the descriptor and do not set own bit */
priv - > hw - > desc - > prepare_tx_desc ( desc , 1 , bmax , csum , STMMAC_CHAIN_MODE ,
2017-04-10 20:33:29 +02:00
0 , false , skb - > len ) ;
2011-10-18 00:01:24 +00:00
while ( len ! = 0 ) {
2017-04-06 09:49:10 +01:00
tx_q - > tx_skbuff [ entry ] = NULL ;
2016-02-29 14:27:30 +01:00
entry = STMMAC_GET_ENTRY ( entry , DMA_TX_SIZE ) ;
2017-04-06 09:49:10 +01:00
desc = tx_q - > dma_tx + entry ;
2011-10-18 00:01:24 +00:00
if ( len > bmax ) {
2016-11-14 18:58:05 +01:00
des2 = dma_map_single ( priv - > device ,
( skb - > data + bmax * i ) ,
bmax , DMA_TO_DEVICE ) ;
desc - > des2 = cpu_to_le32 ( des2 ) ;
if ( dma_mapping_error ( priv - > device , des2 ) )
2014-08-27 11:27:00 +02:00
return - 1 ;
2017-04-06 09:49:10 +01:00
tx_q - > tx_skbuff_dma [ entry ] . buf = des2 ;
tx_q - > tx_skbuff_dma [ entry ] . len = bmax ;
2013-03-26 04:43:05 +00:00
priv - > hw - > desc - > prepare_tx_desc ( desc , 0 , bmax , csum ,
2016-02-29 14:27:35 +01:00
STMMAC_CHAIN_MODE , 1 ,
2017-04-10 20:33:29 +02:00
false , skb - > len ) ;
2011-10-18 00:01:24 +00:00
len - = bmax ;
i + + ;
} else {
2016-11-14 18:58:05 +01:00
des2 = dma_map_single ( priv - > device ,
( skb - > data + bmax * i ) , len ,
DMA_TO_DEVICE ) ;
desc - > des2 = cpu_to_le32 ( des2 ) ;
if ( dma_mapping_error ( priv - > device , des2 ) )
2014-08-27 11:27:00 +02:00
return - 1 ;
2017-04-06 09:49:10 +01:00
tx_q - > tx_skbuff_dma [ entry ] . buf = des2 ;
tx_q - > tx_skbuff_dma [ entry ] . len = len ;
2016-02-29 14:27:35 +01:00
/* last descriptor can be set now */
2013-03-26 04:43:05 +00:00
priv - > hw - > desc - > prepare_tx_desc ( desc , 0 , len , csum ,
2016-02-29 14:27:35 +01:00
STMMAC_CHAIN_MODE , 1 ,
2017-04-10 20:33:29 +02:00
true , skb - > len ) ;
2011-10-18 00:01:24 +00:00
len = 0 ;
}
}
2016-02-29 14:27:30 +01:00
2017-04-06 09:49:10 +01:00
tx_q - > cur_tx = entry ;
2016-02-29 14:27:30 +01:00
2011-10-18 00:01:24 +00:00
return entry ;
}
static unsigned int stmmac_is_jumbo_frm ( int len , int enh_desc )
{
unsigned int ret = 0 ;
if ( ( enh_desc & & ( len > BUF_SIZE_8KiB ) ) | |
( ! enh_desc & & ( len > BUF_SIZE_2KiB ) ) ) {
ret = 1 ;
}
return ret ;
}
2013-03-26 04:43:06 +00:00
static void stmmac_init_dma_chain ( void * des , dma_addr_t phy_addr ,
unsigned int size , unsigned int extend_desc )
2011-10-18 00:01:24 +00:00
{
/*
* In chained mode the des3 points to the next element in the ring .
* The latest element has to point to the head .
*/
int i ;
dma_addr_t dma_phy = phy_addr ;
2013-03-26 04:43:06 +00:00
if ( extend_desc ) {
2013-04-08 02:10:01 +00:00
struct dma_extended_desc * p = ( struct dma_extended_desc * ) des ;
2013-03-26 04:43:06 +00:00
for ( i = 0 ; i < ( size - 1 ) ; i + + ) {
dma_phy + = sizeof ( struct dma_extended_desc ) ;
2016-11-14 18:58:05 +01:00
p - > basic . des3 = cpu_to_le32 ( ( unsigned int ) dma_phy ) ;
2013-03-26 04:43:06 +00:00
p + + ;
}
2016-11-14 18:58:05 +01:00
p - > basic . des3 = cpu_to_le32 ( ( unsigned int ) phy_addr ) ;
2013-03-26 04:43:06 +00:00
} else {
2013-04-08 02:10:01 +00:00
struct dma_desc * p = ( struct dma_desc * ) des ;
2013-03-26 04:43:06 +00:00
for ( i = 0 ; i < ( size - 1 ) ; i + + ) {
dma_phy + = sizeof ( struct dma_desc ) ;
2016-11-14 18:58:05 +01:00
p - > des3 = cpu_to_le32 ( ( unsigned int ) dma_phy ) ;
2013-03-26 04:43:06 +00:00
p + + ;
}
2016-11-14 18:58:05 +01:00
p - > des3 = cpu_to_le32 ( ( unsigned int ) phy_addr ) ;
2011-10-18 00:01:24 +00:00
}
}
2013-03-26 04:43:10 +00:00
static void stmmac_refill_desc3 ( void * priv_ptr , struct dma_desc * p )
{
2017-04-06 09:49:09 +01:00
struct stmmac_rx_queue * rx_q = ( struct stmmac_rx_queue * ) priv_ptr ;
struct stmmac_priv * priv = rx_q - > priv_data ;
2013-03-26 04:43:10 +00:00
if ( priv - > hwts_rx_en & & ! priv - > extend_desc )
/* NOTE: Device will overwrite des3 with timestamp value if
* 1588 - 2002 time stamping is enabled , hence reinitialize it
* to keep explicit chaining in the descriptor .
*/
2017-04-06 09:49:09 +01:00
p - > des3 = cpu_to_le32 ( ( unsigned int ) ( rx_q - > dma_rx_phy +
( ( ( rx_q - > dirty_rx ) + 1 ) %
2016-11-14 18:58:05 +01:00
DMA_RX_SIZE ) *
sizeof ( struct dma_desc ) ) ) ;
2013-03-26 04:43:10 +00:00
}
static void stmmac_clean_desc3 ( void * priv_ptr , struct dma_desc * p )
{
2017-04-06 09:49:10 +01:00
struct stmmac_tx_queue * tx_q = ( struct stmmac_tx_queue * ) priv_ptr ;
struct stmmac_priv * priv = tx_q - > priv_data ;
unsigned int entry = tx_q - > dirty_tx ;
2013-03-26 04:43:10 +00:00
2017-04-06 09:49:10 +01:00
if ( tx_q - > tx_skbuff_dma [ entry ] . last_segment & & ! priv - > extend_desc & &
2016-02-29 14:27:33 +01:00
priv - > hwts_tx_en )
2013-03-26 04:43:10 +00:00
/* NOTE: Device will overwrite des3 with timestamp value if
* 1588 - 2002 time stamping is enabled , hence reinitialize it
* to keep explicit chaining in the descriptor .
*/
2017-04-06 09:49:10 +01:00
p - > des3 = cpu_to_le32 ( ( unsigned int ) ( ( tx_q - > dma_tx_phy +
( ( tx_q - > dirty_tx + 1 ) % DMA_TX_SIZE ) )
2016-11-14 18:58:05 +01:00
* sizeof ( struct dma_desc ) ) ) ;
2013-03-26 04:43:10 +00:00
}
2014-03-10 13:40:33 +01:00
const struct stmmac_mode_ops chain_mode_ops = {
2013-03-26 04:43:06 +00:00
. init = stmmac_init_dma_chain ,
2011-10-18 00:01:24 +00:00
. is_jumbo_frm = stmmac_is_jumbo_frm ,
. jumbo_frm = stmmac_jumbo_frm ,
2013-03-26 04:43:10 +00:00
. refill_desc3 = stmmac_refill_desc3 ,
. clean_desc3 = stmmac_clean_desc3 ,
2011-10-18 00:01:24 +00:00
} ;