Skip to content

Commit

Permalink
Merge branch 'fixes' of git://git.kernel.org/pub/scm/linux/kernel/git…
Browse files Browse the repository at this point in the history
…/djbw/async_tx

* 'fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/djbw/async_tx:
  dmatest: fix use after free in dmatest_exit
  ipu_idmac: fix spinlock type
  iop-adma, mv_xor: fix mem leak on self-test setup failure
  fsldma: fix off by one in dma_halt
  I/OAT: fail self-test if callback test reaches timeout
  I/OAT: update driver version and copyright dates
  I/OAT: list usage cleanup
  I/OAT: set tcp_dma_copybreak to 256k for I/OAT ver.3
  I/OAT: cancel watchdog before dma remove
  I/OAT: fail initialization on zero channels detection
  I/OAT: do not set DCACTRL_CMPL_WRITE_ENABLE for I/OAT ver.3
  I/OAT: add verification for proper APICID_TAG_MAP setting by BIOS
  dmaengine: update kerneldoc
  • Loading branch information
Linus Torvalds committed Mar 8, 2009
2 parents fd6ec5f + 7cbd487 commit 5dc18f5
Show file tree
Hide file tree
Showing 13 changed files with 86 additions and 50 deletions.
2 changes: 1 addition & 1 deletion drivers/dca/dca-core.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright(c) 2007 Intel Corporation. All rights reserved.
* Copyright(c) 2007 - 2009 Intel Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
Expand Down
6 changes: 4 additions & 2 deletions drivers/dma/dmatest.c
Original file line number Diff line number Diff line change
Expand Up @@ -430,13 +430,15 @@ late_initcall(dmatest_init);
static void __exit dmatest_exit(void)
{
struct dmatest_chan *dtc, *_dtc;
struct dma_chan *chan;

list_for_each_entry_safe(dtc, _dtc, &dmatest_channels, node) {
list_del(&dtc->node);
chan = dtc->chan;
dmatest_cleanup_channel(dtc);
pr_debug("dmatest: dropped channel %s\n",
dma_chan_name(dtc->chan));
dma_release_channel(dtc->chan);
dma_chan_name(chan));
dma_release_channel(chan);
}
}
module_exit(dmatest_exit);
Expand Down
8 changes: 6 additions & 2 deletions drivers/dma/fsldma.c
Original file line number Diff line number Diff line change
Expand Up @@ -158,16 +158,20 @@ static void dma_start(struct fsl_dma_chan *fsl_chan)

static void dma_halt(struct fsl_dma_chan *fsl_chan)
{
int i = 0;
int i;

DMA_OUT(fsl_chan, &fsl_chan->reg_base->mr,
DMA_IN(fsl_chan, &fsl_chan->reg_base->mr, 32) | FSL_DMA_MR_CA,
32);
DMA_OUT(fsl_chan, &fsl_chan->reg_base->mr,
DMA_IN(fsl_chan, &fsl_chan->reg_base->mr, 32) & ~(FSL_DMA_MR_CS
| FSL_DMA_MR_EMS_EN | FSL_DMA_MR_CA), 32);

while (!dma_is_idle(fsl_chan) && (i++ < 100))
for (i = 0; i < 100; i++) {
if (dma_is_idle(fsl_chan))
break;
udelay(10);
}
if (i >= 100 && !dma_is_idle(fsl_chan))
dev_err(fsl_chan->dev, "DMA halt timeout!\n");
}
Expand Down
2 changes: 1 addition & 1 deletion drivers/dma/ioat.c
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/*
* Intel I/OAT DMA Linux driver
* Copyright(c) 2007 Intel Corporation.
* Copyright(c) 2007 - 2009 Intel Corporation.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
Expand Down
26 changes: 25 additions & 1 deletion drivers/dma/ioat_dca.c
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/*
* Intel I/OAT DMA Linux driver
* Copyright(c) 2007 Intel Corporation.
* Copyright(c) 2007 - 2009 Intel Corporation.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
Expand Down Expand Up @@ -49,6 +49,23 @@

#define DCA_TAG_MAP_MASK 0xDF

/* expected tag map bytes for I/OAT ver.2 */
#define DCA2_TAG_MAP_BYTE0 0x80
#define DCA2_TAG_MAP_BYTE1 0x0
#define DCA2_TAG_MAP_BYTE2 0x81
#define DCA2_TAG_MAP_BYTE3 0x82
#define DCA2_TAG_MAP_BYTE4 0x82

