@ -79,6 +79,8 @@ static const u8 xor_idx_to_field[] = { 1, 4, 5, 6, 7, 0, 1, 2 };
static const u8 pq_idx_to_desc = 0xf8 ;
static const u8 pq_idx_to_field [ ] = { 1 , 4 , 5 , 0 , 1 , 2 , 4 , 5 } ;
static void ioat3_eh ( struct ioat2_dma_chan * ioat ) ;
static dma_addr_t xor_get_src ( struct ioat_raw_descriptor * descs [ 2 ] , int idx )
{
struct ioat_raw_descriptor * raw = descs [ xor_idx_to_desc > > idx & 1 ] ;
@ -347,6 +349,33 @@ static bool desc_has_ext(struct ioat_ring_ent *desc)
return false ;
}
static u64 ioat3_get_current_completion ( struct ioat_chan_common * chan )
{
u64 phys_complete ;
u64 completion ;
completion = * chan - > completion ;
phys_complete = ioat_chansts_to_addr ( completion ) ;
dev_dbg ( to_dev ( chan ) , " %s: phys_complete: %#llx \n " , __func__ ,
( unsigned long long ) phys_complete ) ;
return phys_complete ;
}
static bool ioat3_cleanup_preamble ( struct ioat_chan_common * chan ,
u64 * phys_complete )
{
* phys_complete = ioat3_get_current_completion ( chan ) ;
if ( * phys_complete = = chan - > last_completion )
return false ;
clear_bit ( IOAT_COMPLETION_ACK , & chan - > state ) ;
mod_timer ( & chan - > timer , jiffies + COMPLETION_TIMEOUT ) ;
return true ;
}
/**
* __cleanup - reclaim used descriptors
* @ ioat : channel ( ring ) to clean
@ -365,6 +394,16 @@ static void __cleanup(struct ioat2_dma_chan *ioat, dma_addr_t phys_complete)
dev_dbg ( to_dev ( chan ) , " %s: head: %#x tail: %#x issued: %#x \n " ,
__func__ , ioat - > head , ioat - > tail , ioat - > issued ) ;
/*
* At restart of the channel , the completion address and the
* channel status will be 0 due to starting a new chain . Since
* it ' s new chain and the first descriptor " fails " , there is
* nothing to clean up . We do not want to reap the entire submitted
* chain due to this 0 address value and then BUG .
*/
if ( ! phys_complete )
return ;
active = ioat2_ring_active ( ioat ) ;
for ( i = 0 ; i < active & & ! seen_current ; i + + ) {
struct dma_async_tx_descriptor * tx ;
@ -411,11 +450,22 @@ static void __cleanup(struct ioat2_dma_chan *ioat, dma_addr_t phys_complete)
static void ioat3_cleanup ( struct ioat2_dma_chan * ioat )
{
struct ioat_chan_common * chan = & ioat - > base ;
dma_addr_t phys_complete ;
u64 phys_complete ;
spin_lock_bh ( & chan - > cleanup_lock ) ;
if ( ioat_cleanup_preamble ( chan , & phys_complete ) )
if ( ioat3_cleanup_preamble ( chan , & phys_complete ) )
__cleanup ( ioat , phys_complete ) ;
if ( is_ioat_halted ( * chan - > completion ) ) {
u32 chanerr = readl ( chan - > reg_base + IOAT_CHANERR_OFFSET ) ;
if ( chanerr & IOAT_CHANERR_HANDLE_MASK ) {
mod_timer ( & chan - > timer , jiffies + IDLE_TIMEOUT ) ;
ioat3_eh ( ioat ) ;
}
}
spin_unlock_bh ( & chan - > cleanup_lock ) ;
}
@ -430,15 +480,77 @@ static void ioat3_cleanup_event(unsigned long data)
static void ioat3_restart_channel ( struct ioat2_dma_chan * ioat )
{
struct ioat_chan_common * chan = & ioat - > base ;
dma_addr_t phys_complete ;
u64 phys_complete ;
ioat2_quiesce ( chan , 0 ) ;
if ( ioat_cleanup_preamble ( chan , & phys_complete ) )
if ( ioat3 _cleanup_preamble ( chan , & phys_complete ) )
__cleanup ( ioat , phys_complete ) ;
__ioat2_restart_chan ( ioat ) ;
}
static void ioat3_eh ( struct ioat2_dma_chan * ioat )
{
struct ioat_chan_common * chan = & ioat - > base ;
struct pci_dev * pdev = to_pdev ( chan ) ;
struct ioat_dma_descriptor * hw ;
u64 phys_complete ;
struct ioat_ring_ent * desc ;
u32 err_handled = 0 ;
u32 chanerr_int ;
u32 chanerr ;
/* cleanup so tail points to descriptor that caused the error */
if ( ioat3_cleanup_preamble ( chan , & phys_complete ) )
__cleanup ( ioat , phys_complete ) ;
chanerr = readl ( chan - > reg_base + IOAT_CHANERR_OFFSET ) ;
pci_read_config_dword ( pdev , IOAT_PCI_CHANERR_INT_OFFSET , & chanerr_int ) ;
dev_dbg ( to_dev ( chan ) , " %s: error = %x:%x \n " ,
__func__ , chanerr , chanerr_int ) ;
desc = ioat2_get_ring_ent ( ioat , ioat - > tail ) ;
hw = desc - > hw ;
dump_desc_dbg ( ioat , desc ) ;
switch ( hw - > ctl_f . op ) {
case IOAT_OP_XOR_VAL :
if ( chanerr & IOAT_CHANERR_XOR_P_OR_CRC_ERR ) {
* desc - > result | = SUM_CHECK_P_RESULT ;
err_handled | = IOAT_CHANERR_XOR_P_OR_CRC_ERR ;
}
break ;
case IOAT_OP_PQ_VAL :
if ( chanerr & IOAT_CHANERR_XOR_P_OR_CRC_ERR ) {
* desc - > result | = SUM_CHECK_P_RESULT ;
err_handled | = IOAT_CHANERR_XOR_P_OR_CRC_ERR ;
}
if ( chanerr & IOAT_CHANERR_XOR_Q_ERR ) {
* desc - > result | = SUM_CHECK_Q_RESULT ;
err_handled | = IOAT_CHANERR_XOR_Q_ERR ;
}
break ;
}
/* fault on unhandled error or spurious halt */
if ( chanerr ^ err_handled | | chanerr = = 0 ) {
dev_err ( to_dev ( chan ) , " %s: fatal error (%x:%x) \n " ,
__func__ , chanerr , err_handled ) ;
BUG ( ) ;
}
writel ( chanerr , chan - > reg_base + IOAT_CHANERR_OFFSET ) ;
pci_write_config_dword ( pdev , IOAT_PCI_CHANERR_INT_OFFSET , chanerr_int ) ;
/* mark faulting descriptor as complete */
* chan - > completion = desc - > txd . phys ;
spin_lock_bh ( & ioat - > prep_lock ) ;
ioat3_restart_channel ( ioat ) ;
spin_unlock_bh ( & ioat - > prep_lock ) ;
}
static void check_active ( struct ioat2_dma_chan * ioat )
{
struct ioat_chan_common * chan = & ioat - > base ;
@ -1441,15 +1553,13 @@ int ioat3_dma_probe(struct ioatdma_device *device, int dca)
device - > cleanup_fn = ioat3_cleanup_event ;
device - > timer_fn = ioat3_timer_event ;
# ifdef CONFIG_ASYNC_TX_DISABLE_PQ_VAL_DMA
dma_cap_clear ( DMA_PQ_VAL , dma - > cap_mask ) ;
dma - > device_prep_dma_pq_val = NULL ;
# endif
if ( is_xeon_cb32 ( pdev ) ) {
dma_cap_clear ( DMA_XOR_VAL , dma - > cap_mask ) ;
dma - > device_prep_dma_xor_val = NULL ;
# ifdef CONFIG_ASYNC_TX_DISABLE_XOR_VAL_DMA
dma_cap_clear ( DMA_XOR_VAL , dma - > cap_mask ) ;
dma - > device_prep_dma_xor_val = NULL ;
# endif
dma_cap_clear ( DMA_PQ_VAL , dma - > cap_mask ) ;
dma - > device_prep_dma_pq_val = NULL ;
}
err = ioat_probe ( device ) ;
if ( err )