Commit bf40a686 authored by Dan Williams's avatar Dan Williams

ioat3: split ioat3 support to its own file, add memset

Up until this point the driver for Intel(R) QuickData Technology
engines, specification versions 2 and 3, were mostly identical save for
a few quirks.  Version 3.2 hardware adds many new capabilities (like
raid offload support) requiring some infrastructure that is not relevant
for v2.  For better code organization of the new funcionality move v3
and v3.2 support to its own file dma_v3.c, and export some routines from
the base files (dma.c and dma_v2.c) that can be reused directly.

The first new capability included in this code reorganization is support
for v3.2 memset operations.
Signed-off-by: default avatarDan Williams <dan.j.williams@intel.com>
parent 2aec048c
obj-$(CONFIG_INTEL_IOATDMA) += ioatdma.o obj-$(CONFIG_INTEL_IOATDMA) += ioatdma.o
ioatdma-objs := pci.o dma.o dma_v2.o dca.o ioatdma-objs := pci.o dma.o dma_v2.o dma_v3.o dca.o
...@@ -538,17 +538,6 @@ static void ioat1_cleanup_tasklet(unsigned long data) ...@@ -538,17 +538,6 @@ static void ioat1_cleanup_tasklet(unsigned long data)
writew(IOAT_CHANCTRL_RUN, chan->base.reg_base + IOAT_CHANCTRL_OFFSET); writew(IOAT_CHANCTRL_RUN, chan->base.reg_base + IOAT_CHANCTRL_OFFSET);
} }
static void ioat_unmap(struct pci_dev *pdev, dma_addr_t addr, size_t len,
int direction, enum dma_ctrl_flags flags, bool dst)
{
if ((dst && (flags & DMA_COMPL_DEST_UNMAP_SINGLE)) ||
(!dst && (flags & DMA_COMPL_SRC_UNMAP_SINGLE)))
pci_unmap_single(pdev, addr, len, direction);
else
pci_unmap_page(pdev, addr, len, direction);
}
void ioat_dma_unmap(struct ioat_chan_common *chan, enum dma_ctrl_flags flags, void ioat_dma_unmap(struct ioat_chan_common *chan, enum dma_ctrl_flags flags,
size_t len, struct ioat_dma_descriptor *hw) size_t len, struct ioat_dma_descriptor *hw)
{ {
......
...@@ -60,6 +60,10 @@ ...@@ -60,6 +60,10 @@
* @dca: direct cache access context * @dca: direct cache access context
* @intr_quirk: interrupt setup quirk (for ioat_v1 devices) * @intr_quirk: interrupt setup quirk (for ioat_v1 devices)
* @enumerate_channels: hw version specific channel enumeration * @enumerate_channels: hw version specific channel enumeration
* @cleanup_tasklet: select between the v2 and v3 cleanup routines
* @timer_fn: select between the v2 and v3 timer watchdog routines
*
* Note: the v3 cleanup routine supports raid operations
*/ */
struct ioatdma_device { struct ioatdma_device {
...@@ -74,6 +78,8 @@ struct ioatdma_device { ...@@ -74,6 +78,8 @@ struct ioatdma_device {
struct dca_provider *dca; struct dca_provider *dca;
void (*intr_quirk)(struct ioatdma_device *device); void (*intr_quirk)(struct ioatdma_device *device);
int (*enumerate_channels)(struct ioatdma_device *device); int (*enumerate_channels)(struct ioatdma_device *device);
void (*cleanup_tasklet)(unsigned long data);
void (*timer_fn)(unsigned long data);
}; };
struct ioat_chan_common { struct ioat_chan_common {
...@@ -287,6 +293,16 @@ static inline bool is_ioat_bug(unsigned long err) ...@@ -287,6 +293,16 @@ static inline bool is_ioat_bug(unsigned long err)
IOAT_CHANERR_LENGTH_ERR)); IOAT_CHANERR_LENGTH_ERR));
} }
static inline void ioat_unmap(struct pci_dev *pdev, dma_addr_t addr, size_t len,
int direction, enum dma_ctrl_flags flags, bool dst)
{
if ((dst && (flags & DMA_COMPL_DEST_UNMAP_SINGLE)) ||
(!dst && (flags & DMA_COMPL_SRC_UNMAP_SINGLE)))
pci_unmap_single(pdev, addr, len, direction);
else
pci_unmap_page(pdev, addr, len, direction);
}
int __devinit ioat_probe(struct ioatdma_device *device); int __devinit ioat_probe(struct ioatdma_device *device);
int __devinit ioat_register(struct ioatdma_device *device); int __devinit ioat_register(struct ioatdma_device *device);
int __devinit ioat1_dma_probe(struct ioatdma_device *dev, int dca); int __devinit ioat1_dma_probe(struct ioatdma_device *dev, int dca);
......
...@@ -39,7 +39,7 @@ ...@@ -39,7 +39,7 @@
#include "registers.h" #include "registers.h"
#include "hw.h" #include "hw.h"
static int ioat_ring_alloc_order = 8; int ioat_ring_alloc_order = 8;
module_param(ioat_ring_alloc_order, int, 0644); module_param(ioat_ring_alloc_order, int, 0644);
MODULE_PARM_DESC(ioat_ring_alloc_order, MODULE_PARM_DESC(ioat_ring_alloc_order,
"ioat2+: allocate 2^n descriptors per channel (default: n=8)"); "ioat2+: allocate 2^n descriptors per channel (default: n=8)");
...@@ -63,7 +63,7 @@ static void __ioat2_issue_pending(struct ioat2_dma_chan *ioat) ...@@ -63,7 +63,7 @@ static void __ioat2_issue_pending(struct ioat2_dma_chan *ioat)
__func__, ioat->head, ioat->tail, ioat->issued, ioat->dmacount); __func__, ioat->head, ioat->tail, ioat->issued, ioat->dmacount);
} }
static void ioat2_issue_pending(struct dma_chan *chan) void ioat2_issue_pending(struct dma_chan *chan)
{ {
struct ioat2_dma_chan *ioat = to_ioat2_chan(chan); struct ioat2_dma_chan *ioat = to_ioat2_chan(chan);
...@@ -214,7 +214,7 @@ static void ioat2_cleanup_tasklet(unsigned long data) ...@@ -214,7 +214,7 @@ static void ioat2_cleanup_tasklet(unsigned long data)
writew(IOAT_CHANCTRL_RUN, ioat->base.reg_base + IOAT_CHANCTRL_OFFSET); writew(IOAT_CHANCTRL_RUN, ioat->base.reg_base + IOAT_CHANCTRL_OFFSET);
} }
static void __restart_chan(struct ioat2_dma_chan *ioat) void __ioat2_restart_chan(struct ioat2_dma_chan *ioat)
{ {
struct ioat_chan_common *chan = &ioat->base; struct ioat_chan_common *chan = &ioat->base;
...@@ -255,11 +255,9 @@ static void ioat2_restart_channel(struct ioat2_dma_chan *ioat) ...@@ -255,11 +255,9 @@ static void ioat2_restart_channel(struct ioat2_dma_chan *ioat)
if (ioat_cleanup_preamble(chan, &phys_complete)) if (ioat_cleanup_preamble(chan, &phys_complete))
__cleanup(ioat, phys_complete); __cleanup(ioat, phys_complete);
__restart_chan(ioat); __ioat2_restart_chan(ioat);
} }
static bool reshape_ring(struct ioat2_dma_chan *ioat, int order);
static void ioat2_timer_event(unsigned long data) static void ioat2_timer_event(unsigned long data)
{ {
struct ioat2_dma_chan *ioat = (void *) data; struct ioat2_dma_chan *ioat = (void *) data;
...@@ -321,7 +319,7 @@ static void ioat2_timer_event(unsigned long data) ...@@ -321,7 +319,7 @@ static void ioat2_timer_event(unsigned long data)
* ioat2_enumerate_channels - find and initialize the device's channels * ioat2_enumerate_channels - find and initialize the device's channels
* @device: the device to be enumerated * @device: the device to be enumerated
*/ */
static int ioat2_enumerate_channels(struct ioatdma_device *device) int ioat2_enumerate_channels(struct ioatdma_device *device)
{ {
struct ioat2_dma_chan *ioat; struct ioat2_dma_chan *ioat;
struct device *dev = &device->pdev->dev; struct device *dev = &device->pdev->dev;
...@@ -354,8 +352,8 @@ static int ioat2_enumerate_channels(struct ioatdma_device *device) ...@@ -354,8 +352,8 @@ static int ioat2_enumerate_channels(struct ioatdma_device *device)
break; break;
ioat_init_channel(device, &ioat->base, i, ioat_init_channel(device, &ioat->base, i,
ioat2_timer_event, device->timer_fn,
ioat2_cleanup_tasklet, device->cleanup_tasklet,
(unsigned long) ioat); (unsigned long) ioat);
ioat->xfercap_log = xfercap_log; ioat->xfercap_log = xfercap_log;
spin_lock_init(&ioat->ring_lock); spin_lock_init(&ioat->ring_lock);
...@@ -460,7 +458,7 @@ static struct ioat_ring_ent **ioat2_alloc_ring(struct dma_chan *c, int order, gf ...@@ -460,7 +458,7 @@ static struct ioat_ring_ent **ioat2_alloc_ring(struct dma_chan *c, int order, gf
/* ioat2_alloc_chan_resources - allocate/initialize ioat2 descriptor ring /* ioat2_alloc_chan_resources - allocate/initialize ioat2 descriptor ring
* @chan: channel to be initialized * @chan: channel to be initialized
*/ */
static int ioat2_alloc_chan_resources(struct dma_chan *c) int ioat2_alloc_chan_resources(struct dma_chan *c)
{ {
struct ioat2_dma_chan *ioat = to_ioat2_chan(c); struct ioat2_dma_chan *ioat = to_ioat2_chan(c);
struct ioat_chan_common *chan = &ioat->base; struct ioat_chan_common *chan = &ioat->base;
...@@ -514,7 +512,7 @@ static int ioat2_alloc_chan_resources(struct dma_chan *c) ...@@ -514,7 +512,7 @@ static int ioat2_alloc_chan_resources(struct dma_chan *c)
return 1 << ioat->alloc_order; return 1 << ioat->alloc_order;
} }
static bool reshape_ring(struct ioat2_dma_chan *ioat, int order) bool reshape_ring(struct ioat2_dma_chan *ioat, int order)
{ {
/* reshape differs from normal ring allocation in that we want /* reshape differs from normal ring allocation in that we want
* to allocate a new software ring while only * to allocate a new software ring while only
...@@ -627,7 +625,7 @@ static bool reshape_ring(struct ioat2_dma_chan *ioat, int order) ...@@ -627,7 +625,7 @@ static bool reshape_ring(struct ioat2_dma_chan *ioat, int order)
* @ioat: ioat2,3 channel (ring) to operate on * @ioat: ioat2,3 channel (ring) to operate on
* @num_descs: allocation length * @num_descs: allocation length
*/ */
static int ioat2_alloc_and_lock(u16 *idx, struct ioat2_dma_chan *ioat, int num_descs) int ioat2_alloc_and_lock(u16 *idx, struct ioat2_dma_chan *ioat, int num_descs)
{ {
struct ioat_chan_common *chan = &ioat->base; struct ioat_chan_common *chan = &ioat->base;
...@@ -655,9 +653,11 @@ static int ioat2_alloc_and_lock(u16 *idx, struct ioat2_dma_chan *ioat, int num_d ...@@ -655,9 +653,11 @@ static int ioat2_alloc_and_lock(u16 *idx, struct ioat2_dma_chan *ioat, int num_d
spin_lock_bh(&chan->cleanup_lock); spin_lock_bh(&chan->cleanup_lock);
if (jiffies > chan->timer.expires && if (jiffies > chan->timer.expires &&
timer_pending(&chan->timer)) { timer_pending(&chan->timer)) {
struct ioatdma_device *device = chan->device;
mod_timer(&chan->timer, jiffies + COMPLETION_TIMEOUT); mod_timer(&chan->timer, jiffies + COMPLETION_TIMEOUT);
spin_unlock_bh(&chan->cleanup_lock); spin_unlock_bh(&chan->cleanup_lock);
ioat2_timer_event((unsigned long) ioat); device->timer_fn((unsigned long) ioat);
} else } else
spin_unlock_bh(&chan->cleanup_lock); spin_unlock_bh(&chan->cleanup_lock);
return -ENOMEM; return -ENOMEM;
...@@ -670,7 +670,7 @@ static int ioat2_alloc_and_lock(u16 *idx, struct ioat2_dma_chan *ioat, int num_d ...@@ -670,7 +670,7 @@ static int ioat2_alloc_and_lock(u16 *idx, struct ioat2_dma_chan *ioat, int num_d
return 0; /* with ioat->ring_lock held */ return 0; /* with ioat->ring_lock held */
} }
static struct dma_async_tx_descriptor * struct dma_async_tx_descriptor *
ioat2_dma_prep_memcpy_lock(struct dma_chan *c, dma_addr_t dma_dest, ioat2_dma_prep_memcpy_lock(struct dma_chan *c, dma_addr_t dma_dest,
dma_addr_t dma_src, size_t len, unsigned long flags) dma_addr_t dma_src, size_t len, unsigned long flags)
{ {
...@@ -722,11 +722,11 @@ ioat2_dma_prep_memcpy_lock(struct dma_chan *c, dma_addr_t dma_dest, ...@@ -722,11 +722,11 @@ ioat2_dma_prep_memcpy_lock(struct dma_chan *c, dma_addr_t dma_dest,
* ioat2_free_chan_resources - release all the descriptors * ioat2_free_chan_resources - release all the descriptors
* @chan: the channel to be cleaned * @chan: the channel to be cleaned
*/ */
static void ioat2_free_chan_resources(struct dma_chan *c) void ioat2_free_chan_resources(struct dma_chan *c)
{ {
struct ioat2_dma_chan *ioat = to_ioat2_chan(c); struct ioat2_dma_chan *ioat = to_ioat2_chan(c);
struct ioat_chan_common *chan = &ioat->base; struct ioat_chan_common *chan = &ioat->base;
struct ioatdma_device *ioatdma_device = chan->device; struct ioatdma_device *device = chan->device;
struct ioat_ring_ent *desc; struct ioat_ring_ent *desc;
const u16 total_descs = 1 << ioat->alloc_order; const u16 total_descs = 1 << ioat->alloc_order;
int descs; int descs;
...@@ -740,7 +740,7 @@ static void ioat2_free_chan_resources(struct dma_chan *c) ...@@ -740,7 +740,7 @@ static void ioat2_free_chan_resources(struct dma_chan *c)
tasklet_disable(&chan->cleanup_task); tasklet_disable(&chan->cleanup_task);
del_timer_sync(&chan->timer); del_timer_sync(&chan->timer);
ioat2_cleanup(ioat); device->cleanup_tasklet((unsigned long) ioat);
/* Delay 100ms after reset to allow internal DMA logic to quiesce /* Delay 100ms after reset to allow internal DMA logic to quiesce
* before removing DMA descriptor resources. * before removing DMA descriptor resources.
...@@ -770,8 +770,7 @@ static void ioat2_free_chan_resources(struct dma_chan *c) ...@@ -770,8 +770,7 @@ static void ioat2_free_chan_resources(struct dma_chan *c)
kfree(ioat->ring); kfree(ioat->ring);
ioat->ring = NULL; ioat->ring = NULL;
ioat->alloc_order = 0; ioat->alloc_order = 0;
pci_pool_free(ioatdma_device->completion_pool, pci_pool_free(device->completion_pool, chan->completion,
chan->completion,
chan->completion_dma); chan->completion_dma);
spin_unlock_bh(&ioat->ring_lock); spin_unlock_bh(&ioat->ring_lock);
...@@ -781,16 +780,17 @@ static void ioat2_free_chan_resources(struct dma_chan *c) ...@@ -781,16 +780,17 @@ static void ioat2_free_chan_resources(struct dma_chan *c)
ioat->dmacount = 0; ioat->dmacount = 0;
} }
static enum dma_status enum dma_status
ioat2_is_complete(struct dma_chan *c, dma_cookie_t cookie, ioat2_is_complete(struct dma_chan *c, dma_cookie_t cookie,
dma_cookie_t *done, dma_cookie_t *used) dma_cookie_t *done, dma_cookie_t *used)
{ {
struct ioat2_dma_chan *ioat = to_ioat2_chan(c); struct ioat2_dma_chan *ioat = to_ioat2_chan(c);
struct ioatdma_device *device = ioat->base.device;
if (ioat_is_complete(c, cookie, done, used) == DMA_SUCCESS) if (ioat_is_complete(c, cookie, done, used) == DMA_SUCCESS)
return DMA_SUCCESS; return DMA_SUCCESS;
ioat2_cleanup(ioat); device->cleanup_tasklet((unsigned long) ioat);
return ioat_is_complete(c, cookie, done, used); return ioat_is_complete(c, cookie, done, used);
} }
...@@ -804,6 +804,8 @@ int __devinit ioat2_dma_probe(struct ioatdma_device *device, int dca) ...@@ -804,6 +804,8 @@ int __devinit ioat2_dma_probe(struct ioatdma_device *device, int dca)
int err; int err;
device->enumerate_channels = ioat2_enumerate_channels; device->enumerate_channels = ioat2_enumerate_channels;
device->cleanup_tasklet = ioat2_cleanup_tasklet;
device->timer_fn = ioat2_timer_event;
dma = &device->common; dma = &device->common;
dma->device_prep_dma_memcpy = ioat2_dma_prep_memcpy_lock; dma->device_prep_dma_memcpy = ioat2_dma_prep_memcpy_lock;
dma->device_issue_pending = ioat2_issue_pending; dma->device_issue_pending = ioat2_issue_pending;
...@@ -830,53 +832,3 @@ int __devinit ioat2_dma_probe(struct ioatdma_device *device, int dca) ...@@ -830,53 +832,3 @@ int __devinit ioat2_dma_probe(struct ioatdma_device *device, int dca)
return err; return err;
} }
int __devinit ioat3_dma_probe(struct ioatdma_device *device, int dca)
{
struct pci_dev *pdev = device->pdev;
struct dma_device *dma;
struct dma_chan *c;
struct ioat_chan_common *chan;
int err;
u16 dev_id;
device->enumerate_channels = ioat2_enumerate_channels;
dma = &device->common;
dma->device_prep_dma_memcpy = ioat2_dma_prep_memcpy_lock;
dma->device_issue_pending = ioat2_issue_pending;
dma->device_alloc_chan_resources = ioat2_alloc_chan_resources;
dma->device_free_chan_resources = ioat2_free_chan_resources;
dma->device_is_tx_complete = ioat2_is_complete;
/* -= IOAT ver.3 workarounds =- */
/* Write CHANERRMSK_INT with 3E07h to mask out the errors
* that can cause stability issues for IOAT ver.3
*/
pci_write_config_dword(pdev, IOAT_PCI_CHANERRMASK_INT_OFFSET, 0x3e07);
/* Clear DMAUNCERRSTS Cfg-Reg Parity Error status bit
* (workaround for spurious config parity error after restart)
*/
pci_read_config_word(pdev, IOAT_PCI_DEVICE_ID_OFFSET, &dev_id);
if (dev_id == PCI_DEVICE_ID_INTEL_IOAT_TBG0)
pci_write_config_dword(pdev, IOAT_PCI_DMAUNCERRSTS_OFFSET, 0x10);
err = ioat_probe(device);
if (err)
return err;
ioat_set_tcp_copy_break(262144);
list_for_each_entry(c, &dma->channels, device_node) {
chan = to_chan_common(c);
writel(IOAT_DMA_DCA_ANY_CPU,
chan->reg_base + IOAT_DCACTRL_OFFSET);
}
err = ioat_register(device);
if (err)
return err;
if (dca)
device->dca = ioat3_dca_init(pdev, device->reg_base);
return err;
}
...@@ -27,6 +27,7 @@ ...@@ -27,6 +27,7 @@
extern int ioat_pending_level; extern int ioat_pending_level;
extern int ioat_ring_alloc_order;
/* /*
* workaround for IOAT ver.3.0 null descriptor issue * workaround for IOAT ver.3.0 null descriptor issue
...@@ -167,4 +168,16 @@ int __devinit ioat2_dma_probe(struct ioatdma_device *dev, int dca); ...@@ -167,4 +168,16 @@ int __devinit ioat2_dma_probe(struct ioatdma_device *dev, int dca);
int __devinit ioat3_dma_probe(struct ioatdma_device *dev, int dca); int __devinit ioat3_dma_probe(struct ioatdma_device *dev, int dca);
struct dca_provider * __devinit ioat2_dca_init(struct pci_dev *pdev, void __iomem *iobase); struct dca_provider * __devinit ioat2_dca_init(struct pci_dev *pdev, void __iomem *iobase);
struct dca_provider * __devinit ioat3_dca_init(struct pci_dev *pdev, void __iomem *iobase); struct dca_provider * __devinit ioat3_dca_init(struct pci_dev *pdev, void __iomem *iobase);
int ioat2_alloc_and_lock(u16 *idx, struct ioat2_dma_chan *ioat, int num_descs);
int ioat2_enumerate_channels(struct ioatdma_device *device);
struct dma_async_tx_descriptor *
ioat2_dma_prep_memcpy_lock(struct dma_chan *c, dma_addr_t dma_dest,
dma_addr_t dma_src, size_t len, unsigned long flags);
void ioat2_issue_pending(struct dma_chan *chan);
int ioat2_alloc_chan_resources(struct dma_chan *c);
void ioat2_free_chan_resources(struct dma_chan *c);
enum dma_status ioat2_is_complete(struct dma_chan *c, dma_cookie_t cookie,
dma_cookie_t *done, dma_cookie_t *used);
void __ioat2_restart_chan(struct ioat2_dma_chan *ioat);
bool reshape_ring(struct ioat2_dma_chan *ioat, int order);
#endif /* IOATDMA_V2_H */ #endif /* IOATDMA_V2_H */
This diff is collapsed.
...@@ -36,7 +36,7 @@ ...@@ -36,7 +36,7 @@
#include "hw.h" #include "hw.h"
MODULE_VERSION(IOAT_DMA_VERSION); MODULE_VERSION(IOAT_DMA_VERSION);
MODULE_LICENSE("GPL"); MODULE_LICENSE("Dual BSD/GPL");
MODULE_AUTHOR("Intel Corporation"); MODULE_AUTHOR("Intel Corporation");
static struct pci_device_id ioat_pci_tbl[] = { static struct pci_device_id ioat_pci_tbl[] = {
......
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