/* verify if tag map matches expected values */
static inline int dca2_tag_map_valid(u8 *tag_map)
{
return ((tag_map[0] == DCA2_TAG_MAP_BYTE0) &&
(tag_map[1] == DCA2_TAG_MAP_BYTE1) &&
(tag_map[2] == DCA2_TAG_MAP_BYTE2) &&
(tag_map[3] == DCA2_TAG_MAP_BYTE3) &&
(tag_map[4] == DCA2_TAG_MAP_BYTE4));
}

/*
* "Legacy" DCA systems do not implement the DCA register set in the
* I/OAT device. Software needs direct support for their tag mappings.
Expand Down Expand Up @@ -452,6 +469,13 @@ struct dca_provider *ioat2_dca_init(struct pci_dev *pdev, void __iomem *iobase)
ioatdca->tag_map[i] = 0;
}

if (!dca2_tag_map_valid(ioatdca->tag_map)) {
dev_err(&pdev->dev, "APICID_TAG_MAP set incorrectly by BIOS, "
"disabling DCA\n");
free_dca_provider(dca);
return NULL;
}

err = register_dca_provider(dca, &pdev->dev);
if (err) {
free_dca_provider(dca);
Expand Down
39 changes: 24 additions & 15 deletions drivers/dma/ioat_dma.c
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/*
* Intel I/OAT DMA Linux driver
* Copyright(c) 2004 - 2007 Intel Corporation.
* Copyright(c) 2004 - 2009 Intel Corporation.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
Expand Down Expand Up @@ -189,11 +189,13 @@ static int ioat_dma_enumerate_channels(struct ioatdma_device *device)
ioat_chan->xfercap = xfercap;
ioat_chan->desccount = 0;
INIT_DELAYED_WORK(&ioat_chan->work, ioat_dma_chan_reset_part2);
if (ioat_chan->device->version != IOAT_VER_1_2) {
writel(IOAT_DCACTRL_CMPL_WRITE_ENABLE
| IOAT_DMA_DCA_ANY_CPU,
ioat_chan->reg_base + IOAT_DCACTRL_OFFSET);
}
if (ioat_chan->device->version == IOAT_VER_2_0)
writel(IOAT_DCACTRL_CMPL_WRITE_ENABLE |
IOAT_DMA_DCA_ANY_CPU,
ioat_chan->reg_base + IOAT_DCACTRL_OFFSET);
else if (ioat_chan->device->version == IOAT_VER_3_0)
writel(IOAT_DMA_DCA_ANY_CPU,
ioat_chan->reg_base + IOAT_DCACTRL_OFFSET);
spin_lock_init(&ioat_chan->cleanup_lock);
spin_lock_init(&ioat_chan->desc_lock);
INIT_LIST_HEAD(&ioat_chan->free_desc);
Expand Down Expand Up @@ -1169,9 +1171,8 @@ static void ioat_dma_memcpy_cleanup(struct ioat_dma_chan *ioat_chan)
* up if the client is done with the descriptor
*/
if (async_tx_test_ack(&desc->async_tx)) {
list_del(&desc->node);
list_add_tail(&desc->node,
&ioat_chan->free_desc);
list_move_tail(&desc->node,
&ioat_chan->free_desc);
} else
desc->async_tx.cookie = 0;
} else {
Expand Down Expand Up @@ -1362,6 +1363,7 @@ static int ioat_dma_self_test(struct ioatdma_device *device)
dma_cookie_t cookie;
int err = 0;
struct completion cmp;
unsigned long tmo;

src = kzalloc(sizeof(u8) * IOAT_TEST_SIZE, GFP_KERNEL);
if (!src)
Expand Down Expand Up @@ -1413,9 +1415,10 @@ static int ioat_dma_self_test(struct ioatdma_device *device)
}
device->common.device_issue_pending(dma_chan);

