Migrate to DMA coherent functions

Add initial EEH fast recovery support
parent 470a1248
......@@ -126,10 +126,14 @@ static unsigned int irq_stub = 0;
static pci_ers_result_t a24xx_pci_error_detected(struct pci_dev *pdev,
pci_channel_state_t state);
static pci_ers_result_t a24xx_pci_slot_reset(struct pci_dev *pdev);
static pci_ers_result_t a24xx_pci_mmio_enabled(struct pci_dev *pdev);
static void a24xx_pci_resume(struct pci_dev *pdev);
static const struct pci_error_handlers a24xx_err_handler = {
.error_detected = a24xx_pci_error_detected,
.slot_reset = a24xx_pci_slot_reset,
.mmio_enabled = a24xx_pci_mmio_enabled,
.resume = a24xx_pci_resume,
};
static const struct dahdi_echocan_features vpm_ec_features = {
......@@ -2358,7 +2362,8 @@ static int __devinit a24xx_init_one(struct pci_dev *pdev, const struct pci_devic
/* Allocate enough memory for two dahdi chunks, receive and transmit. Each sample uses
8 bits. */
wc_dev->writechunk = pci_alloc_consistent(pdev, ms_per_irq * DAHDI_MAX_CHUNKSIZE * MAX_NUM_CARDS * 2 * 2, &wc_dev->writedma);
wc_dev->dma_buffer_size = ms_per_irq * DAHDI_MAX_CHUNKSIZE * MAX_NUM_CARDS * 2 * 2;
wc_dev->writechunk = dma_alloc_coherent(&pdev->dev, wc_dev->dma_buffer_size, &wc_dev->writedma, GFP_KERNEL);
if (!wc_dev->writechunk) {
printk("opvxa24xx: Unable to allocate DMA-able memory\n");
if (wc_dev->freeregion) {
......@@ -2369,7 +2374,7 @@ static int __devinit a24xx_init_one(struct pci_dev *pdev, const struct pci_devic
}
if(debug) {
printk("opvxa24xx: dma buffer allocated at %p, pci(%p)\n", wc_dev->writechunk, (void *)wc_dev->writedma);
printk("opvxa24xx: dma buffer allocated at %p, pci(%p), size %d bytes\n", wc_dev->writechunk, (void *)wc_dev->writedma, wc_dev->dma_buffer_size);
}
__a24xx_malloc_chunk(wc_dev,ms_per_irq);
......@@ -2381,7 +2386,7 @@ static int __devinit a24xx_init_one(struct pci_dev *pdev, const struct pci_devic
release_mem_region(wc_dev->mem_region, wc_dev->mem_len);
iounmap((void *)wc_dev->mem32);
}
pci_free_consistent(pdev, ms_per_irq * DAHDI_MAX_CHUNKSIZE * MAX_NUM_CARDS * 2 * 2, (void *)wc_dev->writechunk, wc_dev->writedma);
dma_free_coherent(&pdev->dev, wc_dev->dma_buffer_size, (void *)wc_dev->writechunk, wc_dev->writedma);
return -ENOMEM;
}
......@@ -2417,7 +2422,7 @@ static int __devinit a24xx_init_one(struct pci_dev *pdev, const struct pci_devic
release_mem_region(wc_dev->mem_region, wc_dev->mem_len);
iounmap((void *)wc_dev->mem32);
}
pci_free_consistent(pdev, ms_per_irq * DAHDI_MAX_CHUNKSIZE * MAX_NUM_CARDS * 2 * 2, (void *)wc_dev->writechunk, wc_dev->writedma);
dma_free_coherent(&pdev->dev, wc_dev->dma_buffer_size, (void *)wc_dev->writechunk, wc_dev->writedma);
pci_set_drvdata(pdev, NULL);
dahdi_unregister_device(wc->dev.ddev); //Dennis
kfree(wc->dev.ddev->location);
......@@ -2450,7 +2455,7 @@ static int __devinit a24xx_init_one(struct pci_dev *pdev, const struct pci_devic
release_mem_region(wc_dev->mem_region, wc_dev->mem_len);
iounmap((void *)wc_dev->mem32);
}
pci_free_consistent(pdev, ms_per_irq * DAHDI_MAX_CHUNKSIZE * MAX_NUM_CARDS * 2 * 2, (void *)wc_dev->writechunk, wc_dev->writedma);
dma_free_coherent(&pdev->dev, wc_dev->dma_buffer_size, (void *)wc_dev->writechunk, wc_dev->writedma);
pci_set_drvdata(pdev, NULL);
free_wc(wc);
return -EIO;
......@@ -2467,7 +2472,7 @@ static int __devinit a24xx_init_one(struct pci_dev *pdev, const struct pci_devic
release_mem_region(wc_dev->mem_region, wc_dev->mem_len);
iounmap((void *)wc_dev->mem32);
}
pci_free_consistent(pdev, ms_per_irq * DAHDI_MAX_CHUNKSIZE * MAX_NUM_CARDS * 2 * 2, (void *)wc_dev->writechunk, wc_dev->writedma);
dma_free_coherent(&pdev->dev, wc_dev->dma_buffer_size, (void *)wc_dev->writechunk, wc_dev->writedma);
pci_set_drvdata(pdev, NULL);
dahdi_unregister_device(wc->dev.ddev); //Dennis
kfree(wc->dev.ddev->location);
......@@ -2600,7 +2605,7 @@ static void __devexit a24xx_remove_one(struct pci_dev *pdev)
free_irq(pdev->irq, wc);
}
/* Immediately free resources */
pci_free_consistent(pdev, ms_per_irq * DAHDI_MAX_CHUNKSIZE * MAX_NUM_CARDS * 2 * 2, (void *)wc_dev->writechunk, wc_dev->writedma);
dma_free_coherent(&pdev->dev, wc_dev->dma_buffer_size, (void *)wc_dev->writechunk, wc_dev->writedma);
destroy_callerid(wc);
destroy_busydetect(wc);
......@@ -2695,11 +2700,49 @@ static void __exit a24xx_cleanup(void)
static pci_ers_result_t a24xx_pci_error_detected(struct pci_dev *pdev,
pci_channel_state_t state)
{
struct a24xx *wc = pci_get_drvdata(pdev);
struct a24xx_dev *wc_dev = &wc->dev;
if (state == pci_channel_io_perm_failure)
return PCI_ERS_RESULT_DISCONNECT;
return PCI_ERS_RESULT_NEED_RESET;
__opvx_a24xx_disable_interrupts(wc_dev);
__opvx_a24xx_stop_dma(wc_dev);
printk(KERN_WARNING "OpenVox: Non-correctable non-fatal error reported, unfreezing...\n");
return PCI_ERS_RESULT_CAN_RECOVER;
}
/*
* Description: Called when a PCI error fence has been partially cleared,
* only MMIO is reenabled at this point.
*
*/
static pci_ers_result_t a24xx_pci_mmio_enabled(struct pci_dev __maybe_unused *pdev)
{
return PCI_ERS_RESULT_RECOVERED;
}
/*
* Description: Called when a PCI error fence has been cleared and
* the driver is clear to resume normal operations.
*
*/
static void a24xx_pci_resume(struct pci_dev *pdev)
{
struct a24xx *wc = pci_get_drvdata(pdev);
struct a24xx_dev *wc_dev = &wc->dev;
printk(KERN_WARNING "OpenVox: Resuming operations after thaw...\n");
__opvx_a24xx_enable_interrupts(wc_dev);
/* Initialize Write/Buffers to all blank data */
memset((void *)wc_dev->writechunk,0, ms_per_irq * DAHDI_MAX_CHUNKSIZE * MAX_NUM_CARDS * 2 * 2);
__opvx_a24xx_start_dma(wc_dev, wc_dev->writedma);
}
/**
......@@ -2712,7 +2755,7 @@ static pci_ers_result_t a24xx_pci_error_detected(struct pci_dev *pdev,
*/
static pci_ers_result_t a24xx_pci_slot_reset(struct pci_dev *pdev)
{
int rc;
struct pci_device_id ent;
struct a24xx *wc = pci_get_drvdata(pdev);
struct a24xx_dev *wc_dev = &wc->dev;
......@@ -2721,13 +2764,10 @@ static pci_ers_result_t a24xx_pci_slot_reset(struct pci_dev *pdev)
pci_save_state(pdev);
// Ideally we'd completely reinitialize the card here,
// but that will require more invasive changes to the driver.
//
// For now, assume that bad card-side firwmare has "merely" caused
// an invalid DMA operation, and that we can safely resume without
// re-initializing anything...
//a24xx_init_one(pdev, wc_dev->device_id);
// Try to completely reinitialize the card here...
ent = wc_dev->device_id;
a24xx_remove_one(pdev);
a24xx_init_one(pdev, &ent);
return PCI_ERS_RESULT_RECOVERED;
}
......
......@@ -192,6 +192,7 @@ struct a24xx_dev {
unsigned long mem_len; /* Length of 32 bit region */
volatile unsigned long mem32; /* Virtual representation of 32 bit memory area */
int dma_buffer_size;
dma_addr_t readdma;
dma_addr_t writedma;
volatile unsigned char *writechunk; /* Double-word aligned write memory */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment