提交 e6c0b69a 编写于 作者: D Dan Williams

ioat: convert ioat_probe to pcim/devm

The driver currently duplicates much of what these routines offer, so
just use the common code.  For example ->irq_mode tracks what interrupt
mode was initialized, which duplicates the ->msix_enabled and
->msi_enabled handling in pcim_release.

This also adds a check to the return value of dma_async_device_register,
which can fail.
Signed-off-by: NMaciej Sosnowski <maciej.sosnowski@intel.com>
Signed-off-by: NDan Williams <dan.j.williams@intel.com>
上级 1f27adc2
...@@ -121,6 +121,7 @@ static int ioat_dma_enumerate_channels(struct ioatdma_device *device) ...@@ -121,6 +121,7 @@ static int ioat_dma_enumerate_channels(struct ioatdma_device *device)
u32 xfercap; u32 xfercap;
int i; int i;
struct ioat_dma_chan *ioat_chan; struct ioat_dma_chan *ioat_chan;
struct device *dev = &device->pdev->dev;
/* /*
* IOAT ver.3 workarounds * IOAT ver.3 workarounds
...@@ -164,7 +165,7 @@ static int ioat_dma_enumerate_channels(struct ioatdma_device *device) ...@@ -164,7 +165,7 @@ static int ioat_dma_enumerate_channels(struct ioatdma_device *device)
} }
#endif #endif
for (i = 0; i < device->common.chancnt; i++) { for (i = 0; i < device->common.chancnt; i++) {
ioat_chan = kzalloc(sizeof(*ioat_chan), GFP_KERNEL); ioat_chan = devm_kzalloc(dev, sizeof(*ioat_chan), GFP_KERNEL);
if (!ioat_chan) { if (!ioat_chan) {
device->common.chancnt = i; device->common.chancnt = i;
break; break;
...@@ -1450,7 +1451,11 @@ MODULE_PARM_DESC(ioat_interrupt_style, ...@@ -1450,7 +1451,11 @@ MODULE_PARM_DESC(ioat_interrupt_style,
static int ioat_dma_setup_interrupts(struct ioatdma_device *device) static int ioat_dma_setup_interrupts(struct ioatdma_device *device)
{ {
struct ioat_dma_chan *ioat_chan; struct ioat_dma_chan *ioat_chan;
int err, i, j, msixcnt; struct pci_dev *pdev = device->pdev;
struct device *dev = &pdev->dev;
struct msix_entry *msix;
int i, j, msixcnt;
int err = -EINVAL;
u8 intrctrl = 0; u8 intrctrl = 0;
if (!strcmp(ioat_interrupt_style, "msix")) if (!strcmp(ioat_interrupt_style, "msix"))
...@@ -1461,8 +1466,7 @@ static int ioat_dma_setup_interrupts(struct ioatdma_device *device) ...@@ -1461,8 +1466,7 @@ static int ioat_dma_setup_interrupts(struct ioatdma_device *device)
goto msi; goto msi;
if (!strcmp(ioat_interrupt_style, "intx")) if (!strcmp(ioat_interrupt_style, "intx"))
goto intx; goto intx;
dev_err(&device->pdev->dev, "invalid ioat_interrupt_style %s\n", dev_err(dev, "invalid ioat_interrupt_style %s\n", ioat_interrupt_style);
ioat_interrupt_style);
goto err_no_irq; goto err_no_irq;
msix: msix:
...@@ -1471,55 +1475,55 @@ static int ioat_dma_setup_interrupts(struct ioatdma_device *device) ...@@ -1471,55 +1475,55 @@ static int ioat_dma_setup_interrupts(struct ioatdma_device *device)
for (i = 0; i < msixcnt; i++) for (i = 0; i < msixcnt; i++)
device->msix_entries[i].entry = i; device->msix_entries[i].entry = i;
err = pci_enable_msix(device->pdev, device->msix_entries, msixcnt); err = pci_enable_msix(pdev, device->msix_entries, msixcnt);
if (err < 0) if (err < 0)
goto msi; goto msi;
if (err > 0) if (err > 0)
goto msix_single_vector; goto msix_single_vector;
for (i = 0; i < msixcnt; i++) { for (i = 0; i < msixcnt; i++) {
msix = &device->msix_entries[i];
ioat_chan = ioat_lookup_chan_by_index(device, i); ioat_chan = ioat_lookup_chan_by_index(device, i);
err = request_irq(device->msix_entries[i].vector, err = devm_request_irq(dev, msix->vector,
ioat_dma_do_interrupt_msix, ioat_dma_do_interrupt_msix, 0,
0, "ioat-msix", ioat_chan); "ioat-msix", ioat_chan);
if (err) { if (err) {
for (j = 0; j < i; j++) { for (j = 0; j < i; j++) {
msix = &device->msix_entries[j];
ioat_chan = ioat_chan =
ioat_lookup_chan_by_index(device, j); ioat_lookup_chan_by_index(device, j);
free_irq(device->msix_entries[j].vector, devm_free_irq(dev, msix->vector, ioat_chan);
ioat_chan);
} }
goto msix_single_vector; goto msix_single_vector;
} }
} }
intrctrl |= IOAT_INTRCTRL_MSIX_VECTOR_CONTROL; intrctrl |= IOAT_INTRCTRL_MSIX_VECTOR_CONTROL;
device->irq_mode = msix_multi_vector;
goto done; goto done;
msix_single_vector: msix_single_vector:
device->msix_entries[0].entry = 0; msix = &device->msix_entries[0];
err = pci_enable_msix(device->pdev, device->msix_entries, 1); msix->entry = 0;
err = pci_enable_msix(pdev, device->msix_entries, 1);
if (err) if (err)
goto msi; goto msi;
err = request_irq(device->msix_entries[0].vector, ioat_dma_do_interrupt, err = devm_request_irq(dev, msix->vector, ioat_dma_do_interrupt, 0,
0, "ioat-msix", device); "ioat-msix", device);
if (err) { if (err) {
pci_disable_msix(device->pdev); pci_disable_msix(pdev);
goto msi; goto msi;
} }
device->irq_mode = msix_single_vector;
goto done; goto done;
msi: msi:
err = pci_enable_msi(device->pdev); err = pci_enable_msi(pdev);
if (err) if (err)
goto intx; goto intx;
err = request_irq(device->pdev->irq, ioat_dma_do_interrupt, err = devm_request_irq(dev, pdev->irq, ioat_dma_do_interrupt, 0,
0, "ioat-msi", device); "ioat-msi", device);
if (err) { if (err) {
pci_disable_msi(device->pdev); pci_disable_msi(pdev);
goto intx; goto intx;
} }
/* /*
...@@ -1527,21 +1531,17 @@ static int ioat_dma_setup_interrupts(struct ioatdma_device *device) ...@@ -1527,21 +1531,17 @@ static int ioat_dma_setup_interrupts(struct ioatdma_device *device)
*/ */
if (device->version == IOAT_VER_1_2) { if (device->version == IOAT_VER_1_2) {
u32 dmactrl; u32 dmactrl;
pci_read_config_dword(device->pdev, pci_read_config_dword(pdev, IOAT_PCI_DMACTRL_OFFSET, &dmactrl);
IOAT_PCI_DMACTRL_OFFSET, &dmactrl);
dmactrl |= IOAT_PCI_DMACTRL_MSI_EN; dmactrl |= IOAT_PCI_DMACTRL_MSI_EN;
pci_write_config_dword(device->pdev, pci_write_config_dword(pdev, IOAT_PCI_DMACTRL_OFFSET, dmactrl);
IOAT_PCI_DMACTRL_OFFSET, dmactrl);
} }
device->irq_mode = msi;
goto done; goto done;
intx: intx:
err = request_irq(device->pdev->irq, ioat_dma_do_interrupt, err = devm_request_irq(dev, pdev->irq, ioat_dma_do_interrupt,
IRQF_SHARED, "ioat-intx", device); IRQF_SHARED, "ioat-intx", device);
if (err) if (err)
goto err_no_irq; goto err_no_irq;
device->irq_mode = intx;
done: done:
intrctrl |= IOAT_INTRCTRL_MASTER_INT_EN; intrctrl |= IOAT_INTRCTRL_MASTER_INT_EN;
...@@ -1551,60 +1551,26 @@ static int ioat_dma_setup_interrupts(struct ioatdma_device *device) ...@@ -1551,60 +1551,26 @@ static int ioat_dma_setup_interrupts(struct ioatdma_device *device)
err_no_irq: err_no_irq:
/* Disable all interrupt generation */ /* Disable all interrupt generation */
writeb(0, device->reg_base + IOAT_INTRCTRL_OFFSET); writeb(0, device->reg_base + IOAT_INTRCTRL_OFFSET);
dev_err(&device->pdev->dev, "no usable interrupts\n"); dev_err(dev, "no usable interrupts\n");
device->irq_mode = none; return err;
return -1;
} }
/** static void ioat_disable_interrupts(struct ioatdma_device *device)
* ioat_dma_remove_interrupts - remove whatever interrupts were set
* @device: ioat device
*/
static void ioat_dma_remove_interrupts(struct ioatdma_device *device)
{ {
struct ioat_dma_chan *ioat_chan;
int i;
/* Disable all interrupt generation */ /* Disable all interrupt generation */
writeb(0, device->reg_base + IOAT_INTRCTRL_OFFSET); writeb(0, device->reg_base + IOAT_INTRCTRL_OFFSET);
switch (device->irq_mode) {
case msix_multi_vector:
for (i = 0; i < device->common.chancnt; i++) {
ioat_chan = ioat_lookup_chan_by_index(device, i);
free_irq(device->msix_entries[i].vector, ioat_chan);
}
pci_disable_msix(device->pdev);
break;
case msix_single_vector:
free_irq(device->msix_entries[0].vector, device);
pci_disable_msix(device->pdev);
break;
case msi:
free_irq(device->pdev->irq, device);
pci_disable_msi(device->pdev);
break;
case intx:
free_irq(device->pdev->irq, device);
break;
case none:
dev_warn(&device->pdev->dev,
"call to %s without interrupts setup\n", __func__);
}
device->irq_mode = none;
} }
struct ioatdma_device *ioat_dma_probe(struct pci_dev *pdev, struct ioatdma_device *ioat_dma_probe(struct pci_dev *pdev,
void __iomem *iobase) void __iomem *iobase)
{ {
int err; int err;
struct device *dev = &pdev->dev;
struct ioatdma_device *device; struct ioatdma_device *device;
device = kzalloc(sizeof(*device), GFP_KERNEL); device = devm_kzalloc(dev, sizeof(*device), GFP_KERNEL);
if (!device) { if (!device)
err = -ENOMEM; err = -ENOMEM;
goto err_kzalloc;
}
device->pdev = pdev; device->pdev = pdev;
device->reg_base = iobase; device->reg_base = iobase;
device->version = readb(device->reg_base + IOAT_VER_OFFSET); device->version = readb(device->reg_base + IOAT_VER_OFFSET);
...@@ -1651,14 +1617,12 @@ struct ioatdma_device *ioat_dma_probe(struct pci_dev *pdev, ...@@ -1651,14 +1617,12 @@ struct ioatdma_device *ioat_dma_probe(struct pci_dev *pdev,
break; break;
} }
dev_err(&device->pdev->dev, dev_err(dev, "Intel(R) I/OAT DMA Engine found,"
"Intel(R) I/OAT DMA Engine found,"
" %d channels, device version 0x%02x, driver version %s\n", " %d channels, device version 0x%02x, driver version %s\n",
device->common.chancnt, device->version, IOAT_DMA_VERSION); device->common.chancnt, device->version, IOAT_DMA_VERSION);
if (!device->common.chancnt) { if (!device->common.chancnt) {
dev_err(&device->pdev->dev, dev_err(dev, "Intel(R) I/OAT DMA Engine problem found: "
"Intel(R) I/OAT DMA Engine problem found: "
"zero channels detected\n"); "zero channels detected\n");
goto err_setup_interrupts; goto err_setup_interrupts;
} }
...@@ -1671,9 +1635,11 @@ struct ioatdma_device *ioat_dma_probe(struct pci_dev *pdev, ...@@ -1671,9 +1635,11 @@ struct ioatdma_device *ioat_dma_probe(struct pci_dev *pdev,
if (err) if (err)
goto err_self_test; goto err_self_test;
ioat_set_tcp_copy_break(device); err = dma_async_device_register(&device->common);
if (err)
goto err_self_test;
dma_async_device_register(&device->common); ioat_set_tcp_copy_break(device);
if (device->version != IOAT_VER_3_0) { if (device->version != IOAT_VER_3_0) {
INIT_DELAYED_WORK(&device->work, ioat_dma_chan_watchdog); INIT_DELAYED_WORK(&device->work, ioat_dma_chan_watchdog);
...@@ -1684,16 +1650,12 @@ struct ioatdma_device *ioat_dma_probe(struct pci_dev *pdev, ...@@ -1684,16 +1650,12 @@ struct ioatdma_device *ioat_dma_probe(struct pci_dev *pdev,
return device; return device;
err_self_test: err_self_test:
ioat_dma_remove_interrupts(device); ioat_disable_interrupts(device);
err_setup_interrupts: err_setup_interrupts:
pci_pool_destroy(device->completion_pool); pci_pool_destroy(device->completion_pool);
err_completion_pool: err_completion_pool:
pci_pool_destroy(device->dma_pool); pci_pool_destroy(device->dma_pool);
err_dma_pool: err_dma_pool:
kfree(device);
err_kzalloc:
dev_err(&pdev->dev,
"Intel(R) I/OAT DMA Engine initialization failed\n");
return NULL; return NULL;
} }
...@@ -1705,23 +1667,17 @@ void ioat_dma_remove(struct ioatdma_device *device) ...@@ -1705,23 +1667,17 @@ void ioat_dma_remove(struct ioatdma_device *device)
if (device->version != IOAT_VER_3_0) if (device->version != IOAT_VER_3_0)
cancel_delayed_work(&device->work); cancel_delayed_work(&device->work);
ioat_dma_remove_interrupts(device); ioat_disable_interrupts(device);
dma_async_device_unregister(&device->common); dma_async_device_unregister(&device->common);
pci_pool_destroy(device->dma_pool); pci_pool_destroy(device->dma_pool);
pci_pool_destroy(device->completion_pool); pci_pool_destroy(device->completion_pool);
iounmap(device->reg_base);
pci_release_regions(device->pdev);
pci_disable_device(device->pdev);
list_for_each_entry_safe(chan, _chan, list_for_each_entry_safe(chan, _chan,
&device->common.channels, device_node) { &device->common.channels, device_node) {
ioat_chan = to_ioat_chan(chan); ioat_chan = to_ioat_chan(chan);
list_del(&chan->device_node); list_del(&chan->device_node);
kfree(ioat_chan);
} }
kfree(device);
} }
...@@ -31,14 +31,6 @@ ...@@ -31,14 +31,6 @@
#define IOAT_DMA_VERSION "3.64" #define IOAT_DMA_VERSION "3.64"
enum ioat_interrupt {
none = 0,
msix_multi_vector = 1,
msix_single_vector = 2,
msi = 3,
intx = 4,
};
#define IOAT_LOW_COMPLETION_MASK 0xffffffc0 #define IOAT_LOW_COMPLETION_MASK 0xffffffc0
#define IOAT_DMA_DCA_ANY_CPU ~0 #define IOAT_DMA_DCA_ANY_CPU ~0
#define IOAT_WATCHDOG_PERIOD (2 * HZ) #define IOAT_WATCHDOG_PERIOD (2 * HZ)
...@@ -59,7 +51,6 @@ enum ioat_interrupt { ...@@ -59,7 +51,6 @@ enum ioat_interrupt {
*/ */
#define NULL_DESC_BUFFER_SIZE 1 #define NULL_DESC_BUFFER_SIZE 1
/** /**
* struct ioatdma_device - internal representation of a IOAT device * struct ioatdma_device - internal representation of a IOAT device
* @pdev: PCI-Express device * @pdev: PCI-Express device
...@@ -67,7 +58,6 @@ enum ioat_interrupt { ...@@ -67,7 +58,6 @@ enum ioat_interrupt {
* @dma_pool: for allocating DMA descriptors * @dma_pool: for allocating DMA descriptors
* @common: embedded struct dma_device * @common: embedded struct dma_device
* @version: version of ioatdma device * @version: version of ioatdma device
* @irq_mode: which style irq to use
* @msix_entries: irq handlers * @msix_entries: irq handlers
* @idx: per channel data * @idx: per channel data
*/ */
...@@ -79,7 +69,6 @@ struct ioatdma_device { ...@@ -79,7 +69,6 @@ struct ioatdma_device {
struct pci_pool *completion_pool; struct pci_pool *completion_pool;
struct dma_device common; struct dma_device common;
u8 version; u8 version;
enum ioat_interrupt irq_mode;
struct delayed_work work; struct delayed_work work;
struct msix_entry msix_entries[4]; struct msix_entry msix_entries[4];
struct ioat_dma_chan *idx[4]; struct ioat_dma_chan *idx[4];
......
...@@ -23,6 +23,7 @@ ...@@ -23,6 +23,7 @@
/* PCI Configuration Space Values */ /* PCI Configuration Space Values */
#define IOAT_PCI_VID 0x8086 #define IOAT_PCI_VID 0x8086
#define IOAT_MMIO_BAR 0
/* CB device ID's */ /* CB device ID's */
#define IOAT_PCI_DID_5000 0x1A38 #define IOAT_PCI_DID_5000 0x1A38
......
...@@ -62,7 +62,6 @@ static struct pci_device_id ioat_pci_tbl[] = { ...@@ -62,7 +62,6 @@ static struct pci_device_id ioat_pci_tbl[] = {
struct ioat_device { struct ioat_device {
struct pci_dev *pdev; struct pci_dev *pdev;
void __iomem *iobase;
struct ioatdma_device *dma; struct ioatdma_device *dma;
struct dca_provider *dca; struct dca_provider *dca;
}; };
...@@ -75,8 +74,10 @@ static int ioat_dca_enabled = 1; ...@@ -75,8 +74,10 @@ static int ioat_dca_enabled = 1;
module_param(ioat_dca_enabled, int, 0644); module_param(ioat_dca_enabled, int, 0644);
MODULE_PARM_DESC(ioat_dca_enabled, "control support of dca service (default: 1)"); MODULE_PARM_DESC(ioat_dca_enabled, "control support of dca service (default: 1)");
#define DRV_NAME "ioatdma"
static struct pci_driver ioat_pci_driver = { static struct pci_driver ioat_pci_driver = {
.name = "ioatdma", .name = DRV_NAME,
.id_table = ioat_pci_tbl, .id_table = ioat_pci_tbl,
.probe = ioat_probe, .probe = ioat_probe,
.remove = __devexit_p(ioat_remove), .remove = __devexit_p(ioat_remove),
...@@ -85,47 +86,42 @@ static struct pci_driver ioat_pci_driver = { ...@@ -85,47 +86,42 @@ static struct pci_driver ioat_pci_driver = {
static int __devinit ioat_probe(struct pci_dev *pdev, static int __devinit ioat_probe(struct pci_dev *pdev,
const struct pci_device_id *id) const struct pci_device_id *id)
{ {
void __iomem * const *iomap;
void __iomem *iobase; void __iomem *iobase;
struct device *dev = &pdev->dev;
struct ioat_device *device; struct ioat_device *device;
unsigned long mmio_start, mmio_len;
int err; int err;
err = pci_enable_device(pdev); err = pcim_enable_device(pdev);
if (err) if (err)
goto err_enable_device; return err;
err = pci_request_regions(pdev, ioat_pci_driver.name); err = pcim_iomap_regions(pdev, 1 << IOAT_MMIO_BAR, DRV_NAME);
if (err) if (err)
goto err_request_regions; return err;
iomap = pcim_iomap_table(pdev);
if (!iomap)
return -ENOMEM;
err = pci_set_dma_mask(pdev, DMA_BIT_MASK(64)); err = pci_set_dma_mask(pdev, DMA_BIT_MASK(64));
if (err) if (err)
err = pci_set_dma_mask(pdev, DMA_BIT_MASK(32)); err = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
if (err) if (err)
goto err_set_dma_mask; return err;
err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64)); err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64));
if (err) if (err)
err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32)); err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32));
if (err) if (err)
goto err_set_dma_mask; return err;
mmio_start = pci_resource_start(pdev, 0); device = devm_kzalloc(dev, sizeof(*device), GFP_KERNEL);
mmio_len = pci_resource_len(pdev, 0); if (!device)
iobase = ioremap(mmio_start, mmio_len); return -ENOMEM;
if (!iobase) {
err = -ENOMEM;
goto err_ioremap;
}
device = kzalloc(sizeof(*device), GFP_KERNEL);
if (!device) {
err = -ENOMEM;
goto err_kzalloc;
}
device->pdev = pdev; device->pdev = pdev;
pci_set_drvdata(pdev, device); pci_set_drvdata(pdev, device);
device->iobase = iobase; iobase = iomap[IOAT_MMIO_BAR];
pci_set_master(pdev); pci_set_master(pdev);
...@@ -146,28 +142,15 @@ static int __devinit ioat_probe(struct pci_dev *pdev, ...@@ -146,28 +142,15 @@ static int __devinit ioat_probe(struct pci_dev *pdev,
device->dca = ioat3_dca_init(pdev, iobase); device->dca = ioat3_dca_init(pdev, iobase);
break; break;
default: default:
err = -ENODEV; return -ENODEV;
break;
} }
if (!device->dma)
err = -ENODEV;
if (err) if (!device->dma) {
goto err_version; dev_err(dev, "Intel(R) I/OAT DMA Engine init failed\n");
return -ENODEV;
}
return 0; return 0;
err_version:
kfree(device);
err_kzalloc:
iounmap(iobase);
err_ioremap:
err_set_dma_mask:
pci_release_regions(pdev);
pci_disable_device(pdev);
err_request_regions:
err_enable_device:
return err;
} }
static void __devexit ioat_remove(struct pci_dev *pdev) static void __devexit ioat_remove(struct pci_dev *pdev)
...@@ -185,8 +168,6 @@ static void __devexit ioat_remove(struct pci_dev *pdev) ...@@ -185,8 +168,6 @@ static void __devexit ioat_remove(struct pci_dev *pdev)
ioat_dma_remove(device->dma); ioat_dma_remove(device->dma);
device->dma = NULL; device->dma = NULL;
} }
kfree(device);
} }
static int __init ioat_init_module(void) static int __init ioat_init_module(void)
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册