wait_for_completion_timeout(&cmp, msecs_to_jiffies(3000));
tmo = wait_for_completion_timeout(&cmp, msecs_to_jiffies(3000));

if (device->common.device_is_tx_complete(dma_chan, cookie, NULL, NULL)
if (tmo == 0 ||
device->common.device_is_tx_complete(dma_chan, cookie, NULL, NULL)
!= DMA_SUCCESS) {
dev_err(&device->pdev->dev,
"Self-test copy timed out, disabling\n");
Expand Down Expand Up @@ -1657,6 +1660,13 @@ struct ioatdma_device *ioat_dma_probe(struct pci_dev *pdev,
" %d channels, device version 0x%02x, driver version %s\n",
device->common.chancnt, device->version, IOAT_DMA_VERSION);

if (!device->common.chancnt) {
dev_err(&device->pdev->dev,
"Intel(R) I/OAT DMA Engine problem found: "
"zero channels detected\n");
goto err_setup_interrupts;
}

err = ioat_dma_setup_interrupts(device);
if (err)
goto err_setup_interrupts;
Expand Down Expand Up @@ -1696,6 +1706,9 @@ void ioat_dma_remove(struct ioatdma_device *device)
struct dma_chan *chan, *_chan;
struct ioat_dma_chan *ioat_chan;

if (device->version != IOAT_VER_3_0)
cancel_delayed_work(&device->work);

ioat_dma_remove_interrupts(device);

dma_async_device_unregister(&device->common);
Expand All @@ -1707,10 +1720,6 @@ void ioat_dma_remove(struct ioatdma_device *device)
pci_release_regions(device->pdev);
pci_disable_device(device->pdev);

if (device->version != IOAT_VER_3_0) {
cancel_delayed_work(&device->work);
}

list_for_each_entry_safe(chan, _chan,
&device->common.channels, device_node) {
ioat_chan = to_ioat_chan(chan);
Expand Down
8 changes: 5 additions & 3 deletions drivers/dma/ioatdma.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright(c) 2004 - 2007 Intel Corporation. All rights reserved.
* Copyright(c) 2004 - 2009 Intel Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
Expand Down Expand Up @@ -29,7 +29,7 @@
#include <linux/pci_ids.h>
#include <net/tcp.h>

#define IOAT_DMA_VERSION "3.30"
#define IOAT_DMA_VERSION "3.64"

enum ioat_interrupt {
none = 0,
Expand Down Expand Up @@ -135,12 +135,14 @@ static inline void ioat_set_tcp_copy_break(struct ioatdma_device *dev)
#ifdef CONFIG_NET_DMA
switch (dev->version) {
case IOAT_VER_1_2:
case IOAT_VER_3_0:
sysctl_tcp_dma_copybreak = 4096;
break;
case IOAT_VER_2_0:
sysctl_tcp_dma_copybreak = 2048;
break;
case IOAT_VER_3_0:
sysctl_tcp_dma_copybreak = 262144;
break;
}
#endif
}
Expand Down
2 changes: 1 addition & 1 deletion drivers/dma/ioatdma_hw.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright(c) 2004 - 2007 Intel Corporation. All rights reserved.
* Copyright(c) 2004 - 2009 Intel Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
Expand Down
2 changes: 1 addition & 1 deletion drivers/dma/ioatdma_registers.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright(c) 2004 - 2007 Intel Corporation. All rights reserved.
* Copyright(c) 2004 - 2009 Intel Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
Expand Down
16 changes: 8 additions & 8 deletions drivers/dma/iop-adma.c
Original file line number Diff line number Diff line change
Expand Up @@ -928,19 +928,19 @@ iop_adma_xor_zero_sum_self_test(struct iop_adma_device *device)

for (src_idx = 0; src_idx < IOP_ADMA_NUM_SRC_TEST; src_idx++) {
xor_srcs[src_idx] = alloc_page(GFP_KERNEL);
if (!xor_srcs[src_idx])
while (src_idx--) {
if (!xor_srcs[src_idx]) {
while (src_idx--)
__free_page(xor_srcs[src_idx]);
return -ENOMEM;
}
return -ENOMEM;
}
}

dest = alloc_page(GFP_KERNEL);
if (!dest)
while (src_idx--) {
if (!dest) {
while (src_idx--)
__free_page(xor_srcs[src_idx]);
return -ENOMEM;
}
return -ENOMEM;
}

/* Fill in src buffers */
for (src_idx = 0; src_idx < IOP_ADMA_NUM_SRC_TEST; src_idx++) {
Expand Down
2 changes: 1 addition & 1 deletion drivers/dma/ipu/ipu_idmac.c
Original file line number Diff line number Diff line change
Expand Up @@ -729,7 +729,7 @@ static int ipu_init_channel_buffer(struct idmac_channel *ichan,

ichan->status = IPU_CHANNEL_READY;

spin_unlock_irqrestore(ipu->lock, flags);
spin_unlock_irqrestore(&ipu->lock, flags);

return 0;
}
Expand Down
16 changes: 8 additions & 8 deletions drivers/dma/mv_xor.c
Original file line number Diff line number Diff line change
Expand Up @@ -1019,19 +1019,19 @@ mv_xor_xor_self_test(struct mv_xor_device *device)

for (src_idx = 0; src_idx < MV_XOR_NUM_SRC_TEST; src_idx++) {
xor_srcs[src_idx] = alloc_page(GFP_KERNEL);
if (!xor_srcs[src_idx])
while (src_idx--) {
if (!xor_srcs[src_idx]) {
while (src_idx--)
__free_page(xor_srcs[src_idx]);
return -ENOMEM;
}
return -ENOMEM;
}
}

dest = alloc_page(GFP_KERNEL);
if (!dest)
while (src_idx--) {
if (!dest) {
while (src_idx--)
__free_page(xor_srcs[src_idx]);
return -ENOMEM;
}
return -ENOMEM;
}

/* Fill in src buffers */
for (src_idx = 0; src_idx < MV_XOR_NUM_SRC_TEST; src_idx++) {
Expand Down
7 changes: 1 addition & 6 deletions include/linux/dmaengine.h
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,6 @@ typedef struct { DECLARE_BITMAP(bits, DMA_TX_TYPE_END); } dma_cap_mask_t;

/**
* struct dma_chan_percpu - the per-CPU part of struct dma_chan
* @refcount: local_t used for open-coded "bigref" counting
* @memcpy_count: transaction counter
* @bytes_transferred: byte counter
*/
Expand All @@ -114,9 +113,6 @@ struct dma_chan_percpu {
* @cookie: last cookie value returned to client
* @chan_id: channel ID for sysfs
* @dev: class device for sysfs
* @refcount: kref, used in "bigref" slow-mode
* @slow_ref: indicates that the DMA channel is free
* @rcu: the DMA channel's RCU head
* @device_node: used to add this to the device chan list
* @local: per-cpu pointer to a struct dma_chan_percpu
* @client-count: how many clients are using this channel
Expand Down Expand Up @@ -213,8 +209,6 @@ struct dma_async_tx_descriptor {
* @global_node: list_head for global dma_device_list
* @cap_mask: one or more dma_capability flags
* @max_xor: maximum number of xor sources, 0 if no capability
* @refcount: reference count
* @done: IO completion struct
* @dev_id: unique device ID
* @dev: struct device reference for dma mapping api
* @device_alloc_chan_resources: allocate resources and return the
Expand All @@ -227,6 +221,7 @@ struct dma_async_tx_descriptor {
* @device_prep_dma_interrupt: prepares an end of chain interrupt operation
* @device_prep_slave_sg: prepares a slave dma operation
* @device_terminate_all: terminate all pending operations
* @device_is_tx_complete: poll for transaction completion
* @device_issue_pending: push pending transactions to hardware
*/
struct dma_device {
Expand Down

0 comments on commit 5dc18f5

Please sign in to comment.