From 0efe5523894a2677269d56ef5ae2f0f6747240fb Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Tue, 9 Oct 2018 16:57:14 +0200 Subject: [PATCH 1/7] fore200e: simplify fore200e_bus usage There is no need to have a global array of the ops, instead PCI and sbus can have their own instances assigned in *_probe. Also switch to C99 initializers. Signed-off-by: Christoph Hellwig Signed-off-by: David S. Miller --- drivers/atm/fore200e.c | 121 +++++++++++++++++++---------------------- 1 file changed, 56 insertions(+), 65 deletions(-) diff --git a/drivers/atm/fore200e.c b/drivers/atm/fore200e.c index 99a38115b0a8..008bd8541c61 100644 --- a/drivers/atm/fore200e.c +++ b/drivers/atm/fore200e.c @@ -106,7 +106,6 @@ static const struct atmdev_ops fore200e_ops; -static const struct fore200e_bus fore200e_bus[]; static LIST_HEAD(fore200e_boards); @@ -664,9 +663,31 @@ fore200e_pca_proc_read(struct fore200e* fore200e, char *page) pci_dev->bus->number, PCI_SLOT(pci_dev->devfn), PCI_FUNC(pci_dev->devfn)); } +static const struct fore200e_bus fore200e_pci_ops = { + .model_name = "PCA-200E", + .proc_name = "pca200e", + .descr_alignment = 32, + .buffer_alignment = 4, + .status_alignment = 32, + .read = fore200e_pca_read, + .write = fore200e_pca_write, + .dma_map = fore200e_pca_dma_map, + .dma_unmap = fore200e_pca_dma_unmap, + .dma_sync_for_cpu = fore200e_pca_dma_sync_for_cpu, + .dma_sync_for_device = fore200e_pca_dma_sync_for_device, + .dma_chunk_alloc = fore200e_pca_dma_chunk_alloc, + .dma_chunk_free = fore200e_pca_dma_chunk_free, + .configure = fore200e_pca_configure, + .map = fore200e_pca_map, + .reset = fore200e_pca_reset, + .prom_read = fore200e_pca_prom_read, + .unmap = fore200e_pca_unmap, + .irq_check = fore200e_pca_irq_check, + .irq_ack = fore200e_pca_irq_ack, + .proc_read = fore200e_pca_proc_read, +}; #endif /* CONFIG_PCI */ - #ifdef CONFIG_SBUS static u32 fore200e_sba_read(volatile u32 __iomem *addr) @@ -855,8 +876,32 @@ static int fore200e_sba_proc_read(struct fore200e *fore200e, char *page) return sprintf(page, " SBUS slot/device:\t\t%d/'%s'\n", (regs ? regs->which_io : 0), op->dev.of_node->name); } -#endif /* CONFIG_SBUS */ +static const struct fore200e_bus fore200e_sbus_ops = { + .model_name = "SBA-200E", + .proc_name = "sba200e", + .descr_alignment = 32, + .buffer_alignent = 64, + .status_alignment = 32, + .read = fore200e_sba_read, + .write = fore200e_sba_write, + .dma_map = fore200e_sba_dma_map, + .dma_unap = fore200e_sba_dma_unmap, + .dma_sync_for_cpu = fore200e_sba_dma_sync_for_cpu, + .dma_sync_for_device = fore200e_sba_dma_sync_for_device, + .dma_chunk_alloc = fore200e_sba_dma_chunk_alloc, + .dma_chunk_free = fore200e_sba_dma_chunk_free, + .configure = fore200e_sba_configure, + .map = fore200e_sba_map, + .reset = fore200e_sba_reset, + .prom_read = fore200e_sba_prom_read, + .unmap = fore200e_sba_unmap, + .irq_enable = fore200e_sba_irq_enable, + .irq_check = fore200e_sba_irq_check, + .irq_ack = fore200e_sba_irq_ack, + .proc_read = fore200e_sba_proc_read, +}; +#endif /* CONFIG_SBUS */ static void fore200e_tx_irq(struct fore200e* fore200e) @@ -2631,7 +2676,6 @@ static const struct of_device_id fore200e_sba_match[]; static int fore200e_sba_probe(struct platform_device *op) { const struct of_device_id *match; - const struct fore200e_bus *bus; struct fore200e *fore200e; static int index = 0; int err; @@ -2639,18 +2683,17 @@ static int fore200e_sba_probe(struct platform_device *op) match = of_match_device(fore200e_sba_match, &op->dev); if (!match) return -EINVAL; - bus = match->data; fore200e = kzalloc(sizeof(struct fore200e), GFP_KERNEL); if (!fore200e) return -ENOMEM; - fore200e->bus = bus; + fore200e->bus = &fore200e_sbus_ops; fore200e->bus_dev = op; fore200e->irq = op->archdata.irqs[0]; fore200e->phys_base = op->resource[0].start; - sprintf(fore200e->name, "%s-%d", bus->model_name, index); + sprintf(fore200e->name, "SBA-200E-%d", index); err = fore200e_init(fore200e, &op->dev); if (err < 0) { @@ -2678,7 +2721,6 @@ static int fore200e_sba_remove(struct platform_device *op) static const struct of_device_id fore200e_sba_match[] = { { .name = SBA200E_PROM_NAME, - .data = (void *) &fore200e_bus[1], }, {}, }; @@ -2698,7 +2740,6 @@ static struct platform_driver fore200e_sba_driver = { static int fore200e_pca_detect(struct pci_dev *pci_dev, const struct pci_device_id *pci_ent) { - const struct fore200e_bus* bus = (struct fore200e_bus*) pci_ent->driver_data; struct fore200e* fore200e; int err = 0; static int index = 0; @@ -2719,20 +2760,19 @@ static int fore200e_pca_detect(struct pci_dev *pci_dev, goto out_disable; } - fore200e->bus = bus; + fore200e->bus = &fore200e_pci_ops; fore200e->bus_dev = pci_dev; fore200e->irq = pci_dev->irq; fore200e->phys_base = pci_resource_start(pci_dev, 0); - sprintf(fore200e->name, "%s-%d", bus->model_name, index - 1); + sprintf(fore200e->name, "PCA-200E-%d", index - 1); pci_set_master(pci_dev); - printk(FORE200E "device %s found at 0x%lx, IRQ %s\n", - fore200e->bus->model_name, + printk(FORE200E "device PCA-200E found at 0x%lx, IRQ %s\n", fore200e->phys_base, fore200e_irq_itoa(fore200e->irq)); - sprintf(fore200e->name, "%s-%d", bus->model_name, index); + sprintf(fore200e->name, "PCA-200E-%d", index); err = fore200e_init(fore200e, &pci_dev->dev); if (err < 0) { @@ -2767,8 +2807,7 @@ static void fore200e_pca_remove_one(struct pci_dev *pci_dev) static const struct pci_device_id fore200e_pca_tbl[] = { - { PCI_VENDOR_ID_FORE, PCI_DEVICE_ID_FORE_PCA200E, PCI_ANY_ID, PCI_ANY_ID, - 0, 0, (unsigned long) &fore200e_bus[0] }, + { PCI_VENDOR_ID_FORE, PCI_DEVICE_ID_FORE_PCA200E, PCI_ANY_ID, PCI_ANY_ID }, { 0, } }; @@ -3108,8 +3147,7 @@ module_init(fore200e_module_init); module_exit(fore200e_module_cleanup); -static const struct atmdev_ops fore200e_ops = -{ +static const struct atmdev_ops fore200e_ops = { .open = fore200e_open, .close = fore200e_close, .ioctl = fore200e_ioctl, @@ -3121,53 +3159,6 @@ static const struct atmdev_ops fore200e_ops = .owner = THIS_MODULE }; - -static const struct fore200e_bus fore200e_bus[] = { -#ifdef CONFIG_PCI - { "PCA-200E", "pca200e", 32, 4, 32, - fore200e_pca_read, - fore200e_pca_write, - fore200e_pca_dma_map, - fore200e_pca_dma_unmap, - fore200e_pca_dma_sync_for_cpu, - fore200e_pca_dma_sync_for_device, - fore200e_pca_dma_chunk_alloc, - fore200e_pca_dma_chunk_free, - fore200e_pca_configure, - fore200e_pca_map, - fore200e_pca_reset, - fore200e_pca_prom_read, - fore200e_pca_unmap, - NULL, - fore200e_pca_irq_check, - fore200e_pca_irq_ack, - fore200e_pca_proc_read, - }, -#endif -#ifdef CONFIG_SBUS - { "SBA-200E", "sba200e", 32, 64, 32, - fore200e_sba_read, - fore200e_sba_write, - fore200e_sba_dma_map, - fore200e_sba_dma_unmap, - fore200e_sba_dma_sync_for_cpu, - fore200e_sba_dma_sync_for_device, - fore200e_sba_dma_chunk_alloc, - fore200e_sba_dma_chunk_free, - fore200e_sba_configure, - fore200e_sba_map, - fore200e_sba_reset, - fore200e_sba_prom_read, - fore200e_sba_unmap, - fore200e_sba_irq_enable, - fore200e_sba_irq_check, - fore200e_sba_irq_ack, - fore200e_sba_proc_read, - }, -#endif - {} -}; - MODULE_LICENSE("GPL"); #ifdef CONFIG_PCI #ifdef __LITTLE_ENDIAN__ From aff9d262fbf02184f1b79b264f29e9ae0bc1b77b Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Tue, 9 Oct 2018 16:57:15 +0200 Subject: [PATCH 2/7] fore200e: store a struct device in struct fore200e This can be used much better than the untyped void pointer containing either a PCI or platform device. Signed-off-by: Christoph Hellwig Signed-off-by: David S. Miller --- drivers/atm/fore200e.c | 65 ++++++++++++++---------------------------- drivers/atm/fore200e.h | 2 +- 2 files changed, 23 insertions(+), 44 deletions(-) diff --git a/drivers/atm/fore200e.c b/drivers/atm/fore200e.c index 008bd8541c61..0b8d2ad8273d 100644 --- a/drivers/atm/fore200e.c +++ b/drivers/atm/fore200e.c @@ -432,7 +432,7 @@ static void fore200e_pca_write(u32 val, volatile u32 __iomem *addr) static u32 fore200e_pca_dma_map(struct fore200e* fore200e, void* virt_addr, int size, int direction) { - u32 dma_addr = dma_map_single(&((struct pci_dev *) fore200e->bus_dev)->dev, virt_addr, size, direction); + u32 dma_addr = dma_map_single(fore200e->dev, virt_addr, size, direction); DPRINTK(3, "PCI DVMA mapping: virt_addr = 0x%p, size = %d, direction = %d, --> dma_addr = 0x%08x\n", virt_addr, size, direction, dma_addr); @@ -447,7 +447,7 @@ fore200e_pca_dma_unmap(struct fore200e* fore200e, u32 dma_addr, int size, int di DPRINTK(3, "PCI DVMA unmapping: dma_addr = 0x%08x, size = %d, direction = %d\n", dma_addr, size, direction); - dma_unmap_single(&((struct pci_dev *) fore200e->bus_dev)->dev, dma_addr, size, direction); + dma_unmap_single(fore200e->dev, dma_addr, size, direction); } @@ -456,7 +456,7 @@ fore200e_pca_dma_sync_for_cpu(struct fore200e* fore200e, u32 dma_addr, int size, { DPRINTK(3, "PCI DVMA sync: dma_addr = 0x%08x, size = %d, direction = %d\n", dma_addr, size, direction); - dma_sync_single_for_cpu(&((struct pci_dev *) fore200e->bus_dev)->dev, dma_addr, size, direction); + dma_sync_single_for_cpu(fore200e->dev, dma_addr, size, direction); } static void @@ -464,7 +464,7 @@ fore200e_pca_dma_sync_for_device(struct fore200e* fore200e, u32 dma_addr, int si { DPRINTK(3, "PCI DVMA sync: dma_addr = 0x%08x, size = %d, direction = %d\n", dma_addr, size, direction); - dma_sync_single_for_device(&((struct pci_dev *) fore200e->bus_dev)->dev, dma_addr, size, direction); + dma_sync_single_for_device(fore200e->dev, dma_addr, size, direction); } @@ -477,7 +477,7 @@ fore200e_pca_dma_chunk_alloc(struct fore200e* fore200e, struct chunk* chunk, { /* returned chunks are page-aligned */ chunk->alloc_size = size * nbr; - chunk->alloc_addr = dma_alloc_coherent(&((struct pci_dev *) fore200e->bus_dev)->dev, + chunk->alloc_addr = dma_alloc_coherent(fore200e->dev, chunk->alloc_size, &chunk->dma_addr, GFP_KERNEL); @@ -496,7 +496,7 @@ fore200e_pca_dma_chunk_alloc(struct fore200e* fore200e, struct chunk* chunk, static void fore200e_pca_dma_chunk_free(struct fore200e* fore200e, struct chunk* chunk) { - dma_free_coherent(&((struct pci_dev *) fore200e->bus_dev)->dev, + dma_free_coherent(fore200e->dev, chunk->alloc_size, chunk->alloc_addr, chunk->dma_addr); @@ -570,7 +570,7 @@ fore200e_pca_unmap(struct fore200e* fore200e) static int fore200e_pca_configure(struct fore200e *fore200e) { - struct pci_dev* pci_dev = (struct pci_dev*)fore200e->bus_dev; + struct pci_dev *pci_dev = to_pci_dev(fore200e->dev); u8 master_ctrl, latency; DPRINTK(2, "device %s being configured\n", fore200e->name); @@ -657,7 +657,7 @@ fore200e_pca_prom_read(struct fore200e* fore200e, struct prom_data* prom) static int fore200e_pca_proc_read(struct fore200e* fore200e, char *page) { - struct pci_dev* pci_dev = (struct pci_dev*)fore200e->bus_dev; + struct pci_dev *pci_dev = to_pci_dev(fore200e->dev); return sprintf(page, " PCI bus/slot/function:\t%d/%d/%d\n", pci_dev->bus->number, PCI_SLOT(pci_dev->devfn), PCI_FUNC(pci_dev->devfn)); @@ -702,10 +702,9 @@ static void fore200e_sba_write(u32 val, volatile u32 __iomem *addr) static u32 fore200e_sba_dma_map(struct fore200e *fore200e, void* virt_addr, int size, int direction) { - struct platform_device *op = fore200e->bus_dev; u32 dma_addr; - dma_addr = dma_map_single(&op->dev, virt_addr, size, direction); + dma_addr = dma_map_single(fore200e->dev, virt_addr, size, direction); DPRINTK(3, "SBUS DVMA mapping: virt_addr = 0x%p, size = %d, direction = %d --> dma_addr = 0x%08x\n", virt_addr, size, direction, dma_addr); @@ -715,30 +714,24 @@ static u32 fore200e_sba_dma_map(struct fore200e *fore200e, void* virt_addr, int static void fore200e_sba_dma_unmap(struct fore200e *fore200e, u32 dma_addr, int size, int direction) { - struct platform_device *op = fore200e->bus_dev; - DPRINTK(3, "SBUS DVMA unmapping: dma_addr = 0x%08x, size = %d, direction = %d,\n", dma_addr, size, direction); - dma_unmap_single(&op->dev, dma_addr, size, direction); + dma_unmap_single(fore200e->dev, dma_addr, size, direction); } static void fore200e_sba_dma_sync_for_cpu(struct fore200e *fore200e, u32 dma_addr, int size, int direction) { - struct platform_device *op = fore200e->bus_dev; - DPRINTK(3, "SBUS DVMA sync: dma_addr = 0x%08x, size = %d, direction = %d\n", dma_addr, size, direction); - dma_sync_single_for_cpu(&op->dev, dma_addr, size, direction); + dma_sync_single_for_cpu(fore200e->dev, dma_addr, size, direction); } static void fore200e_sba_dma_sync_for_device(struct fore200e *fore200e, u32 dma_addr, int size, int direction) { - struct platform_device *op = fore200e->bus_dev; - DPRINTK(3, "SBUS DVMA sync: dma_addr = 0x%08x, size = %d, direction = %d\n", dma_addr, size, direction); - dma_sync_single_for_device(&op->dev, dma_addr, size, direction); + dma_sync_single_for_device(fore200e->dev, dma_addr, size, direction); } /* Allocate a DVMA consistent chunk of memory intended to act as a communication mechanism @@ -747,12 +740,10 @@ static void fore200e_sba_dma_sync_for_device(struct fore200e *fore200e, u32 dma_ static int fore200e_sba_dma_chunk_alloc(struct fore200e *fore200e, struct chunk *chunk, int size, int nbr, int alignment) { - struct platform_device *op = fore200e->bus_dev; - chunk->alloc_size = chunk->align_size = size * nbr; /* returned chunks are page-aligned */ - chunk->alloc_addr = dma_alloc_coherent(&op->dev, chunk->alloc_size, + chunk->alloc_addr = dma_alloc_coherent(fore200e->dev, chunk->alloc_size, &chunk->dma_addr, GFP_ATOMIC); if ((chunk->alloc_addr == NULL) || (chunk->dma_addr == 0)) @@ -766,9 +757,7 @@ static int fore200e_sba_dma_chunk_alloc(struct fore200e *fore200e, struct chunk /* free a DVMA consistent chunk of memory */ static void fore200e_sba_dma_chunk_free(struct fore200e *fore200e, struct chunk *chunk) { - struct platform_device *op = fore200e->bus_dev; - - dma_free_coherent(&op->dev, chunk->alloc_size, + dma_free_coherent(fore200e->dev, chunk->alloc_size, chunk->alloc_addr, chunk->dma_addr); } @@ -798,7 +787,7 @@ static void fore200e_sba_reset(struct fore200e *fore200e) static int __init fore200e_sba_map(struct fore200e *fore200e) { - struct platform_device *op = fore200e->bus_dev; + struct platform_device *op = to_platform_device(fore200e->dev); unsigned int bursts; /* gain access to the SBA specific registers */ @@ -828,7 +817,7 @@ static int __init fore200e_sba_map(struct fore200e *fore200e) static void fore200e_sba_unmap(struct fore200e *fore200e) { - struct platform_device *op = fore200e->bus_dev; + struct platform_device *op = to_platform_device(fore200e->dev); of_iounmap(&op->resource[0], fore200e->regs.sba.hcr, SBA200E_HCR_LENGTH); of_iounmap(&op->resource[1], fore200e->regs.sba.bsr, SBA200E_BSR_LENGTH); @@ -844,7 +833,7 @@ static int __init fore200e_sba_configure(struct fore200e *fore200e) static int __init fore200e_sba_prom_read(struct fore200e *fore200e, struct prom_data *prom) { - struct platform_device *op = fore200e->bus_dev; + struct platform_device *op = to_platform_device(fore200e->dev); const u8 *prop; int len; @@ -868,7 +857,7 @@ static int __init fore200e_sba_prom_read(struct fore200e *fore200e, struct prom_ static int fore200e_sba_proc_read(struct fore200e *fore200e, char *page) { - struct platform_device *op = fore200e->bus_dev; + struct platform_device *op = to_platform_device(fore200e->dev); const struct linux_prom_registers *regs; regs = of_get_property(op->dev.of_node, "reg", NULL); @@ -2532,25 +2521,15 @@ static void fore200e_monitor_puts(struct fore200e *fore200e, char *str) static int fore200e_load_and_start_fw(struct fore200e *fore200e) { const struct firmware *firmware; - struct device *device; const struct fw_header *fw_header; const __le32 *fw_data; u32 fw_size; u32 __iomem *load_addr; char buf[48]; - int err = -ENODEV; - - if (strcmp(fore200e->bus->model_name, "PCA-200E") == 0) - device = &((struct pci_dev *) fore200e->bus_dev)->dev; -#ifdef CONFIG_SBUS - else if (strcmp(fore200e->bus->model_name, "SBA-200E") == 0) - device = &((struct platform_device *) fore200e->bus_dev)->dev; -#endif - else - return err; + int err; sprintf(buf, "%s%s", fore200e->bus->proc_name, FW_EXT); - if ((err = request_firmware(&firmware, buf, device)) < 0) { + if ((err = request_firmware(&firmware, buf, fore200e->dev)) < 0) { printk(FORE200E "problem loading firmware image %s\n", fore200e->bus->model_name); return err; } @@ -2689,7 +2668,7 @@ static int fore200e_sba_probe(struct platform_device *op) return -ENOMEM; fore200e->bus = &fore200e_sbus_ops; - fore200e->bus_dev = op; + fore200e->dev = &op->dev; fore200e->irq = op->archdata.irqs[0]; fore200e->phys_base = op->resource[0].start; @@ -2761,7 +2740,7 @@ static int fore200e_pca_detect(struct pci_dev *pci_dev, } fore200e->bus = &fore200e_pci_ops; - fore200e->bus_dev = pci_dev; + fore200e->dev = &pci_dev->dev; fore200e->irq = pci_dev->irq; fore200e->phys_base = pci_resource_start(pci_dev, 0); diff --git a/drivers/atm/fore200e.h b/drivers/atm/fore200e.h index c8a02c8fba15..c8c6ea818ffc 100644 --- a/drivers/atm/fore200e.h +++ b/drivers/atm/fore200e.h @@ -844,7 +844,7 @@ typedef struct fore200e { enum fore200e_state state; /* device state */ char name[16]; /* device name */ - void* bus_dev; /* bus-specific kernel data */ + struct device *dev; int irq; /* irq number */ unsigned long phys_base; /* physical base address */ void __iomem * virt_base; /* virtual base address */ From 8b08adbd87a66c7844481efa70e061c9efae277b Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Tue, 9 Oct 2018 16:57:16 +0200 Subject: [PATCH 3/7] fore200e: remove the align_size field of struct chunk There is no need for this field, as the only user of it can just use the local size variable instead. Signed-off-by: Christoph Hellwig Signed-off-by: David S. Miller --- drivers/atm/fore200e.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/atm/fore200e.c b/drivers/atm/fore200e.c index 0b8d2ad8273d..05951550abb8 100644 --- a/drivers/atm/fore200e.c +++ b/drivers/atm/fore200e.c @@ -182,7 +182,6 @@ fore200e_chunk_alloc(struct fore200e* fore200e, struct chunk* chunk, int size, i alignment = 0; chunk->alloc_size = size + alignment; - chunk->align_size = size; chunk->direction = direction; chunk->alloc_addr = kzalloc(chunk->alloc_size, GFP_KERNEL | GFP_DMA); @@ -194,7 +193,7 @@ fore200e_chunk_alloc(struct fore200e* fore200e, struct chunk* chunk, int size, i chunk->align_addr = chunk->alloc_addr + offset; - chunk->dma_addr = fore200e->bus->dma_map(fore200e, chunk->align_addr, chunk->align_size, direction); + chunk->dma_addr = fore200e->bus->dma_map(fore200e, chunk->align_addr, size, direction); return 0; } @@ -740,7 +739,7 @@ static void fore200e_sba_dma_sync_for_device(struct fore200e *fore200e, u32 dma_ static int fore200e_sba_dma_chunk_alloc(struct fore200e *fore200e, struct chunk *chunk, int size, int nbr, int alignment) { - chunk->alloc_size = chunk->align_size = size * nbr; + chunk->alloc_size = size * nbr; /* returned chunks are page-aligned */ chunk->alloc_addr = dma_alloc_coherent(fore200e->dev, chunk->alloc_size, From f3fadcb5644aa94c8197f1699798d95baa5d59a8 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Tue, 9 Oct 2018 16:57:17 +0200 Subject: [PATCH 4/7] fore200e: devirtualize dma mapping calls There is no need for an indirection before calling the dma mapping routines now that we store a struct device in struct fore200e. Signed-off-by: Christoph Hellwig Signed-off-by: David S. Miller --- drivers/atm/fore200e.c | 112 +++++++---------------------------------- drivers/atm/fore200e.h | 4 -- 2 files changed, 17 insertions(+), 99 deletions(-) diff --git a/drivers/atm/fore200e.c b/drivers/atm/fore200e.c index 05951550abb8..beeb71088560 100644 --- a/drivers/atm/fore200e.c +++ b/drivers/atm/fore200e.c @@ -193,8 +193,8 @@ fore200e_chunk_alloc(struct fore200e* fore200e, struct chunk* chunk, int size, i chunk->align_addr = chunk->alloc_addr + offset; - chunk->dma_addr = fore200e->bus->dma_map(fore200e, chunk->align_addr, size, direction); - + chunk->dma_addr = dma_map_single(fore200e->dev, chunk->align_addr, + size, direction); return 0; } @@ -204,8 +204,8 @@ fore200e_chunk_alloc(struct fore200e* fore200e, struct chunk* chunk, int size, i static void fore200e_chunk_free(struct fore200e* fore200e, struct chunk* chunk) { - fore200e->bus->dma_unmap(fore200e, chunk->dma_addr, chunk->dma_size, chunk->direction); - + dma_unmap_single(fore200e->dev, chunk->dma_addr, chunk->dma_size, + chunk->direction); kfree(chunk->alloc_addr); } @@ -427,46 +427,6 @@ static void fore200e_pca_write(u32 val, volatile u32 __iomem *addr) writel(cpu_to_le32(val), addr); } - -static u32 -fore200e_pca_dma_map(struct fore200e* fore200e, void* virt_addr, int size, int direction) -{ - u32 dma_addr = dma_map_single(fore200e->dev, virt_addr, size, direction); - - DPRINTK(3, "PCI DVMA mapping: virt_addr = 0x%p, size = %d, direction = %d, --> dma_addr = 0x%08x\n", - virt_addr, size, direction, dma_addr); - - return dma_addr; -} - - -static void -fore200e_pca_dma_unmap(struct fore200e* fore200e, u32 dma_addr, int size, int direction) -{ - DPRINTK(3, "PCI DVMA unmapping: dma_addr = 0x%08x, size = %d, direction = %d\n", - dma_addr, size, direction); - - dma_unmap_single(fore200e->dev, dma_addr, size, direction); -} - - -static void -fore200e_pca_dma_sync_for_cpu(struct fore200e* fore200e, u32 dma_addr, int size, int direction) -{ - DPRINTK(3, "PCI DVMA sync: dma_addr = 0x%08x, size = %d, direction = %d\n", dma_addr, size, direction); - - dma_sync_single_for_cpu(fore200e->dev, dma_addr, size, direction); -} - -static void -fore200e_pca_dma_sync_for_device(struct fore200e* fore200e, u32 dma_addr, int size, int direction) -{ - DPRINTK(3, "PCI DVMA sync: dma_addr = 0x%08x, size = %d, direction = %d\n", dma_addr, size, direction); - - dma_sync_single_for_device(fore200e->dev, dma_addr, size, direction); -} - - /* allocate a DMA consistent chunk of memory intended to act as a communication mechanism (to hold descriptors, status, queues, etc.) shared by the driver and the adapter */ @@ -621,7 +581,8 @@ fore200e_pca_prom_read(struct fore200e* fore200e, struct prom_data* prom) opcode.opcode = OPCODE_GET_PROM; opcode.pad = 0; - prom_dma = fore200e->bus->dma_map(fore200e, prom, sizeof(struct prom_data), DMA_FROM_DEVICE); + prom_dma = dma_map_single(fore200e->dev, prom, sizeof(struct prom_data), + DMA_FROM_DEVICE); fore200e->bus->write(prom_dma, &entry->cp_entry->cmd.prom_block.prom_haddr); @@ -633,7 +594,7 @@ fore200e_pca_prom_read(struct fore200e* fore200e, struct prom_data* prom) *entry->status = STATUS_FREE; - fore200e->bus->dma_unmap(fore200e, prom_dma, sizeof(struct prom_data), DMA_FROM_DEVICE); + dma_unmap_single(fore200e->dev, prom_dma, sizeof(struct prom_data), DMA_FROM_DEVICE); if (ok == 0) { printk(FORE200E "unable to get PROM data from device %s\n", fore200e->name); @@ -670,10 +631,6 @@ static const struct fore200e_bus fore200e_pci_ops = { .status_alignment = 32, .read = fore200e_pca_read, .write = fore200e_pca_write, - .dma_map = fore200e_pca_dma_map, - .dma_unmap = fore200e_pca_dma_unmap, - .dma_sync_for_cpu = fore200e_pca_dma_sync_for_cpu, - .dma_sync_for_device = fore200e_pca_dma_sync_for_device, .dma_chunk_alloc = fore200e_pca_dma_chunk_alloc, .dma_chunk_free = fore200e_pca_dma_chunk_free, .configure = fore200e_pca_configure, @@ -699,40 +656,6 @@ static void fore200e_sba_write(u32 val, volatile u32 __iomem *addr) sbus_writel(val, addr); } -static u32 fore200e_sba_dma_map(struct fore200e *fore200e, void* virt_addr, int size, int direction) -{ - u32 dma_addr; - - dma_addr = dma_map_single(fore200e->dev, virt_addr, size, direction); - - DPRINTK(3, "SBUS DVMA mapping: virt_addr = 0x%p, size = %d, direction = %d --> dma_addr = 0x%08x\n", - virt_addr, size, direction, dma_addr); - - return dma_addr; -} - -static void fore200e_sba_dma_unmap(struct fore200e *fore200e, u32 dma_addr, int size, int direction) -{ - DPRINTK(3, "SBUS DVMA unmapping: dma_addr = 0x%08x, size = %d, direction = %d,\n", - dma_addr, size, direction); - - dma_unmap_single(fore200e->dev, dma_addr, size, direction); -} - -static void fore200e_sba_dma_sync_for_cpu(struct fore200e *fore200e, u32 dma_addr, int size, int direction) -{ - DPRINTK(3, "SBUS DVMA sync: dma_addr = 0x%08x, size = %d, direction = %d\n", dma_addr, size, direction); - - dma_sync_single_for_cpu(fore200e->dev, dma_addr, size, direction); -} - -static void fore200e_sba_dma_sync_for_device(struct fore200e *fore200e, u32 dma_addr, int size, int direction) -{ - DPRINTK(3, "SBUS DVMA sync: dma_addr = 0x%08x, size = %d, direction = %d\n", dma_addr, size, direction); - - dma_sync_single_for_device(fore200e->dev, dma_addr, size, direction); -} - /* Allocate a DVMA consistent chunk of memory intended to act as a communication mechanism * (to hold descriptors, status, queues, etc.) shared by the driver and the adapter. */ @@ -873,10 +796,6 @@ static const struct fore200e_bus fore200e_sbus_ops = { .status_alignment = 32, .read = fore200e_sba_read, .write = fore200e_sba_write, - .dma_map = fore200e_sba_dma_map, - .dma_unap = fore200e_sba_dma_unmap, - .dma_sync_for_cpu = fore200e_sba_dma_sync_for_cpu, - .dma_sync_for_device = fore200e_sba_dma_sync_for_device, .dma_chunk_alloc = fore200e_sba_dma_chunk_alloc, .dma_chunk_free = fore200e_sba_dma_chunk_free, .configure = fore200e_sba_configure, @@ -917,7 +836,7 @@ fore200e_tx_irq(struct fore200e* fore200e) kfree(entry->data); /* remove DMA mapping */ - fore200e->bus->dma_unmap(fore200e, entry->tpd->tsd[ 0 ].buffer, entry->tpd->tsd[ 0 ].length, + dma_unmap_single(fore200e->dev, entry->tpd->tsd[ 0 ].buffer, entry->tpd->tsd[ 0 ].length, DMA_TO_DEVICE); vc_map = entry->vc_map; @@ -1138,12 +1057,14 @@ fore200e_push_rpd(struct fore200e* fore200e, struct atm_vcc* vcc, struct rpd* rp buffer = FORE200E_HDL2BUF(rpd->rsd[ i ].handle); /* Make device DMA transfer visible to CPU. */ - fore200e->bus->dma_sync_for_cpu(fore200e, buffer->data.dma_addr, rpd->rsd[ i ].length, DMA_FROM_DEVICE); + dma_sync_single_for_cpu(fore200e->dev, buffer->data.dma_addr, + rpd->rsd[i].length, DMA_FROM_DEVICE); skb_put_data(skb, buffer->data.align_addr, rpd->rsd[i].length); /* Now let the device get at it again. */ - fore200e->bus->dma_sync_for_device(fore200e, buffer->data.dma_addr, rpd->rsd[ i ].length, DMA_FROM_DEVICE); + dma_sync_single_for_device(fore200e->dev, buffer->data.dma_addr, + rpd->rsd[i].length, DMA_FROM_DEVICE); } DPRINTK(3, "rx skb: len = %d, truesize = %d\n", skb->len, skb->truesize); @@ -1712,7 +1633,8 @@ fore200e_send(struct atm_vcc *vcc, struct sk_buff *skb) entry->data = tx_copy ? data : NULL; tpd = entry->tpd; - tpd->tsd[ 0 ].buffer = fore200e->bus->dma_map(fore200e, data, tx_len, DMA_TO_DEVICE); + tpd->tsd[ 0 ].buffer = dma_map_single(fore200e->dev, data, tx_len, + DMA_TO_DEVICE); tpd->tsd[ 0 ].length = tx_len; FORE200E_NEXT_ENTRY(txq->head, QUEUE_SIZE_TX); @@ -1785,8 +1707,8 @@ fore200e_getstats(struct fore200e* fore200e) return -ENOMEM; } - stats_dma_addr = fore200e->bus->dma_map(fore200e, fore200e->stats, - sizeof(struct stats), DMA_FROM_DEVICE); + stats_dma_addr = dma_map_single(fore200e->dev, fore200e->stats, + sizeof(struct stats), DMA_FROM_DEVICE); FORE200E_NEXT_ENTRY(cmdq->head, QUEUE_SIZE_CMD); @@ -1803,7 +1725,7 @@ fore200e_getstats(struct fore200e* fore200e) *entry->status = STATUS_FREE; - fore200e->bus->dma_unmap(fore200e, stats_dma_addr, sizeof(struct stats), DMA_FROM_DEVICE); + dma_unmap_single(fore200e->dev, stats_dma_addr, sizeof(struct stats), DMA_FROM_DEVICE); if (ok == 0) { printk(FORE200E "unable to get statistics from device %s\n", fore200e->name); diff --git a/drivers/atm/fore200e.h b/drivers/atm/fore200e.h index c8c6ea818ffc..f62fc9b85db0 100644 --- a/drivers/atm/fore200e.h +++ b/drivers/atm/fore200e.h @@ -805,10 +805,6 @@ typedef struct fore200e_bus { int status_alignment; /* status words DMA alignment requirement */ u32 (*read)(volatile u32 __iomem *); void (*write)(u32, volatile u32 __iomem *); - u32 (*dma_map)(struct fore200e*, void*, int, int); - void (*dma_unmap)(struct fore200e*, u32, int, int); - void (*dma_sync_for_cpu)(struct fore200e*, u32, int, int); - void (*dma_sync_for_device)(struct fore200e*, u32, int, int); int (*dma_chunk_alloc)(struct fore200e*, struct chunk*, int, int, int); void (*dma_chunk_free)(struct fore200e*, struct chunk*); int (*configure)(struct fore200e*); From 1335d6fd65da11e9576c0a5dc6b8d65aadbfc9b6 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Tue, 9 Oct 2018 16:57:18 +0200 Subject: [PATCH 5/7] fore200e: devirtualize dma alloc calls There is no need for an indirection before calling the dma alloc routines now that we store a struct device in struct fore200e. Also remove the pointless GFP_ATOMIC for the sbus case, and fix the up the error handling by removing the 0 dma_addr test - some iommus can return 0 as a perfectly valid bus address. Signed-off-by: Christoph Hellwig Signed-off-by: David S. Miller --- drivers/atm/fore200e.c | 128 +++++++++++++++-------------------------- drivers/atm/fore200e.h | 2 - 2 files changed, 45 insertions(+), 85 deletions(-) diff --git a/drivers/atm/fore200e.c b/drivers/atm/fore200e.c index beeb71088560..86be269500a9 100644 --- a/drivers/atm/fore200e.c +++ b/drivers/atm/fore200e.c @@ -209,6 +209,34 @@ fore200e_chunk_free(struct fore200e* fore200e, struct chunk* chunk) kfree(chunk->alloc_addr); } +/* + * Allocate a DMA consistent chunk of memory intended to act as a communication + * mechanism (to hold descriptors, status, queues, etc.) shared by the driver + * and the adapter. + */ +static int +fore200e_dma_chunk_alloc(struct fore200e *fore200e, struct chunk *chunk, + int size, int nbr, int alignment) +{ + /* returned chunks are page-aligned */ + chunk->alloc_size = size * nbr; + chunk->alloc_addr = dma_alloc_coherent(fore200e->dev, chunk->alloc_size, + &chunk->dma_addr, GFP_KERNEL); + if (!chunk->alloc_addr) + return -ENOMEM; + chunk->align_addr = chunk->alloc_addr; + return 0; +} + +/* + * Free a DMA consistent chunk of memory. + */ +static void +fore200e_dma_chunk_free(struct fore200e* fore200e, struct chunk* chunk) +{ + dma_free_coherent(fore200e->dev, chunk->alloc_size, chunk->alloc_addr, + chunk->dma_addr); +} static void fore200e_spin(int msecs) @@ -301,10 +329,10 @@ fore200e_uninit_bs_queue(struct fore200e* fore200e) struct chunk* rbd_block = &fore200e->host_bsq[ scheme ][ magn ].rbd_block; if (status->alloc_addr) - fore200e->bus->dma_chunk_free(fore200e, status); + fore200e_dma_chunk_free(fore200e, status); if (rbd_block->alloc_addr) - fore200e->bus->dma_chunk_free(fore200e, rbd_block); + fore200e_dma_chunk_free(fore200e, rbd_block); } } } @@ -370,17 +398,17 @@ fore200e_shutdown(struct fore200e* fore200e) /* fall through */ case FORE200E_STATE_INIT_RXQ: - fore200e->bus->dma_chunk_free(fore200e, &fore200e->host_rxq.status); - fore200e->bus->dma_chunk_free(fore200e, &fore200e->host_rxq.rpd); + fore200e_dma_chunk_free(fore200e, &fore200e->host_rxq.status); + fore200e_dma_chunk_free(fore200e, &fore200e->host_rxq.rpd); /* fall through */ case FORE200E_STATE_INIT_TXQ: - fore200e->bus->dma_chunk_free(fore200e, &fore200e->host_txq.status); - fore200e->bus->dma_chunk_free(fore200e, &fore200e->host_txq.tpd); + fore200e_dma_chunk_free(fore200e, &fore200e->host_txq.status); + fore200e_dma_chunk_free(fore200e, &fore200e->host_txq.tpd); /* fall through */ case FORE200E_STATE_INIT_CMDQ: - fore200e->bus->dma_chunk_free(fore200e, &fore200e->host_cmdq.status); + fore200e_dma_chunk_free(fore200e, &fore200e->host_cmdq.status); /* fall through */ case FORE200E_STATE_INITIALIZE: @@ -427,41 +455,6 @@ static void fore200e_pca_write(u32 val, volatile u32 __iomem *addr) writel(cpu_to_le32(val), addr); } -/* allocate a DMA consistent chunk of memory intended to act as a communication mechanism - (to hold descriptors, status, queues, etc.) shared by the driver and the adapter */ - -static int -fore200e_pca_dma_chunk_alloc(struct fore200e* fore200e, struct chunk* chunk, - int size, int nbr, int alignment) -{ - /* returned chunks are page-aligned */ - chunk->alloc_size = size * nbr; - chunk->alloc_addr = dma_alloc_coherent(fore200e->dev, - chunk->alloc_size, - &chunk->dma_addr, - GFP_KERNEL); - - if ((chunk->alloc_addr == NULL) || (chunk->dma_addr == 0)) - return -ENOMEM; - - chunk->align_addr = chunk->alloc_addr; - - return 0; -} - - -/* free a DMA consistent chunk of memory */ - -static void -fore200e_pca_dma_chunk_free(struct fore200e* fore200e, struct chunk* chunk) -{ - dma_free_coherent(fore200e->dev, - chunk->alloc_size, - chunk->alloc_addr, - chunk->dma_addr); -} - - static int fore200e_pca_irq_check(struct fore200e* fore200e) { @@ -631,8 +624,6 @@ static const struct fore200e_bus fore200e_pci_ops = { .status_alignment = 32, .read = fore200e_pca_read, .write = fore200e_pca_write, - .dma_chunk_alloc = fore200e_pca_dma_chunk_alloc, - .dma_chunk_free = fore200e_pca_dma_chunk_free, .configure = fore200e_pca_configure, .map = fore200e_pca_map, .reset = fore200e_pca_reset, @@ -656,33 +647,6 @@ static void fore200e_sba_write(u32 val, volatile u32 __iomem *addr) sbus_writel(val, addr); } -/* Allocate a DVMA consistent chunk of memory intended to act as a communication mechanism - * (to hold descriptors, status, queues, etc.) shared by the driver and the adapter. - */ -static int fore200e_sba_dma_chunk_alloc(struct fore200e *fore200e, struct chunk *chunk, - int size, int nbr, int alignment) -{ - chunk->alloc_size = size * nbr; - - /* returned chunks are page-aligned */ - chunk->alloc_addr = dma_alloc_coherent(fore200e->dev, chunk->alloc_size, - &chunk->dma_addr, GFP_ATOMIC); - - if ((chunk->alloc_addr == NULL) || (chunk->dma_addr == 0)) - return -ENOMEM; - - chunk->align_addr = chunk->alloc_addr; - - return 0; -} - -/* free a DVMA consistent chunk of memory */ -static void fore200e_sba_dma_chunk_free(struct fore200e *fore200e, struct chunk *chunk) -{ - dma_free_coherent(fore200e->dev, chunk->alloc_size, - chunk->alloc_addr, chunk->dma_addr); -} - static void fore200e_sba_irq_enable(struct fore200e *fore200e) { u32 hcr = fore200e->bus->read(fore200e->regs.sba.hcr) & SBA200E_HCR_STICKY; @@ -796,8 +760,6 @@ static const struct fore200e_bus fore200e_sbus_ops = { .status_alignment = 32, .read = fore200e_sba_read, .write = fore200e_sba_write, - .dma_chunk_alloc = fore200e_sba_dma_chunk_alloc, - .dma_chunk_free = fore200e_sba_dma_chunk_free, .configure = fore200e_sba_configure, .map = fore200e_sba_map, .reset = fore200e_sba_reset, @@ -2111,7 +2073,7 @@ static int fore200e_init_bs_queue(struct fore200e *fore200e) bsq = &fore200e->host_bsq[ scheme ][ magn ]; /* allocate and align the array of status words */ - if (fore200e->bus->dma_chunk_alloc(fore200e, + if (fore200e_dma_chunk_alloc(fore200e, &bsq->status, sizeof(enum status), QUEUE_SIZE_BS, @@ -2120,13 +2082,13 @@ static int fore200e_init_bs_queue(struct fore200e *fore200e) } /* allocate and align the array of receive buffer descriptors */ - if (fore200e->bus->dma_chunk_alloc(fore200e, + if (fore200e_dma_chunk_alloc(fore200e, &bsq->rbd_block, sizeof(struct rbd_block), QUEUE_SIZE_BS, fore200e->bus->descr_alignment) < 0) { - fore200e->bus->dma_chunk_free(fore200e, &bsq->status); + fore200e_dma_chunk_free(fore200e, &bsq->status); return -ENOMEM; } @@ -2167,7 +2129,7 @@ static int fore200e_init_rx_queue(struct fore200e *fore200e) DPRINTK(2, "receive queue is being initialized\n"); /* allocate and align the array of status words */ - if (fore200e->bus->dma_chunk_alloc(fore200e, + if (fore200e_dma_chunk_alloc(fore200e, &rxq->status, sizeof(enum status), QUEUE_SIZE_RX, @@ -2176,13 +2138,13 @@ static int fore200e_init_rx_queue(struct fore200e *fore200e) } /* allocate and align the array of receive PDU descriptors */ - if (fore200e->bus->dma_chunk_alloc(fore200e, + if (fore200e_dma_chunk_alloc(fore200e, &rxq->rpd, sizeof(struct rpd), QUEUE_SIZE_RX, fore200e->bus->descr_alignment) < 0) { - fore200e->bus->dma_chunk_free(fore200e, &rxq->status); + fore200e_dma_chunk_free(fore200e, &rxq->status); return -ENOMEM; } @@ -2226,7 +2188,7 @@ static int fore200e_init_tx_queue(struct fore200e *fore200e) DPRINTK(2, "transmit queue is being initialized\n"); /* allocate and align the array of status words */ - if (fore200e->bus->dma_chunk_alloc(fore200e, + if (fore200e_dma_chunk_alloc(fore200e, &txq->status, sizeof(enum status), QUEUE_SIZE_TX, @@ -2235,13 +2197,13 @@ static int fore200e_init_tx_queue(struct fore200e *fore200e) } /* allocate and align the array of transmit PDU descriptors */ - if (fore200e->bus->dma_chunk_alloc(fore200e, + if (fore200e_dma_chunk_alloc(fore200e, &txq->tpd, sizeof(struct tpd), QUEUE_SIZE_TX, fore200e->bus->descr_alignment) < 0) { - fore200e->bus->dma_chunk_free(fore200e, &txq->status); + fore200e_dma_chunk_free(fore200e, &txq->status); return -ENOMEM; } @@ -2288,7 +2250,7 @@ static int fore200e_init_cmd_queue(struct fore200e *fore200e) DPRINTK(2, "command queue is being initialized\n"); /* allocate and align the array of status words */ - if (fore200e->bus->dma_chunk_alloc(fore200e, + if (fore200e_dma_chunk_alloc(fore200e, &cmdq->status, sizeof(enum status), QUEUE_SIZE_CMD, diff --git a/drivers/atm/fore200e.h b/drivers/atm/fore200e.h index f62fc9b85db0..caf0ea6a328a 100644 --- a/drivers/atm/fore200e.h +++ b/drivers/atm/fore200e.h @@ -805,8 +805,6 @@ typedef struct fore200e_bus { int status_alignment; /* status words DMA alignment requirement */ u32 (*read)(volatile u32 __iomem *); void (*write)(u32, volatile u32 __iomem *); - int (*dma_chunk_alloc)(struct fore200e*, struct chunk*, int, int, int); - void (*dma_chunk_free)(struct fore200e*, struct chunk*); int (*configure)(struct fore200e*); int (*map)(struct fore200e*); void (*reset)(struct fore200e*); From 0e21b2258a0f8ab5537387b3f1a43b672ce62670 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Tue, 9 Oct 2018 16:57:19 +0200 Subject: [PATCH 6/7] fore200e: don't use GFP_DMA The driver properly uses the DMA mapping API, so it should not pointlessly dip into the GFP_DMA pool, which is only 16MB on x86. Signed-off-by: Christoph Hellwig Signed-off-by: David S. Miller --- drivers/atm/fore200e.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/atm/fore200e.c b/drivers/atm/fore200e.c index 86be269500a9..7eda1a8c3d8c 100644 --- a/drivers/atm/fore200e.c +++ b/drivers/atm/fore200e.c @@ -184,7 +184,7 @@ fore200e_chunk_alloc(struct fore200e* fore200e, struct chunk* chunk, int size, i chunk->alloc_size = size + alignment; chunk->direction = direction; - chunk->alloc_addr = kzalloc(chunk->alloc_size, GFP_KERNEL | GFP_DMA); + chunk->alloc_addr = kzalloc(chunk->alloc_size, GFP_KERNEL); if (chunk->alloc_addr == NULL) return -ENOMEM; @@ -1527,7 +1527,7 @@ fore200e_send(struct atm_vcc *vcc, struct sk_buff *skb) } if (tx_copy) { - data = kmalloc(tx_len, GFP_ATOMIC | GFP_DMA); + data = kmalloc(tx_len, GFP_ATOMIC); if (data == NULL) { if (vcc->pop) { vcc->pop(vcc, skb); @@ -1664,7 +1664,7 @@ fore200e_getstats(struct fore200e* fore200e) u32 stats_dma_addr; if (fore200e->stats == NULL) { - fore200e->stats = kzalloc(sizeof(struct stats), GFP_KERNEL | GFP_DMA); + fore200e->stats = kzalloc(sizeof(struct stats), GFP_KERNEL); if (fore200e->stats == NULL) return -ENOMEM; } @@ -1966,7 +1966,7 @@ static int fore200e_irq_request(struct fore200e *fore200e) static int fore200e_get_esi(struct fore200e *fore200e) { - struct prom_data* prom = kzalloc(sizeof(struct prom_data), GFP_KERNEL | GFP_DMA); + struct prom_data* prom = kzalloc(sizeof(struct prom_data), GFP_KERNEL); int ok, i; if (!prom) From 1d9d8be91788416d17862ec5a30fff33281ddef6 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Tue, 9 Oct 2018 16:57:20 +0200 Subject: [PATCH 7/7] fore200e: check for dma mapping failures The driver was lacking any handling for failures from the DMA mapping routines. With an iommu or swiotlb this can be fatal. Signed-off-by: Christoph Hellwig Signed-off-by: David S. Miller --- drivers/atm/fore200e.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/drivers/atm/fore200e.c b/drivers/atm/fore200e.c index 7eda1a8c3d8c..2b5dc8fe1d85 100644 --- a/drivers/atm/fore200e.c +++ b/drivers/atm/fore200e.c @@ -195,6 +195,10 @@ fore200e_chunk_alloc(struct fore200e* fore200e, struct chunk* chunk, int size, i chunk->dma_addr = dma_map_single(fore200e->dev, chunk->align_addr, size, direction); + if (dma_mapping_error(fore200e->dev, chunk->dma_addr)) { + kfree(chunk->alloc_addr); + return -ENOMEM; + } return 0; } @@ -576,6 +580,8 @@ fore200e_pca_prom_read(struct fore200e* fore200e, struct prom_data* prom) prom_dma = dma_map_single(fore200e->dev, prom, sizeof(struct prom_data), DMA_FROM_DEVICE); + if (dma_mapping_error(fore200e->dev, prom_dma)) + return -ENOMEM; fore200e->bus->write(prom_dma, &entry->cp_entry->cmd.prom_block.prom_haddr); @@ -1597,6 +1603,11 @@ fore200e_send(struct atm_vcc *vcc, struct sk_buff *skb) tpd = entry->tpd; tpd->tsd[ 0 ].buffer = dma_map_single(fore200e->dev, data, tx_len, DMA_TO_DEVICE); + if (dma_mapping_error(fore200e->dev, tpd->tsd[0].buffer)) { + if (tx_copy) + kfree(data); + return -ENOMEM; + } tpd->tsd[ 0 ].length = tx_len; FORE200E_NEXT_ENTRY(txq->head, QUEUE_SIZE_TX); @@ -1671,6 +1682,8 @@ fore200e_getstats(struct fore200e* fore200e) stats_dma_addr = dma_map_single(fore200e->dev, fore200e->stats, sizeof(struct stats), DMA_FROM_DEVICE); + if (dma_mapping_error(fore200e->dev, stats_dma_addr)) + return -ENOMEM; FORE200E_NEXT_ENTRY(cmdq->head, QUEUE_SIZE_CMD);