···545455553.1 General format of the API:5656struct dma_async_tx_descriptor *5757-async_<operation>(<op specific parameters>,5858- enum async_tx_flags flags,5959- struct dma_async_tx_descriptor *dependency,6060- dma_async_tx_callback callback_routine,6161- void *callback_parameter);5757+async_<operation>(<op specific parameters>, struct async_submit ctl *submit)625863593.2 Supported operations:6464-memcpy - memory copy between a source and a destination buffer6565-memset - fill a destination buffer with a byte value6666-xor - xor a series of source buffers and write the result to a6767- destination buffer6868-xor_zero_sum - xor a series of source buffers and set a flag if the6969- result is zero. The implementation attempts to prevent7070- writes to memory6060+memcpy - memory copy between a source and a destination buffer6161+memset - fill a destination buffer with a byte value6262+xor - xor a series of source buffers and write the result to a6363+ destination buffer6464+xor_val - xor a series of source buffers and set a flag if the6565+ result is zero. The implementation attempts to prevent6666+ writes to memory6767+pq - generate the p+q (raid6 syndrome) from a series of source buffers6868+pq_val - validate that a p and or q buffer are in sync with a given series of6969+ sources7070+datap - (raid6_datap_recov) recover a raid6 data block and the p block7171+ from the given sources7272+2data - (raid6_2data_recov) recover 2 raid6 data blocks from the given7373+ sources717472753.3 Descriptor management:7376The return value is non-NULL and points to a 'descriptor' when the operation···8380recycle (or free) the descriptor. A descriptor can be acked by one of the8481following methods:85821/ setting the ASYNC_TX_ACK flag if no child operations are to be submitted8686-2/ setting the ASYNC_TX_DEP_ACK flag to acknowledge the parent8787- descriptor of a new operation.8383+2/ submitting an unacknowledged descriptor as a dependency to another8484+ async_tx call will implicitly set the acknowledged state.88853/ calling async_tx_ack() on the descriptor.898690873.4 When does the operation execute?···122119Perform a xor->copy->xor operation where each operation depends on the123120result from the previous operation:124121125125-void complete_xor_copy_xor(void *param)122122+void callback(void *param)126123{127127- printk("complete\n");124124+ struct completion *cmp = param;125125+126126+ complete(cmp);128127}129128130130-int run_xor_copy_xor(struct page **xor_srcs,131131- int xor_src_cnt,132132- struct page *xor_dest,133133- size_t xor_len,134134- struct page *copy_src,135135- struct page *copy_dest,136136- size_t copy_len)129129+void run_xor_copy_xor(struct page **xor_srcs,130130+ int xor_src_cnt,131131+ struct page *xor_dest,132132+ size_t xor_len,133133+ struct page *copy_src,134134+ struct page *copy_dest,135135+ size_t copy_len)137136{138137 struct dma_async_tx_descriptor *tx;138138+ addr_conv_t addr_conv[xor_src_cnt];139139+ struct async_submit_ctl submit;140140+ addr_conv_t addr_conv[NDISKS];141141+ struct completion cmp;139142140140- tx = async_xor(xor_dest, xor_srcs, 0, xor_src_cnt, xor_len,141141- ASYNC_TX_XOR_DROP_DST, NULL, NULL, NULL);142142- tx = async_memcpy(copy_dest, copy_src, 0, 0, copy_len,143143- ASYNC_TX_DEP_ACK, tx, NULL, NULL);144144- tx = async_xor(xor_dest, xor_srcs, 0, xor_src_cnt, xor_len,145145- ASYNC_TX_XOR_DROP_DST | ASYNC_TX_DEP_ACK | ASYNC_TX_ACK,146146- tx, complete_xor_copy_xor, NULL);143143+ init_async_submit(&submit, ASYNC_TX_XOR_DROP_DST, NULL, NULL, NULL,144144+ addr_conv);145145+ tx = async_xor(xor_dest, xor_srcs, 0, xor_src_cnt, xor_len, &submit)146146+147147+ submit->depend_tx = tx;148148+ tx = async_memcpy(copy_dest, copy_src, 0, 0, copy_len, &submit);149149+150150+ init_completion(&cmp);151151+ init_async_submit(&submit, ASYNC_TX_XOR_DROP_DST | ASYNC_TX_ACK, tx,152152+ callback, &cmp, addr_conv);153153+ tx = async_xor(xor_dest, xor_srcs, 0, xor_src_cnt, xor_len, &submit);147154148155 async_tx_issue_pending_all();156156+157157+ wait_for_completion(&cmp);149158}150159151160See include/linux/async_tx.h for more information on the flags. See the
···8686 * @idx: pool index8787 * @unmap_src_cnt: number of xor sources8888 * @unmap_len: transaction bytecount8989+ * @tx_list: list of descriptors that are associated with one operation8990 * @async_tx: support for the async_tx api9091 * @group_list: list of slots that make up a multi-descriptor transaction9192 * for example transfer lengths larger than the supported hw max···103102 u16 idx;104103 u16 unmap_src_cnt;105104 size_t unmap_len;105105+ struct list_head tx_list;106106 struct dma_async_tx_descriptor async_tx;107107 union {108108 u32 *xor_check_result;109109 u32 *crc32_result;110110+ u32 *pq_check_result;110111 };111112};112113
···11+/*22+ * Freescale MPC83XX / MPC85XX DMA Controller33+ *44+ * Copyright (c) 2009 Ira W. Snyder <iws@ovro.caltech.edu>55+ *66+ * This file is licensed under the terms of the GNU General Public License77+ * version 2. This program is licensed "as is" without any warranty of any88+ * kind, whether express or implied.99+ */1010+1111+#ifndef __ARCH_POWERPC_ASM_FSLDMA_H__1212+#define __ARCH_POWERPC_ASM_FSLDMA_H__1313+1414+#include <linux/dmaengine.h>1515+1616+/*1717+ * Definitions for the Freescale DMA controller's DMA_SLAVE implemention1818+ *1919+ * The Freescale DMA_SLAVE implementation was designed to handle many-to-many2020+ * transfers. An example usage would be an accelerated copy between two2121+ * scatterlists. Another example use would be an accelerated copy from2222+ * multiple non-contiguous device buffers into a single scatterlist.2323+ *2424+ * A DMA_SLAVE transaction is defined by a struct fsl_dma_slave. This2525+ * structure contains a list of hardware addresses that should be copied2626+ * to/from the scatterlist passed into device_prep_slave_sg(). The structure2727+ * also has some fields to enable hardware-specific features.2828+ */2929+3030+/**3131+ * struct fsl_dma_hw_addr3232+ * @entry: linked list entry3333+ * @address: the hardware address3434+ * @length: length to transfer3535+ *3636+ * Holds a single physical hardware address / length pair for use3737+ * with the DMAEngine DMA_SLAVE API.3838+ */3939+struct fsl_dma_hw_addr {4040+ struct list_head entry;4141+4242+ dma_addr_t address;4343+ size_t length;4444+};4545+4646+/**4747+ * struct fsl_dma_slave4848+ * @addresses: a linked list of struct fsl_dma_hw_addr structures4949+ * @request_count: value for DMA request count5050+ * @src_loop_size: setup and enable constant source-address DMA transfers5151+ * @dst_loop_size: setup and enable constant destination address DMA transfers5252+ * @external_start: enable externally started DMA transfers5353+ * @external_pause: enable externally paused DMA transfers5454+ *5555+ * Holds a list of address / length pairs for use with the DMAEngine5656+ * DMA_SLAVE API implementation for the Freescale DMA controller.5757+ */5858+struct fsl_dma_slave {5959+6060+ /* List of hardware address/length pairs */6161+ struct list_head addresses;6262+6363+ /* Support for extra controller features */6464+ unsigned int request_count;6565+ unsigned int src_loop_size;6666+ unsigned int dst_loop_size;6767+ bool external_start;6868+ bool external_pause;6969+};7070+7171+/**7272+ * fsl_dma_slave_append - add an address/length pair to a struct fsl_dma_slave7373+ * @slave: the &struct fsl_dma_slave to add to7474+ * @address: the hardware address to add7575+ * @length: the length of bytes to transfer from @address7676+ *7777+ * Add a hardware address/length pair to a struct fsl_dma_slave. Returns 0 on7878+ * success, -ERRNO otherwise.7979+ */8080+static inline int fsl_dma_slave_append(struct fsl_dma_slave *slave,8181+ dma_addr_t address, size_t length)8282+{8383+ struct fsl_dma_hw_addr *addr;8484+8585+ addr = kzalloc(sizeof(*addr), GFP_ATOMIC);8686+ if (!addr)8787+ return -ENOMEM;8888+8989+ INIT_LIST_HEAD(&addr->entry);9090+ addr->address = address;9191+ addr->length = length;9292+9393+ list_add_tail(&addr->entry, &slave->addresses);9494+ return 0;9595+}9696+9797+/**9898+ * fsl_dma_slave_free - free a struct fsl_dma_slave9999+ * @slave: the struct fsl_dma_slave to free100100+ *101101+ * Free a struct fsl_dma_slave and all associated address/length pairs102102+ */103103+static inline void fsl_dma_slave_free(struct fsl_dma_slave *slave)104104+{105105+ struct fsl_dma_hw_addr *addr, *tmp;106106+107107+ if (slave) {108108+ list_for_each_entry_safe(addr, tmp, &slave->addresses, entry) {109109+ list_del(&addr->entry);110110+ kfree(addr);111111+ }112112+113113+ kfree(slave);114114+ }115115+}116116+117117+/**118118+ * fsl_dma_slave_alloc - allocate a struct fsl_dma_slave119119+ * @gfp: the flags to pass to kmalloc when allocating this structure120120+ *121121+ * Allocate a struct fsl_dma_slave for use by the DMA_SLAVE API. Returns a new122122+ * struct fsl_dma_slave on success, or NULL on failure.123123+ */124124+static inline struct fsl_dma_slave *fsl_dma_slave_alloc(gfp_t gfp)125125+{126126+ struct fsl_dma_slave *slave;127127+128128+ slave = kzalloc(sizeof(*slave), gfp);129129+ if (!slave)130130+ return NULL;131131+132132+ INIT_LIST_HEAD(&slave->addresses);133133+ return slave;134134+}135135+136136+#endif /* __ARCH_POWERPC_ASM_FSLDMA_H__ */
+9-3
arch/sh/drivers/dma/Kconfig
···11menu "DMA support"2233-config SH_DMA_API44- bool5364config SH_DMA75 bool "SuperH on-chip DMA controller (DMAC) support"86 depends on CPU_SH3 || CPU_SH499- select SH_DMA_API107 default n118129config SH_DMA_IRQ_MULTI···1518 CPU_SUBTYPE_SH7763 || CPU_SUBTYPE_SH7764 || \1619 CPU_SUBTYPE_SH7780 || CPU_SUBTYPE_SH7785 || \1720 CPU_SUBTYPE_SH77602121+2222+config SH_DMA_API2323+ depends on SH_DMA2424+ bool "SuperH DMA API support"2525+ default n2626+ help2727+ SH_DMA_API always enabled DMA API of used SuperH.2828+ If you want to use DMA ENGINE, you must not enable this.2929+ Please enable DMA_ENGINE and SH_DMAE.18301931config NR_ONCHIP_DMA_CHANNELS2032 int
+1-2
arch/sh/drivers/dma/Makefile
···22# Makefile for the SuperH DMA specific kernel interface routines under Linux.33#4455-obj-$(CONFIG_SH_DMA_API) += dma-api.o dma-sysfs.o66-obj-$(CONFIG_SH_DMA) += dma-sh.o55+obj-$(CONFIG_SH_DMA_API) += dma-sh.o dma-api.o dma-sysfs.o76obj-$(CONFIG_PVR2_DMA) += dma-pvr2.o87obj-$(CONFIG_G2_DMA) += dma-g2.o98obj-$(CONFIG_SH_DMABRG) += dmabrg.o
···3333 * async_memcpy - attempt to copy memory with a dma engine.3434 * @dest: destination page3535 * @src: src page3636- * @offset: offset in pages to start transaction3636+ * @dest_offset: offset into 'dest' to start transaction3737+ * @src_offset: offset into 'src' to start transaction3738 * @len: length in bytes3838- * @flags: ASYNC_TX_ACK, ASYNC_TX_DEP_ACK,3939- * @depend_tx: memcpy depends on the result of this transaction4040- * @cb_fn: function to call when the memcpy completes4141- * @cb_param: parameter to pass to the callback routine3939+ * @submit: submission / completion modifiers4040+ *4141+ * honored flags: ASYNC_TX_ACK4242 */4343struct dma_async_tx_descriptor *4444async_memcpy(struct page *dest, struct page *src, unsigned int dest_offset,4545- unsigned int src_offset, size_t len, enum async_tx_flags flags,4646- struct dma_async_tx_descriptor *depend_tx,4747- dma_async_tx_callback cb_fn, void *cb_param)4545+ unsigned int src_offset, size_t len,4646+ struct async_submit_ctl *submit)4847{4949- struct dma_chan *chan = async_tx_find_channel(depend_tx, DMA_MEMCPY,4848+ struct dma_chan *chan = async_tx_find_channel(submit, DMA_MEMCPY,5049 &dest, 1, &src, 1, len);5150 struct dma_device *device = chan ? chan->device : NULL;5251 struct dma_async_tx_descriptor *tx = NULL;53525454- if (device) {5353+ if (device && is_dma_copy_aligned(device, src_offset, dest_offset, len)) {5554 dma_addr_t dma_dest, dma_src;5656- unsigned long dma_prep_flags = cb_fn ? DMA_PREP_INTERRUPT : 0;5555+ unsigned long dma_prep_flags = 0;57565757+ if (submit->cb_fn)5858+ dma_prep_flags |= DMA_PREP_INTERRUPT;5959+ if (submit->flags & ASYNC_TX_FENCE)6060+ dma_prep_flags |= DMA_PREP_FENCE;5861 dma_dest = dma_map_page(device->dev, dest, dest_offset, len,5962 DMA_FROM_DEVICE);6063···70677168 if (tx) {7269 pr_debug("%s: (async) len: %zu\n", __func__, len);7373- async_tx_submit(chan, tx, flags, depend_tx, cb_fn, cb_param);7070+ async_tx_submit(chan, tx, submit);7471 } else {7572 void *dest_buf, *src_buf;7673 pr_debug("%s: (sync) len: %zu\n", __func__, len);77747875 /* wait for any prerequisite operations */7979- async_tx_quiesce(&depend_tx);7676+ async_tx_quiesce(&submit->depend_tx);80778178 dest_buf = kmap_atomic(dest, KM_USER0) + dest_offset;8279 src_buf = kmap_atomic(src, KM_USER1) + src_offset;···8683 kunmap_atomic(dest_buf, KM_USER0);8784 kunmap_atomic(src_buf, KM_USER1);88858989- async_tx_sync_epilog(cb_fn, cb_param);8686+ async_tx_sync_epilog(submit);9087 }91889289 return tx;9390}9491EXPORT_SYMBOL_GPL(async_memcpy);9595-9696-static int __init async_memcpy_init(void)9797-{9898- return 0;9999-}100100-101101-static void __exit async_memcpy_exit(void)102102-{103103- do { } while (0);104104-}105105-106106-module_init(async_memcpy_init);107107-module_exit(async_memcpy_exit);1089210993MODULE_AUTHOR("Intel Corporation");11094MODULE_DESCRIPTION("asynchronous memcpy api");
+15-28
crypto/async_tx/async_memset.c
···3535 * @val: fill value3636 * @offset: offset in pages to start transaction3737 * @len: length in bytes3838- * @flags: ASYNC_TX_ACK, ASYNC_TX_DEP_ACK3939- * @depend_tx: memset depends on the result of this transaction4040- * @cb_fn: function to call when the memcpy completes4141- * @cb_param: parameter to pass to the callback routine3838+ *3939+ * honored flags: ASYNC_TX_ACK4240 */4341struct dma_async_tx_descriptor *4444-async_memset(struct page *dest, int val, unsigned int offset,4545- size_t len, enum async_tx_flags flags,4646- struct dma_async_tx_descriptor *depend_tx,4747- dma_async_tx_callback cb_fn, void *cb_param)4242+async_memset(struct page *dest, int val, unsigned int offset, size_t len,4343+ struct async_submit_ctl *submit)4844{4949- struct dma_chan *chan = async_tx_find_channel(depend_tx, DMA_MEMSET,4545+ struct dma_chan *chan = async_tx_find_channel(submit, DMA_MEMSET,5046 &dest, 1, NULL, 0, len);5147 struct dma_device *device = chan ? chan->device : NULL;5248 struct dma_async_tx_descriptor *tx = NULL;53495454- if (device) {5050+ if (device && is_dma_fill_aligned(device, offset, 0, len)) {5551 dma_addr_t dma_dest;5656- unsigned long dma_prep_flags = cb_fn ? DMA_PREP_INTERRUPT : 0;5252+ unsigned long dma_prep_flags = 0;57535454+ if (submit->cb_fn)5555+ dma_prep_flags |= DMA_PREP_INTERRUPT;5656+ if (submit->flags & ASYNC_TX_FENCE)5757+ dma_prep_flags |= DMA_PREP_FENCE;5858 dma_dest = dma_map_page(device->dev, dest, offset, len,5959 DMA_FROM_DEVICE);6060···64646565 if (tx) {6666 pr_debug("%s: (async) len: %zu\n", __func__, len);6767- async_tx_submit(chan, tx, flags, depend_tx, cb_fn, cb_param);6767+ async_tx_submit(chan, tx, submit);6868 } else { /* run the memset synchronously */6969 void *dest_buf;7070 pr_debug("%s: (sync) len: %zu\n", __func__, len);71717272- dest_buf = (void *) (((char *) page_address(dest)) + offset);7272+ dest_buf = page_address(dest) + offset;73737474 /* wait for any prerequisite operations */7575- async_tx_quiesce(&depend_tx);7575+ async_tx_quiesce(&submit->depend_tx);76767777 memset(dest_buf, val, len);78787979- async_tx_sync_epilog(cb_fn, cb_param);7979+ async_tx_sync_epilog(submit);8080 }81818282 return tx;8383}8484EXPORT_SYMBOL_GPL(async_memset);8585-8686-static int __init async_memset_init(void)8787-{8888- return 0;8989-}9090-9191-static void __exit async_memset_exit(void)9292-{9393- do { } while (0);9494-}9595-9696-module_init(async_memset_init);9797-module_exit(async_memset_exit);98859986MODULE_AUTHOR("Intel Corporation");10087MODULE_DESCRIPTION("asynchronous memset api");
+395
crypto/async_tx/async_pq.c
···11+/*22+ * Copyright(c) 2007 Yuri Tikhonov <yur@emcraft.com>33+ * Copyright(c) 2009 Intel Corporation44+ *55+ * This program is free software; you can redistribute it and/or modify it66+ * under the terms of the GNU General Public License as published by the Free77+ * Software Foundation; either version 2 of the License, or (at your option)88+ * any later version.99+ *1010+ * This program is distributed in the hope that it will be useful, but WITHOUT1111+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or1212+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for1313+ * more details.1414+ *1515+ * You should have received a copy of the GNU General Public License along with1616+ * this program; if not, write to the Free Software Foundation, Inc., 591717+ * Temple Place - Suite 330, Boston, MA 02111-1307, USA.1818+ *1919+ * The full GNU General Public License is included in this distribution in the2020+ * file called COPYING.2121+ */2222+#include <linux/kernel.h>2323+#include <linux/interrupt.h>2424+#include <linux/dma-mapping.h>2525+#include <linux/raid/pq.h>2626+#include <linux/async_tx.h>2727+2828+/**2929+ * scribble - space to hold throwaway P buffer for synchronous gen_syndrome3030+ */3131+static struct page *scribble;3232+3333+static bool is_raid6_zero_block(struct page *p)3434+{3535+ return p == (void *) raid6_empty_zero_page;3636+}3737+3838+/* the struct page *blocks[] parameter passed to async_gen_syndrome()3939+ * and async_syndrome_val() contains the 'P' destination address at4040+ * blocks[disks-2] and the 'Q' destination address at blocks[disks-1]4141+ *4242+ * note: these are macros as they are used as lvalues4343+ */4444+#define P(b, d) (b[d-2])4545+#define Q(b, d) (b[d-1])4646+4747+/**4848+ * do_async_gen_syndrome - asynchronously calculate P and/or Q4949+ */5050+static __async_inline struct dma_async_tx_descriptor *5151+do_async_gen_syndrome(struct dma_chan *chan, struct page **blocks,5252+ const unsigned char *scfs, unsigned int offset, int disks,5353+ size_t len, dma_addr_t *dma_src,5454+ struct async_submit_ctl *submit)5555+{5656+ struct dma_async_tx_descriptor *tx = NULL;5757+ struct dma_device *dma = chan->device;5858+ enum dma_ctrl_flags dma_flags = 0;5959+ enum async_tx_flags flags_orig = submit->flags;6060+ dma_async_tx_callback cb_fn_orig = submit->cb_fn;6161+ dma_async_tx_callback cb_param_orig = submit->cb_param;6262+ int src_cnt = disks - 2;6363+ unsigned char coefs[src_cnt];6464+ unsigned short pq_src_cnt;6565+ dma_addr_t dma_dest[2];6666+ int src_off = 0;6767+ int idx;6868+ int i;6969+7070+ /* DMAs use destinations as sources, so use BIDIRECTIONAL mapping */7171+ if (P(blocks, disks))7272+ dma_dest[0] = dma_map_page(dma->dev, P(blocks, disks), offset,7373+ len, DMA_BIDIRECTIONAL);7474+ else7575+ dma_flags |= DMA_PREP_PQ_DISABLE_P;7676+ if (Q(blocks, disks))7777+ dma_dest[1] = dma_map_page(dma->dev, Q(blocks, disks), offset,7878+ len, DMA_BIDIRECTIONAL);7979+ else8080+ dma_flags |= DMA_PREP_PQ_DISABLE_Q;8181+8282+ /* convert source addresses being careful to collapse 'empty'8383+ * sources and update the coefficients accordingly8484+ */8585+ for (i = 0, idx = 0; i < src_cnt; i++) {8686+ if (is_raid6_zero_block(blocks[i]))8787+ continue;8888+ dma_src[idx] = dma_map_page(dma->dev, blocks[i], offset, len,8989+ DMA_TO_DEVICE);9090+ coefs[idx] = scfs[i];9191+ idx++;9292+ }9393+ src_cnt = idx;9494+9595+ while (src_cnt > 0) {9696+ submit->flags = flags_orig;9797+ pq_src_cnt = min(src_cnt, dma_maxpq(dma, dma_flags));9898+ /* if we are submitting additional pqs, leave the chain open,9999+ * clear the callback parameters, and leave the destination100100+ * buffers mapped101101+ */102102+ if (src_cnt > pq_src_cnt) {103103+ submit->flags &= ~ASYNC_TX_ACK;104104+ submit->flags |= ASYNC_TX_FENCE;105105+ dma_flags |= DMA_COMPL_SKIP_DEST_UNMAP;106106+ submit->cb_fn = NULL;107107+ submit->cb_param = NULL;108108+ } else {109109+ dma_flags &= ~DMA_COMPL_SKIP_DEST_UNMAP;110110+ submit->cb_fn = cb_fn_orig;111111+ submit->cb_param = cb_param_orig;112112+ if (cb_fn_orig)113113+ dma_flags |= DMA_PREP_INTERRUPT;114114+ }115115+ if (submit->flags & ASYNC_TX_FENCE)116116+ dma_flags |= DMA_PREP_FENCE;117117+118118+ /* Since we have clobbered the src_list we are committed119119+ * to doing this asynchronously. Drivers force forward120120+ * progress in case they can not provide a descriptor121121+ */122122+ for (;;) {123123+ tx = dma->device_prep_dma_pq(chan, dma_dest,124124+ &dma_src[src_off],125125+ pq_src_cnt,126126+ &coefs[src_off], len,127127+ dma_flags);128128+ if (likely(tx))129129+ break;130130+ async_tx_quiesce(&submit->depend_tx);131131+ dma_async_issue_pending(chan);132132+ }133133+134134+ async_tx_submit(chan, tx, submit);135135+ submit->depend_tx = tx;136136+137137+ /* drop completed sources */138138+ src_cnt -= pq_src_cnt;139139+ src_off += pq_src_cnt;140140+141141+ dma_flags |= DMA_PREP_CONTINUE;142142+ }143143+144144+ return tx;145145+}146146+147147+/**148148+ * do_sync_gen_syndrome - synchronously calculate a raid6 syndrome149149+ */150150+static void151151+do_sync_gen_syndrome(struct page **blocks, unsigned int offset, int disks,152152+ size_t len, struct async_submit_ctl *submit)153153+{154154+ void **srcs;155155+ int i;156156+157157+ if (submit->scribble)158158+ srcs = submit->scribble;159159+ else160160+ srcs = (void **) blocks;161161+162162+ for (i = 0; i < disks; i++) {163163+ if (is_raid6_zero_block(blocks[i])) {164164+ BUG_ON(i > disks - 3); /* P or Q can't be zero */165165+ srcs[i] = blocks[i];166166+ } else167167+ srcs[i] = page_address(blocks[i]) + offset;168168+ }169169+ raid6_call.gen_syndrome(disks, len, srcs);170170+ async_tx_sync_epilog(submit);171171+}172172+173173+/**174174+ * async_gen_syndrome - asynchronously calculate a raid6 syndrome175175+ * @blocks: source blocks from idx 0..disks-3, P @ disks-2 and Q @ disks-1176176+ * @offset: common offset into each block (src and dest) to start transaction177177+ * @disks: number of blocks (including missing P or Q, see below)178178+ * @len: length of operation in bytes179179+ * @submit: submission/completion modifiers180180+ *181181+ * General note: This routine assumes a field of GF(2^8) with a182182+ * primitive polynomial of 0x11d and a generator of {02}.183183+ *184184+ * 'disks' note: callers can optionally omit either P or Q (but not185185+ * both) from the calculation by setting blocks[disks-2] or186186+ * blocks[disks-1] to NULL. When P or Q is omitted 'len' must be <=187187+ * PAGE_SIZE as a temporary buffer of this size is used in the188188+ * synchronous path. 'disks' always accounts for both destination189189+ * buffers.190190+ *191191+ * 'blocks' note: if submit->scribble is NULL then the contents of192192+ * 'blocks' may be overridden193193+ */194194+struct dma_async_tx_descriptor *195195+async_gen_syndrome(struct page **blocks, unsigned int offset, int disks,196196+ size_t len, struct async_submit_ctl *submit)197197+{198198+ int src_cnt = disks - 2;199199+ struct dma_chan *chan = async_tx_find_channel(submit, DMA_PQ,200200+ &P(blocks, disks), 2,201201+ blocks, src_cnt, len);202202+ struct dma_device *device = chan ? chan->device : NULL;203203+ dma_addr_t *dma_src = NULL;204204+205205+ BUG_ON(disks > 255 || !(P(blocks, disks) || Q(blocks, disks)));206206+207207+ if (submit->scribble)208208+ dma_src = submit->scribble;209209+ else if (sizeof(dma_addr_t) <= sizeof(struct page *))210210+ dma_src = (dma_addr_t *) blocks;211211+212212+ if (dma_src && device &&213213+ (src_cnt <= dma_maxpq(device, 0) ||214214+ dma_maxpq(device, DMA_PREP_CONTINUE) > 0) &&215215+ is_dma_pq_aligned(device, offset, 0, len)) {216216+ /* run the p+q asynchronously */217217+ pr_debug("%s: (async) disks: %d len: %zu\n",218218+ __func__, disks, len);219219+ return do_async_gen_syndrome(chan, blocks, raid6_gfexp, offset,220220+ disks, len, dma_src, submit);221221+ }222222+223223+ /* run the pq synchronously */224224+ pr_debug("%s: (sync) disks: %d len: %zu\n", __func__, disks, len);225225+226226+ /* wait for any prerequisite operations */227227+ async_tx_quiesce(&submit->depend_tx);228228+229229+ if (!P(blocks, disks)) {230230+ P(blocks, disks) = scribble;231231+ BUG_ON(len + offset > PAGE_SIZE);232232+ }233233+ if (!Q(blocks, disks)) {234234+ Q(blocks, disks) = scribble;235235+ BUG_ON(len + offset > PAGE_SIZE);236236+ }237237+ do_sync_gen_syndrome(blocks, offset, disks, len, submit);238238+239239+ return NULL;240240+}241241+EXPORT_SYMBOL_GPL(async_gen_syndrome);242242+243243+/**244244+ * async_syndrome_val - asynchronously validate a raid6 syndrome245245+ * @blocks: source blocks from idx 0..disks-3, P @ disks-2 and Q @ disks-1246246+ * @offset: common offset into each block (src and dest) to start transaction247247+ * @disks: number of blocks (including missing P or Q, see below)248248+ * @len: length of operation in bytes249249+ * @pqres: on val failure SUM_CHECK_P_RESULT and/or SUM_CHECK_Q_RESULT are set250250+ * @spare: temporary result buffer for the synchronous case251251+ * @submit: submission / completion modifiers252252+ *253253+ * The same notes from async_gen_syndrome apply to the 'blocks',254254+ * and 'disks' parameters of this routine. The synchronous path255255+ * requires a temporary result buffer and submit->scribble to be256256+ * specified.257257+ */258258+struct dma_async_tx_descriptor *259259+async_syndrome_val(struct page **blocks, unsigned int offset, int disks,260260+ size_t len, enum sum_check_flags *pqres, struct page *spare,261261+ struct async_submit_ctl *submit)262262+{263263+ struct dma_chan *chan = async_tx_find_channel(submit, DMA_PQ_VAL,264264+ NULL, 0, blocks, disks,265265+ len);266266+ struct dma_device *device = chan ? chan->device : NULL;267267+ struct dma_async_tx_descriptor *tx;268268+ enum dma_ctrl_flags dma_flags = submit->cb_fn ? DMA_PREP_INTERRUPT : 0;269269+ dma_addr_t *dma_src = NULL;270270+271271+ BUG_ON(disks < 4);272272+273273+ if (submit->scribble)274274+ dma_src = submit->scribble;275275+ else if (sizeof(dma_addr_t) <= sizeof(struct page *))276276+ dma_src = (dma_addr_t *) blocks;277277+278278+ if (dma_src && device && disks <= dma_maxpq(device, 0) &&279279+ is_dma_pq_aligned(device, offset, 0, len)) {280280+ struct device *dev = device->dev;281281+ dma_addr_t *pq = &dma_src[disks-2];282282+ int i;283283+284284+ pr_debug("%s: (async) disks: %d len: %zu\n",285285+ __func__, disks, len);286286+ if (!P(blocks, disks))287287+ dma_flags |= DMA_PREP_PQ_DISABLE_P;288288+ if (!Q(blocks, disks))289289+ dma_flags |= DMA_PREP_PQ_DISABLE_Q;290290+ if (submit->flags & ASYNC_TX_FENCE)291291+ dma_flags |= DMA_PREP_FENCE;292292+ for (i = 0; i < disks; i++)293293+ if (likely(blocks[i])) {294294+ BUG_ON(is_raid6_zero_block(blocks[i]));295295+ dma_src[i] = dma_map_page(dev, blocks[i],296296+ offset, len,297297+ DMA_TO_DEVICE);298298+ }299299+300300+ for (;;) {301301+ tx = device->device_prep_dma_pq_val(chan, pq, dma_src,302302+ disks - 2,303303+ raid6_gfexp,304304+ len, pqres,305305+ dma_flags);306306+ if (likely(tx))307307+ break;308308+ async_tx_quiesce(&submit->depend_tx);309309+ dma_async_issue_pending(chan);310310+ }311311+ async_tx_submit(chan, tx, submit);312312+313313+ return tx;314314+ } else {315315+ struct page *p_src = P(blocks, disks);316316+ struct page *q_src = Q(blocks, disks);317317+ enum async_tx_flags flags_orig = submit->flags;318318+ dma_async_tx_callback cb_fn_orig = submit->cb_fn;319319+ void *scribble = submit->scribble;320320+ void *cb_param_orig = submit->cb_param;321321+ void *p, *q, *s;322322+323323+ pr_debug("%s: (sync) disks: %d len: %zu\n",324324+ __func__, disks, len);325325+326326+ /* caller must provide a temporary result buffer and327327+ * allow the input parameters to be preserved328328+ */329329+ BUG_ON(!spare || !scribble);330330+331331+ /* wait for any prerequisite operations */332332+ async_tx_quiesce(&submit->depend_tx);333333+334334+ /* recompute p and/or q into the temporary buffer and then335335+ * check to see the result matches the current value336336+ */337337+ tx = NULL;338338+ *pqres = 0;339339+ if (p_src) {340340+ init_async_submit(submit, ASYNC_TX_XOR_ZERO_DST, NULL,341341+ NULL, NULL, scribble);342342+ tx = async_xor(spare, blocks, offset, disks-2, len, submit);343343+ async_tx_quiesce(&tx);344344+ p = page_address(p_src) + offset;345345+ s = page_address(spare) + offset;346346+ *pqres |= !!memcmp(p, s, len) << SUM_CHECK_P;347347+ }348348+349349+ if (q_src) {350350+ P(blocks, disks) = NULL;351351+ Q(blocks, disks) = spare;352352+ init_async_submit(submit, 0, NULL, NULL, NULL, scribble);353353+ tx = async_gen_syndrome(blocks, offset, disks, len, submit);354354+ async_tx_quiesce(&tx);355355+ q = page_address(q_src) + offset;356356+ s = page_address(spare) + offset;357357+ *pqres |= !!memcmp(q, s, len) << SUM_CHECK_Q;358358+ }359359+360360+ /* restore P, Q and submit */361361+ P(blocks, disks) = p_src;362362+ Q(blocks, disks) = q_src;363363+364364+ submit->cb_fn = cb_fn_orig;365365+ submit->cb_param = cb_param_orig;366366+ submit->flags = flags_orig;367367+ async_tx_sync_epilog(submit);368368+369369+ return NULL;370370+ }371371+}372372+EXPORT_SYMBOL_GPL(async_syndrome_val);373373+374374+static int __init async_pq_init(void)375375+{376376+ scribble = alloc_page(GFP_KERNEL);377377+378378+ if (scribble)379379+ return 0;380380+381381+ pr_err("%s: failed to allocate required spare page\n", __func__);382382+383383+ return -ENOMEM;384384+}385385+386386+static void __exit async_pq_exit(void)387387+{388388+ put_page(scribble);389389+}390390+391391+module_init(async_pq_init);392392+module_exit(async_pq_exit);393393+394394+MODULE_DESCRIPTION("asynchronous raid6 syndrome generation/validation");395395+MODULE_LICENSE("GPL");
+468
crypto/async_tx/async_raid6_recov.c
···11+/*22+ * Asynchronous RAID-6 recovery calculations ASYNC_TX API.33+ * Copyright(c) 2009 Intel Corporation44+ *55+ * based on raid6recov.c:66+ * Copyright 2002 H. Peter Anvin77+ *88+ * This program is free software; you can redistribute it and/or modify it99+ * under the terms of the GNU General Public License as published by the Free1010+ * Software Foundation; either version 2 of the License, or (at your option)1111+ * any later version.1212+ *1313+ * This program is distributed in the hope that it will be useful, but WITHOUT1414+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or1515+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for1616+ * more details.1717+ *1818+ * You should have received a copy of the GNU General Public License along with1919+ * this program; if not, write to the Free Software Foundation, Inc., 512020+ * Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.2121+ *2222+ */2323+#include <linux/kernel.h>2424+#include <linux/interrupt.h>2525+#include <linux/dma-mapping.h>2626+#include <linux/raid/pq.h>2727+#include <linux/async_tx.h>2828+2929+static struct dma_async_tx_descriptor *3030+async_sum_product(struct page *dest, struct page **srcs, unsigned char *coef,3131+ size_t len, struct async_submit_ctl *submit)3232+{3333+ struct dma_chan *chan = async_tx_find_channel(submit, DMA_PQ,3434+ &dest, 1, srcs, 2, len);3535+ struct dma_device *dma = chan ? chan->device : NULL;3636+ const u8 *amul, *bmul;3737+ u8 ax, bx;3838+ u8 *a, *b, *c;3939+4040+ if (dma) {4141+ dma_addr_t dma_dest[2];4242+ dma_addr_t dma_src[2];4343+ struct device *dev = dma->dev;4444+ struct dma_async_tx_descriptor *tx;4545+ enum dma_ctrl_flags dma_flags = DMA_PREP_PQ_DISABLE_P;4646+4747+ if (submit->flags & ASYNC_TX_FENCE)4848+ dma_flags |= DMA_PREP_FENCE;4949+ dma_dest[1] = dma_map_page(dev, dest, 0, len, DMA_BIDIRECTIONAL);5050+ dma_src[0] = dma_map_page(dev, srcs[0], 0, len, DMA_TO_DEVICE);5151+ dma_src[1] = dma_map_page(dev, srcs[1], 0, len, DMA_TO_DEVICE);5252+ tx = dma->device_prep_dma_pq(chan, dma_dest, dma_src, 2, coef,5353+ len, dma_flags);5454+ if (tx) {5555+ async_tx_submit(chan, tx, submit);5656+ return tx;5757+ }5858+5959+ /* could not get a descriptor, unmap and fall through to6060+ * the synchronous path6161+ */6262+ dma_unmap_page(dev, dma_dest[1], len, DMA_BIDIRECTIONAL);6363+ dma_unmap_page(dev, dma_src[0], len, DMA_TO_DEVICE);6464+ dma_unmap_page(dev, dma_src[1], len, DMA_TO_DEVICE);6565+ }6666+6767+ /* run the operation synchronously */6868+ async_tx_quiesce(&submit->depend_tx);6969+ amul = raid6_gfmul[coef[0]];7070+ bmul = raid6_gfmul[coef[1]];7171+ a = page_address(srcs[0]);7272+ b = page_address(srcs[1]);7373+ c = page_address(dest);7474+7575+ while (len--) {7676+ ax = amul[*a++];7777+ bx = bmul[*b++];7878+ *c++ = ax ^ bx;7979+ }8080+8181+ return NULL;8282+}8383+8484+static struct dma_async_tx_descriptor *8585+async_mult(struct page *dest, struct page *src, u8 coef, size_t len,8686+ struct async_submit_ctl *submit)8787+{8888+ struct dma_chan *chan = async_tx_find_channel(submit, DMA_PQ,8989+ &dest, 1, &src, 1, len);9090+ struct dma_device *dma = chan ? chan->device : NULL;9191+ const u8 *qmul; /* Q multiplier table */9292+ u8 *d, *s;9393+9494+ if (dma) {9595+ dma_addr_t dma_dest[2];9696+ dma_addr_t dma_src[1];9797+ struct device *dev = dma->dev;9898+ struct dma_async_tx_descriptor *tx;9999+ enum dma_ctrl_flags dma_flags = DMA_PREP_PQ_DISABLE_P;100100+101101+ if (submit->flags & ASYNC_TX_FENCE)102102+ dma_flags |= DMA_PREP_FENCE;103103+ dma_dest[1] = dma_map_page(dev, dest, 0, len, DMA_BIDIRECTIONAL);104104+ dma_src[0] = dma_map_page(dev, src, 0, len, DMA_TO_DEVICE);105105+ tx = dma->device_prep_dma_pq(chan, dma_dest, dma_src, 1, &coef,106106+ len, dma_flags);107107+ if (tx) {108108+ async_tx_submit(chan, tx, submit);109109+ return tx;110110+ }111111+112112+ /* could not get a descriptor, unmap and fall through to113113+ * the synchronous path114114+ */115115+ dma_unmap_page(dev, dma_dest[1], len, DMA_BIDIRECTIONAL);116116+ dma_unmap_page(dev, dma_src[0], len, DMA_TO_DEVICE);117117+ }118118+119119+ /* no channel available, or failed to allocate a descriptor, so120120+ * perform the operation synchronously121121+ */122122+ async_tx_quiesce(&submit->depend_tx);123123+ qmul = raid6_gfmul[coef];124124+ d = page_address(dest);125125+ s = page_address(src);126126+127127+ while (len--)128128+ *d++ = qmul[*s++];129129+130130+ return NULL;131131+}132132+133133+static struct dma_async_tx_descriptor *134134+__2data_recov_4(size_t bytes, int faila, int failb, struct page **blocks,135135+ struct async_submit_ctl *submit)136136+{137137+ struct dma_async_tx_descriptor *tx = NULL;138138+ struct page *p, *q, *a, *b;139139+ struct page *srcs[2];140140+ unsigned char coef[2];141141+ enum async_tx_flags flags = submit->flags;142142+ dma_async_tx_callback cb_fn = submit->cb_fn;143143+ void *cb_param = submit->cb_param;144144+ void *scribble = submit->scribble;145145+146146+ p = blocks[4-2];147147+ q = blocks[4-1];148148+149149+ a = blocks[faila];150150+ b = blocks[failb];151151+152152+ /* in the 4 disk case P + Pxy == P and Q + Qxy == Q */153153+ /* Dx = A*(P+Pxy) + B*(Q+Qxy) */154154+ srcs[0] = p;155155+ srcs[1] = q;156156+ coef[0] = raid6_gfexi[failb-faila];157157+ coef[1] = raid6_gfinv[raid6_gfexp[faila]^raid6_gfexp[failb]];158158+ init_async_submit(submit, ASYNC_TX_FENCE, tx, NULL, NULL, scribble);159159+ tx = async_sum_product(b, srcs, coef, bytes, submit);160160+161161+ /* Dy = P+Pxy+Dx */162162+ srcs[0] = p;163163+ srcs[1] = b;164164+ init_async_submit(submit, flags | ASYNC_TX_XOR_ZERO_DST, tx, cb_fn,165165+ cb_param, scribble);166166+ tx = async_xor(a, srcs, 0, 2, bytes, submit);167167+168168+ return tx;169169+170170+}171171+172172+static struct dma_async_tx_descriptor *173173+__2data_recov_5(size_t bytes, int faila, int failb, struct page **blocks,174174+ struct async_submit_ctl *submit)175175+{176176+ struct dma_async_tx_descriptor *tx = NULL;177177+ struct page *p, *q, *g, *dp, *dq;178178+ struct page *srcs[2];179179+ unsigned char coef[2];180180+ enum async_tx_flags flags = submit->flags;181181+ dma_async_tx_callback cb_fn = submit->cb_fn;182182+ void *cb_param = submit->cb_param;183183+ void *scribble = submit->scribble;184184+ int uninitialized_var(good);185185+ int i;186186+187187+ for (i = 0; i < 3; i++) {188188+ if (i == faila || i == failb)189189+ continue;190190+ else {191191+ good = i;192192+ break;193193+ }194194+ }195195+ BUG_ON(i >= 3);196196+197197+ p = blocks[5-2];198198+ q = blocks[5-1];199199+ g = blocks[good];200200+201201+ /* Compute syndrome with zero for the missing data pages202202+ * Use the dead data pages as temporary storage for delta p and203203+ * delta q204204+ */205205+ dp = blocks[faila];206206+ dq = blocks[failb];207207+208208+ init_async_submit(submit, ASYNC_TX_FENCE, tx, NULL, NULL, scribble);209209+ tx = async_memcpy(dp, g, 0, 0, bytes, submit);210210+ init_async_submit(submit, ASYNC_TX_FENCE, tx, NULL, NULL, scribble);211211+ tx = async_mult(dq, g, raid6_gfexp[good], bytes, submit);212212+213213+ /* compute P + Pxy */214214+ srcs[0] = dp;215215+ srcs[1] = p;216216+ init_async_submit(submit, ASYNC_TX_FENCE|ASYNC_TX_XOR_DROP_DST, tx,217217+ NULL, NULL, scribble);218218+ tx = async_xor(dp, srcs, 0, 2, bytes, submit);219219+220220+ /* compute Q + Qxy */221221+ srcs[0] = dq;222222+ srcs[1] = q;223223+ init_async_submit(submit, ASYNC_TX_FENCE|ASYNC_TX_XOR_DROP_DST, tx,224224+ NULL, NULL, scribble);225225+ tx = async_xor(dq, srcs, 0, 2, bytes, submit);226226+227227+ /* Dx = A*(P+Pxy) + B*(Q+Qxy) */228228+ srcs[0] = dp;229229+ srcs[1] = dq;230230+ coef[0] = raid6_gfexi[failb-faila];231231+ coef[1] = raid6_gfinv[raid6_gfexp[faila]^raid6_gfexp[failb]];232232+ init_async_submit(submit, ASYNC_TX_FENCE, tx, NULL, NULL, scribble);233233+ tx = async_sum_product(dq, srcs, coef, bytes, submit);234234+235235+ /* Dy = P+Pxy+Dx */236236+ srcs[0] = dp;237237+ srcs[1] = dq;238238+ init_async_submit(submit, flags | ASYNC_TX_XOR_DROP_DST, tx, cb_fn,239239+ cb_param, scribble);240240+ tx = async_xor(dp, srcs, 0, 2, bytes, submit);241241+242242+ return tx;243243+}244244+245245+static struct dma_async_tx_descriptor *246246+__2data_recov_n(int disks, size_t bytes, int faila, int failb,247247+ struct page **blocks, struct async_submit_ctl *submit)248248+{249249+ struct dma_async_tx_descriptor *tx = NULL;250250+ struct page *p, *q, *dp, *dq;251251+ struct page *srcs[2];252252+ unsigned char coef[2];253253+ enum async_tx_flags flags = submit->flags;254254+ dma_async_tx_callback cb_fn = submit->cb_fn;255255+ void *cb_param = submit->cb_param;256256+ void *scribble = submit->scribble;257257+258258+ p = blocks[disks-2];259259+ q = blocks[disks-1];260260+261261+ /* Compute syndrome with zero for the missing data pages262262+ * Use the dead data pages as temporary storage for263263+ * delta p and delta q264264+ */265265+ dp = blocks[faila];266266+ blocks[faila] = (void *)raid6_empty_zero_page;267267+ blocks[disks-2] = dp;268268+ dq = blocks[failb];269269+ blocks[failb] = (void *)raid6_empty_zero_page;270270+ blocks[disks-1] = dq;271271+272272+ init_async_submit(submit, ASYNC_TX_FENCE, tx, NULL, NULL, scribble);273273+ tx = async_gen_syndrome(blocks, 0, disks, bytes, submit);274274+275275+ /* Restore pointer table */276276+ blocks[faila] = dp;277277+ blocks[failb] = dq;278278+ blocks[disks-2] = p;279279+ blocks[disks-1] = q;280280+281281+ /* compute P + Pxy */282282+ srcs[0] = dp;283283+ srcs[1] = p;284284+ init_async_submit(submit, ASYNC_TX_FENCE|ASYNC_TX_XOR_DROP_DST, tx,285285+ NULL, NULL, scribble);286286+ tx = async_xor(dp, srcs, 0, 2, bytes, submit);287287+288288+ /* compute Q + Qxy */289289+ srcs[0] = dq;290290+ srcs[1] = q;291291+ init_async_submit(submit, ASYNC_TX_FENCE|ASYNC_TX_XOR_DROP_DST, tx,292292+ NULL, NULL, scribble);293293+ tx = async_xor(dq, srcs, 0, 2, bytes, submit);294294+295295+ /* Dx = A*(P+Pxy) + B*(Q+Qxy) */296296+ srcs[0] = dp;297297+ srcs[1] = dq;298298+ coef[0] = raid6_gfexi[failb-faila];299299+ coef[1] = raid6_gfinv[raid6_gfexp[faila]^raid6_gfexp[failb]];300300+ init_async_submit(submit, ASYNC_TX_FENCE, tx, NULL, NULL, scribble);301301+ tx = async_sum_product(dq, srcs, coef, bytes, submit);302302+303303+ /* Dy = P+Pxy+Dx */304304+ srcs[0] = dp;305305+ srcs[1] = dq;306306+ init_async_submit(submit, flags | ASYNC_TX_XOR_DROP_DST, tx, cb_fn,307307+ cb_param, scribble);308308+ tx = async_xor(dp, srcs, 0, 2, bytes, submit);309309+310310+ return tx;311311+}312312+313313+/**314314+ * async_raid6_2data_recov - asynchronously calculate two missing data blocks315315+ * @disks: number of disks in the RAID-6 array316316+ * @bytes: block size317317+ * @faila: first failed drive index318318+ * @failb: second failed drive index319319+ * @blocks: array of source pointers where the last two entries are p and q320320+ * @submit: submission/completion modifiers321321+ */322322+struct dma_async_tx_descriptor *323323+async_raid6_2data_recov(int disks, size_t bytes, int faila, int failb,324324+ struct page **blocks, struct async_submit_ctl *submit)325325+{326326+ BUG_ON(faila == failb);327327+ if (failb < faila)328328+ swap(faila, failb);329329+330330+ pr_debug("%s: disks: %d len: %zu\n", __func__, disks, bytes);331331+332332+ /* we need to preserve the contents of 'blocks' for the async333333+ * case, so punt to synchronous if a scribble buffer is not available334334+ */335335+ if (!submit->scribble) {336336+ void **ptrs = (void **) blocks;337337+ int i;338338+339339+ async_tx_quiesce(&submit->depend_tx);340340+ for (i = 0; i < disks; i++)341341+ ptrs[i] = page_address(blocks[i]);342342+343343+ raid6_2data_recov(disks, bytes, faila, failb, ptrs);344344+345345+ async_tx_sync_epilog(submit);346346+347347+ return NULL;348348+ }349349+350350+ switch (disks) {351351+ case 4:352352+ /* dma devices do not uniformly understand a zero source pq353353+ * operation (in contrast to the synchronous case), so354354+ * explicitly handle the 4 disk special case355355+ */356356+ return __2data_recov_4(bytes, faila, failb, blocks, submit);357357+ case 5:358358+ /* dma devices do not uniformly understand a single359359+ * source pq operation (in contrast to the synchronous360360+ * case), so explicitly handle the 5 disk special case361361+ */362362+ return __2data_recov_5(bytes, faila, failb, blocks, submit);363363+ default:364364+ return __2data_recov_n(disks, bytes, faila, failb, blocks, submit);365365+ }366366+}367367+EXPORT_SYMBOL_GPL(async_raid6_2data_recov);368368+369369+/**370370+ * async_raid6_datap_recov - asynchronously calculate a data and the 'p' block371371+ * @disks: number of disks in the RAID-6 array372372+ * @bytes: block size373373+ * @faila: failed drive index374374+ * @blocks: array of source pointers where the last two entries are p and q375375+ * @submit: submission/completion modifiers376376+ */377377+struct dma_async_tx_descriptor *378378+async_raid6_datap_recov(int disks, size_t bytes, int faila,379379+ struct page **blocks, struct async_submit_ctl *submit)380380+{381381+ struct dma_async_tx_descriptor *tx = NULL;382382+ struct page *p, *q, *dq;383383+ u8 coef;384384+ enum async_tx_flags flags = submit->flags;385385+ dma_async_tx_callback cb_fn = submit->cb_fn;386386+ void *cb_param = submit->cb_param;387387+ void *scribble = submit->scribble;388388+ struct page *srcs[2];389389+390390+ pr_debug("%s: disks: %d len: %zu\n", __func__, disks, bytes);391391+392392+ /* we need to preserve the contents of 'blocks' for the async393393+ * case, so punt to synchronous if a scribble buffer is not available394394+ */395395+ if (!scribble) {396396+ void **ptrs = (void **) blocks;397397+ int i;398398+399399+ async_tx_quiesce(&submit->depend_tx);400400+ for (i = 0; i < disks; i++)401401+ ptrs[i] = page_address(blocks[i]);402402+403403+ raid6_datap_recov(disks, bytes, faila, ptrs);404404+405405+ async_tx_sync_epilog(submit);406406+407407+ return NULL;408408+ }409409+410410+ p = blocks[disks-2];411411+ q = blocks[disks-1];412412+413413+ /* Compute syndrome with zero for the missing data page414414+ * Use the dead data page as temporary storage for delta q415415+ */416416+ dq = blocks[faila];417417+ blocks[faila] = (void *)raid6_empty_zero_page;418418+ blocks[disks-1] = dq;419419+420420+ /* in the 4 disk case we only need to perform a single source421421+ * multiplication422422+ */423423+ if (disks == 4) {424424+ int good = faila == 0 ? 1 : 0;425425+ struct page *g = blocks[good];426426+427427+ init_async_submit(submit, ASYNC_TX_FENCE, tx, NULL, NULL,428428+ scribble);429429+ tx = async_memcpy(p, g, 0, 0, bytes, submit);430430+431431+ init_async_submit(submit, ASYNC_TX_FENCE, tx, NULL, NULL,432432+ scribble);433433+ tx = async_mult(dq, g, raid6_gfexp[good], bytes, submit);434434+ } else {435435+ init_async_submit(submit, ASYNC_TX_FENCE, tx, NULL, NULL,436436+ scribble);437437+ tx = async_gen_syndrome(blocks, 0, disks, bytes, submit);438438+ }439439+440440+ /* Restore pointer table */441441+ blocks[faila] = dq;442442+ blocks[disks-1] = q;443443+444444+ /* calculate g^{-faila} */445445+ coef = raid6_gfinv[raid6_gfexp[faila]];446446+447447+ srcs[0] = dq;448448+ srcs[1] = q;449449+ init_async_submit(submit, ASYNC_TX_FENCE|ASYNC_TX_XOR_DROP_DST, tx,450450+ NULL, NULL, scribble);451451+ tx = async_xor(dq, srcs, 0, 2, bytes, submit);452452+453453+ init_async_submit(submit, ASYNC_TX_FENCE, tx, NULL, NULL, scribble);454454+ tx = async_mult(dq, dq, coef, bytes, submit);455455+456456+ srcs[0] = p;457457+ srcs[1] = dq;458458+ init_async_submit(submit, flags | ASYNC_TX_XOR_DROP_DST, tx, cb_fn,459459+ cb_param, scribble);460460+ tx = async_xor(p, srcs, 0, 2, bytes, submit);461461+462462+ return tx;463463+}464464+EXPORT_SYMBOL_GPL(async_raid6_datap_recov);465465+466466+MODULE_AUTHOR("Dan Williams <dan.j.williams@intel.com>");467467+MODULE_DESCRIPTION("asynchronous RAID-6 recovery api");468468+MODULE_LICENSE("GPL");
+42-45
crypto/async_tx/async_tx.c
···4242 async_dmaengine_put();4343}44444545+module_init(async_tx_init);4646+module_exit(async_tx_exit);4747+4548/**4649 * __async_tx_find_channel - find a channel to carry out the operation or let4750 * the transaction execute synchronously4848- * @depend_tx: transaction dependency5151+ * @submit: transaction dependency and submission modifiers4952 * @tx_type: transaction type5053 */5154struct dma_chan *5252-__async_tx_find_channel(struct dma_async_tx_descriptor *depend_tx,5353- enum dma_transaction_type tx_type)5555+__async_tx_find_channel(struct async_submit_ctl *submit,5656+ enum dma_transaction_type tx_type)5457{5858+ struct dma_async_tx_descriptor *depend_tx = submit->depend_tx;5959+5560 /* see if we can keep the chain on one channel */5661 if (depend_tx &&5762 dma_has_cap(tx_type, depend_tx->chan->device->cap_mask))···6459 return async_dma_find_channel(tx_type);6560}6661EXPORT_SYMBOL_GPL(__async_tx_find_channel);6767-#else6868-static int __init async_tx_init(void)6969-{7070- printk(KERN_INFO "async_tx: api initialized (sync-only)\n");7171- return 0;7272-}7373-7474-static void __exit async_tx_exit(void)7575-{7676- do { } while (0);7777-}7862#endif79638064···7783async_tx_channel_switch(struct dma_async_tx_descriptor *depend_tx,7884 struct dma_async_tx_descriptor *tx)7985{8080- struct dma_chan *chan;8181- struct dma_device *device;8686+ struct dma_chan *chan = depend_tx->chan;8787+ struct dma_device *device = chan->device;8288 struct dma_async_tx_descriptor *intr_tx = (void *) ~0;8989+9090+ #ifdef CONFIG_ASYNC_TX_DISABLE_CHANNEL_SWITCH9191+ BUG();9292+ #endif83938494 /* first check to see if we can still append to depend_tx */8595 spin_lock_bh(&depend_tx->lock);···9496 }9597 spin_unlock_bh(&depend_tx->lock);96989797- if (!intr_tx)9999+ /* attached dependency, flush the parent channel */100100+ if (!intr_tx) {101101+ device->device_issue_pending(chan);98102 return;9999-100100- chan = depend_tx->chan;101101- device = chan->device;103103+ }102104103105 /* see if we can schedule an interrupt104106 * otherwise poll for completion···132134 intr_tx->tx_submit(intr_tx);133135 async_tx_ack(intr_tx);134136 }137137+ device->device_issue_pending(chan);135138 } else {136139 if (dma_wait_for_async_tx(depend_tx) == DMA_ERROR)137140 panic("%s: DMA_ERROR waiting for depend_tx\n",···143144144145145146/**146146- * submit_disposition - while holding depend_tx->lock we must avoid submitting147147- * new operations to prevent a circular locking dependency with148148- * drivers that already hold a channel lock when calling149149- * async_tx_run_dependencies.147147+ * submit_disposition - flags for routing an incoming operation150148 * @ASYNC_TX_SUBMITTED: we were able to append the new operation under the lock151149 * @ASYNC_TX_CHANNEL_SWITCH: when the lock is dropped schedule a channel switch152150 * @ASYNC_TX_DIRECT_SUBMIT: when the lock is dropped submit directly151151+ *152152+ * while holding depend_tx->lock we must avoid submitting new operations153153+ * to prevent a circular locking dependency with drivers that already154154+ * hold a channel lock when calling async_tx_run_dependencies.153155 */154156enum submit_disposition {155157 ASYNC_TX_SUBMITTED,···160160161161void162162async_tx_submit(struct dma_chan *chan, struct dma_async_tx_descriptor *tx,163163- enum async_tx_flags flags, struct dma_async_tx_descriptor *depend_tx,164164- dma_async_tx_callback cb_fn, void *cb_param)163163+ struct async_submit_ctl *submit)165164{166166- tx->callback = cb_fn;167167- tx->callback_param = cb_param;165165+ struct dma_async_tx_descriptor *depend_tx = submit->depend_tx;166166+167167+ tx->callback = submit->cb_fn;168168+ tx->callback_param = submit->cb_param;168169169170 if (depend_tx) {170171 enum submit_disposition s;···221220 tx->tx_submit(tx);222221 }223222224224- if (flags & ASYNC_TX_ACK)223223+ if (submit->flags & ASYNC_TX_ACK)225224 async_tx_ack(tx);226225227227- if (depend_tx && (flags & ASYNC_TX_DEP_ACK))226226+ if (depend_tx)228227 async_tx_ack(depend_tx);229228}230229EXPORT_SYMBOL_GPL(async_tx_submit);231230232231/**233233- * async_trigger_callback - schedules the callback function to be run after234234- * any dependent operations have been completed.235235- * @flags: ASYNC_TX_ACK, ASYNC_TX_DEP_ACK236236- * @depend_tx: 'callback' requires the completion of this transaction237237- * @cb_fn: function to call after depend_tx completes238238- * @cb_param: parameter to pass to the callback routine232232+ * async_trigger_callback - schedules the callback function to be run233233+ * @submit: submission and completion parameters234234+ *235235+ * honored flags: ASYNC_TX_ACK236236+ *237237+ * The callback is run after any dependent operations have completed.239238 */240239struct dma_async_tx_descriptor *241241-async_trigger_callback(enum async_tx_flags flags,242242- struct dma_async_tx_descriptor *depend_tx,243243- dma_async_tx_callback cb_fn, void *cb_param)240240+async_trigger_callback(struct async_submit_ctl *submit)244241{245242 struct dma_chan *chan;246243 struct dma_device *device;247244 struct dma_async_tx_descriptor *tx;245245+ struct dma_async_tx_descriptor *depend_tx = submit->depend_tx;248246249247 if (depend_tx) {250248 chan = depend_tx->chan;···262262 if (tx) {263263 pr_debug("%s: (async)\n", __func__);264264265265- async_tx_submit(chan, tx, flags, depend_tx, cb_fn, cb_param);265265+ async_tx_submit(chan, tx, submit);266266 } else {267267 pr_debug("%s: (sync)\n", __func__);268268269269 /* wait for any prerequisite operations */270270- async_tx_quiesce(&depend_tx);270270+ async_tx_quiesce(&submit->depend_tx);271271272272- async_tx_sync_epilog(cb_fn, cb_param);272272+ async_tx_sync_epilog(submit);273273 }274274275275 return tx;···294294 }295295}296296EXPORT_SYMBOL_GPL(async_tx_quiesce);297297-298298-module_init(async_tx_init);299299-module_exit(async_tx_exit);300297301298MODULE_AUTHOR("Intel Corporation");302299MODULE_DESCRIPTION("Asynchronous Bulk Memory Transactions API");
+103-104
crypto/async_tx/async_xor.c
···3333/* do_async_xor - dma map the pages and perform the xor with an engine */3434static __async_inline struct dma_async_tx_descriptor *3535do_async_xor(struct dma_chan *chan, struct page *dest, struct page **src_list,3636- unsigned int offset, int src_cnt, size_t len,3737- enum async_tx_flags flags,3838- struct dma_async_tx_descriptor *depend_tx,3939- dma_async_tx_callback cb_fn, void *cb_param)3636+ unsigned int offset, int src_cnt, size_t len, dma_addr_t *dma_src,3737+ struct async_submit_ctl *submit)4038{4139 struct dma_device *dma = chan->device;4242- dma_addr_t *dma_src = (dma_addr_t *) src_list;4340 struct dma_async_tx_descriptor *tx = NULL;4441 int src_off = 0;4542 int i;4646- dma_async_tx_callback _cb_fn;4747- void *_cb_param;4848- enum async_tx_flags async_flags;4343+ dma_async_tx_callback cb_fn_orig = submit->cb_fn;4444+ void *cb_param_orig = submit->cb_param;4545+ enum async_tx_flags flags_orig = submit->flags;4946 enum dma_ctrl_flags dma_flags;5047 int xor_src_cnt;5148 dma_addr_t dma_dest;···6063 }61646265 while (src_cnt) {6363- async_flags = flags;6666+ submit->flags = flags_orig;6467 dma_flags = 0;6565- xor_src_cnt = min(src_cnt, dma->max_xor);6868+ xor_src_cnt = min(src_cnt, (int)dma->max_xor);6669 /* if we are submitting additional xors, leave the chain open,6770 * clear the callback parameters, and leave the destination6871 * buffer mapped6972 */7073 if (src_cnt > xor_src_cnt) {7171- async_flags &= ~ASYNC_TX_ACK;7474+ submit->flags &= ~ASYNC_TX_ACK;7575+ submit->flags |= ASYNC_TX_FENCE;7276 dma_flags = DMA_COMPL_SKIP_DEST_UNMAP;7373- _cb_fn = NULL;7474- _cb_param = NULL;7777+ submit->cb_fn = NULL;7878+ submit->cb_param = NULL;7579 } else {7676- _cb_fn = cb_fn;7777- _cb_param = cb_param;8080+ submit->cb_fn = cb_fn_orig;8181+ submit->cb_param = cb_param_orig;7882 }7979- if (_cb_fn)8383+ if (submit->cb_fn)8084 dma_flags |= DMA_PREP_INTERRUPT;8181-8585+ if (submit->flags & ASYNC_TX_FENCE)8686+ dma_flags |= DMA_PREP_FENCE;8287 /* Since we have clobbered the src_list we are committed8388 * to doing this asynchronously. Drivers force forward progress8489 * in case they can not provide a descriptor···8990 xor_src_cnt, len, dma_flags);90919192 if (unlikely(!tx))9292- async_tx_quiesce(&depend_tx);9393+ async_tx_quiesce(&submit->depend_tx);93949495 /* spin wait for the preceeding transactions to complete */9596 while (unlikely(!tx)) {···100101 dma_flags);101102 }102103103103- async_tx_submit(chan, tx, async_flags, depend_tx, _cb_fn,104104- _cb_param);105105-106106- depend_tx = tx;107107- flags |= ASYNC_TX_DEP_ACK;104104+ async_tx_submit(chan, tx, submit);105105+ submit->depend_tx = tx;108106109107 if (src_cnt > xor_src_cnt) {110108 /* drop completed sources */···120124121125static void122126do_sync_xor(struct page *dest, struct page **src_list, unsigned int offset,123123- int src_cnt, size_t len, enum async_tx_flags flags,124124- dma_async_tx_callback cb_fn, void *cb_param)127127+ int src_cnt, size_t len, struct async_submit_ctl *submit)125128{126129 int i;127130 int xor_src_cnt;128131 int src_off = 0;129132 void *dest_buf;130130- void **srcs = (void **) src_list;133133+ void **srcs;131134132132- /* reuse the 'src_list' array to convert to buffer pointers */135135+ if (submit->scribble)136136+ srcs = submit->scribble;137137+ else138138+ srcs = (void **) src_list;139139+140140+ /* convert to buffer pointers */133141 for (i = 0; i < src_cnt; i++)134142 srcs[i] = page_address(src_list[i]) + offset;135143136144 /* set destination address */137145 dest_buf = page_address(dest) + offset;138146139139- if (flags & ASYNC_TX_XOR_ZERO_DST)147147+ if (submit->flags & ASYNC_TX_XOR_ZERO_DST)140148 memset(dest_buf, 0, len);141149142150 while (src_cnt > 0) {···153153 src_off += xor_src_cnt;154154 }155155156156- async_tx_sync_epilog(cb_fn, cb_param);156156+ async_tx_sync_epilog(submit);157157}158158159159/**160160 * async_xor - attempt to xor a set of blocks with a dma engine.161161- * xor_blocks always uses the dest as a source so the ASYNC_TX_XOR_ZERO_DST162162- * flag must be set to not include dest data in the calculation. The163163- * assumption with dma eninges is that they only use the destination164164- * buffer as a source when it is explicity specified in the source list.165161 * @dest: destination page166166- * @src_list: array of source pages (if the dest is also a source it must be167167- * at index zero). The contents of this array may be overwritten.168168- * @offset: offset in pages to start transaction162162+ * @src_list: array of source pages163163+ * @offset: common src/dst offset to start transaction169164 * @src_cnt: number of source pages170165 * @len: length in bytes171171- * @flags: ASYNC_TX_XOR_ZERO_DST, ASYNC_TX_XOR_DROP_DEST,172172- * ASYNC_TX_ACK, ASYNC_TX_DEP_ACK173173- * @depend_tx: xor depends on the result of this transaction.174174- * @cb_fn: function to call when the xor completes175175- * @cb_param: parameter to pass to the callback routine166166+ * @submit: submission / completion modifiers167167+ *168168+ * honored flags: ASYNC_TX_ACK, ASYNC_TX_XOR_ZERO_DST, ASYNC_TX_XOR_DROP_DST169169+ *170170+ * xor_blocks always uses the dest as a source so the171171+ * ASYNC_TX_XOR_ZERO_DST flag must be set to not include dest data in172172+ * the calculation. The assumption with dma eninges is that they only173173+ * use the destination buffer as a source when it is explicity specified174174+ * in the source list.175175+ *176176+ * src_list note: if the dest is also a source it must be at index zero.177177+ * The contents of this array will be overwritten if a scribble region178178+ * is not specified.176179 */177180struct dma_async_tx_descriptor *178181async_xor(struct page *dest, struct page **src_list, unsigned int offset,179179- int src_cnt, size_t len, enum async_tx_flags flags,180180- struct dma_async_tx_descriptor *depend_tx,181181- dma_async_tx_callback cb_fn, void *cb_param)182182+ int src_cnt, size_t len, struct async_submit_ctl *submit)182183{183183- struct dma_chan *chan = async_tx_find_channel(depend_tx, DMA_XOR,184184+ struct dma_chan *chan = async_tx_find_channel(submit, DMA_XOR,184185 &dest, 1, src_list,185186 src_cnt, len);187187+ dma_addr_t *dma_src = NULL;188188+186189 BUG_ON(src_cnt <= 1);187190188188- if (chan) {191191+ if (submit->scribble)192192+ dma_src = submit->scribble;193193+ else if (sizeof(dma_addr_t) <= sizeof(struct page *))194194+ dma_src = (dma_addr_t *) src_list;195195+196196+ if (dma_src && chan && is_dma_xor_aligned(chan->device, offset, 0, len)) {189197 /* run the xor asynchronously */190198 pr_debug("%s (async): len: %zu\n", __func__, len);191199192200 return do_async_xor(chan, dest, src_list, offset, src_cnt, len,193193- flags, depend_tx, cb_fn, cb_param);201201+ dma_src, submit);194202 } else {195203 /* run the xor synchronously */196204 pr_debug("%s (sync): len: %zu\n", __func__, len);205205+ WARN_ONCE(chan, "%s: no space for dma address conversion\n",206206+ __func__);197207198208 /* in the sync case the dest is an implied source199209 * (assumes the dest is the first source)200210 */201201- if (flags & ASYNC_TX_XOR_DROP_DST) {211211+ if (submit->flags & ASYNC_TX_XOR_DROP_DST) {202212 src_cnt--;203213 src_list++;204214 }205215206216 /* wait for any prerequisite operations */207207- async_tx_quiesce(&depend_tx);217217+ async_tx_quiesce(&submit->depend_tx);208218209209- do_sync_xor(dest, src_list, offset, src_cnt, len,210210- flags, cb_fn, cb_param);219219+ do_sync_xor(dest, src_list, offset, src_cnt, len, submit);211220212221 return NULL;213222 }···231222}232223233224/**234234- * async_xor_zero_sum - attempt a xor parity check with a dma engine.225225+ * async_xor_val - attempt a xor parity check with a dma engine.235226 * @dest: destination page used if the xor is performed synchronously236236- * @src_list: array of source pages. The dest page must be listed as a source237237- * at index zero. The contents of this array may be overwritten.227227+ * @src_list: array of source pages238228 * @offset: offset in pages to start transaction239229 * @src_cnt: number of source pages240230 * @len: length in bytes241231 * @result: 0 if sum == 0 else non-zero242242- * @flags: ASYNC_TX_ACK, ASYNC_TX_DEP_ACK243243- * @depend_tx: xor depends on the result of this transaction.244244- * @cb_fn: function to call when the xor completes245245- * @cb_param: parameter to pass to the callback routine232232+ * @submit: submission / completion modifiers233233+ *234234+ * honored flags: ASYNC_TX_ACK235235+ *236236+ * src_list note: if the dest is also a source it must be at index zero.237237+ * The contents of this array will be overwritten if a scribble region238238+ * is not specified.246239 */247240struct dma_async_tx_descriptor *248248-async_xor_zero_sum(struct page *dest, struct page **src_list,249249- unsigned int offset, int src_cnt, size_t len,250250- u32 *result, enum async_tx_flags flags,251251- struct dma_async_tx_descriptor *depend_tx,252252- dma_async_tx_callback cb_fn, void *cb_param)241241+async_xor_val(struct page *dest, struct page **src_list, unsigned int offset,242242+ int src_cnt, size_t len, enum sum_check_flags *result,243243+ struct async_submit_ctl *submit)253244{254254- struct dma_chan *chan = async_tx_find_channel(depend_tx, DMA_ZERO_SUM,245245+ struct dma_chan *chan = async_tx_find_channel(submit, DMA_XOR_VAL,255246 &dest, 1, src_list,256247 src_cnt, len);257248 struct dma_device *device = chan ? chan->device : NULL;258249 struct dma_async_tx_descriptor *tx = NULL;250250+ dma_addr_t *dma_src = NULL;259251260252 BUG_ON(src_cnt <= 1);261253262262- if (device && src_cnt <= device->max_xor) {263263- dma_addr_t *dma_src = (dma_addr_t *) src_list;264264- unsigned long dma_prep_flags = cb_fn ? DMA_PREP_INTERRUPT : 0;254254+ if (submit->scribble)255255+ dma_src = submit->scribble;256256+ else if (sizeof(dma_addr_t) <= sizeof(struct page *))257257+ dma_src = (dma_addr_t *) src_list;258258+259259+ if (dma_src && device && src_cnt <= device->max_xor &&260260+ is_dma_xor_aligned(device, offset, 0, len)) {261261+ unsigned long dma_prep_flags = 0;265262 int i;266263267264 pr_debug("%s: (async) len: %zu\n", __func__, len);268265266266+ if (submit->cb_fn)267267+ dma_prep_flags |= DMA_PREP_INTERRUPT;268268+ if (submit->flags & ASYNC_TX_FENCE)269269+ dma_prep_flags |= DMA_PREP_FENCE;269270 for (i = 0; i < src_cnt; i++)270271 dma_src[i] = dma_map_page(device->dev, src_list[i],271272 offset, len, DMA_TO_DEVICE);272273273273- tx = device->device_prep_dma_zero_sum(chan, dma_src, src_cnt,274274- len, result,275275- dma_prep_flags);274274+ tx = device->device_prep_dma_xor_val(chan, dma_src, src_cnt,275275+ len, result,276276+ dma_prep_flags);276277 if (unlikely(!tx)) {277277- async_tx_quiesce(&depend_tx);278278+ async_tx_quiesce(&submit->depend_tx);278279279280 while (!tx) {280281 dma_async_issue_pending(chan);281281- tx = device->device_prep_dma_zero_sum(chan,282282+ tx = device->device_prep_dma_xor_val(chan,282283 dma_src, src_cnt, len, result,283284 dma_prep_flags);284285 }285286 }286287287287- async_tx_submit(chan, tx, flags, depend_tx, cb_fn, cb_param);288288+ async_tx_submit(chan, tx, submit);288289 } else {289289- unsigned long xor_flags = flags;290290+ enum async_tx_flags flags_orig = submit->flags;290291291292 pr_debug("%s: (sync) len: %zu\n", __func__, len);293293+ WARN_ONCE(device && src_cnt <= device->max_xor,294294+ "%s: no space for dma address conversion\n",295295+ __func__);292296293293- xor_flags |= ASYNC_TX_XOR_DROP_DST;294294- xor_flags &= ~ASYNC_TX_ACK;297297+ submit->flags |= ASYNC_TX_XOR_DROP_DST;298298+ submit->flags &= ~ASYNC_TX_ACK;295299296296- tx = async_xor(dest, src_list, offset, src_cnt, len, xor_flags,297297- depend_tx, NULL, NULL);300300+ tx = async_xor(dest, src_list, offset, src_cnt, len, submit);298301299302 async_tx_quiesce(&tx);300303301301- *result = page_is_zero(dest, offset, len) ? 0 : 1;304304+ *result = !page_is_zero(dest, offset, len) << SUM_CHECK_P;302305303303- async_tx_sync_epilog(cb_fn, cb_param);306306+ async_tx_sync_epilog(submit);307307+ submit->flags = flags_orig;304308 }305309306310 return tx;307311}308308-EXPORT_SYMBOL_GPL(async_xor_zero_sum);309309-310310-static int __init async_xor_init(void)311311-{312312- #ifdef CONFIG_ASYNC_TX_DMA313313- /* To conserve stack space the input src_list (array of page pointers)314314- * is reused to hold the array of dma addresses passed to the driver.315315- * This conversion is only possible when dma_addr_t is less than the316316- * the size of a pointer. HIGHMEM64G is known to violate this317317- * assumption.318318- */319319- BUILD_BUG_ON(sizeof(dma_addr_t) > sizeof(struct page *));320320- #endif321321-322322- return 0;323323-}324324-325325-static void __exit async_xor_exit(void)326326-{327327- do { } while (0);328328-}329329-330330-module_init(async_xor_init);331331-module_exit(async_xor_exit);312312+EXPORT_SYMBOL_GPL(async_xor_val);332313333314MODULE_AUTHOR("Intel Corporation");334315MODULE_DESCRIPTION("asynchronous xor/xor-zero-sum api");
+240
crypto/async_tx/raid6test.c
···11+/*22+ * asynchronous raid6 recovery self test33+ * Copyright (c) 2009, Intel Corporation.44+ *55+ * based on drivers/md/raid6test/test.c:66+ * Copyright 2002-2007 H. Peter Anvin77+ *88+ * This program is free software; you can redistribute it and/or modify it99+ * under the terms and conditions of the GNU General Public License,1010+ * version 2, as published by the Free Software Foundation.1111+ *1212+ * This program is distributed in the hope it will be useful, but WITHOUT1313+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or1414+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for1515+ * more details.1616+ *1717+ * You should have received a copy of the GNU General Public License along with1818+ * this program; if not, write to the Free Software Foundation, Inc.,1919+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.2020+ *2121+ */2222+#include <linux/async_tx.h>2323+#include <linux/random.h>2424+2525+#undef pr2626+#define pr(fmt, args...) pr_info("raid6test: " fmt, ##args)2727+2828+#define NDISKS 16 /* Including P and Q */2929+3030+static struct page *dataptrs[NDISKS];3131+static addr_conv_t addr_conv[NDISKS];3232+static struct page *data[NDISKS+3];3333+static struct page *spare;3434+static struct page *recovi;3535+static struct page *recovj;3636+3737+static void callback(void *param)3838+{3939+ struct completion *cmp = param;4040+4141+ complete(cmp);4242+}4343+4444+static void makedata(int disks)4545+{4646+ int i, j;4747+4848+ for (i = 0; i < disks; i++) {4949+ for (j = 0; j < PAGE_SIZE/sizeof(u32); j += sizeof(u32)) {5050+ u32 *p = page_address(data[i]) + j;5151+5252+ *p = random32();5353+ }5454+5555+ dataptrs[i] = data[i];5656+ }5757+}5858+5959+static char disk_type(int d, int disks)6060+{6161+ if (d == disks - 2)6262+ return 'P';6363+ else if (d == disks - 1)6464+ return 'Q';6565+ else6666+ return 'D';6767+}6868+6969+/* Recover two failed blocks. */7070+static void raid6_dual_recov(int disks, size_t bytes, int faila, int failb, struct page **ptrs)7171+{7272+ struct async_submit_ctl submit;7373+ struct completion cmp;7474+ struct dma_async_tx_descriptor *tx = NULL;7575+ enum sum_check_flags result = ~0;7676+7777+ if (faila > failb)7878+ swap(faila, failb);7979+8080+ if (failb == disks-1) {8181+ if (faila == disks-2) {8282+ /* P+Q failure. Just rebuild the syndrome. */8383+ init_async_submit(&submit, 0, NULL, NULL, NULL, addr_conv);8484+ tx = async_gen_syndrome(ptrs, 0, disks, bytes, &submit);8585+ } else {8686+ struct page *blocks[disks];8787+ struct page *dest;8888+ int count = 0;8989+ int i;9090+9191+ /* data+Q failure. Reconstruct data from P,9292+ * then rebuild syndrome9393+ */9494+ for (i = disks; i-- ; ) {9595+ if (i == faila || i == failb)9696+ continue;9797+ blocks[count++] = ptrs[i];9898+ }9999+ dest = ptrs[faila];100100+ init_async_submit(&submit, ASYNC_TX_XOR_ZERO_DST, NULL,101101+ NULL, NULL, addr_conv);102102+ tx = async_xor(dest, blocks, 0, count, bytes, &submit);103103+104104+ init_async_submit(&submit, 0, tx, NULL, NULL, addr_conv);105105+ tx = async_gen_syndrome(ptrs, 0, disks, bytes, &submit);106106+ }107107+ } else {108108+ if (failb == disks-2) {109109+ /* data+P failure. */110110+ init_async_submit(&submit, 0, NULL, NULL, NULL, addr_conv);111111+ tx = async_raid6_datap_recov(disks, bytes, faila, ptrs, &submit);112112+ } else {113113+ /* data+data failure. */114114+ init_async_submit(&submit, 0, NULL, NULL, NULL, addr_conv);115115+ tx = async_raid6_2data_recov(disks, bytes, faila, failb, ptrs, &submit);116116+ }117117+ }118118+ init_completion(&cmp);119119+ init_async_submit(&submit, ASYNC_TX_ACK, tx, callback, &cmp, addr_conv);120120+ tx = async_syndrome_val(ptrs, 0, disks, bytes, &result, spare, &submit);121121+ async_tx_issue_pending(tx);122122+123123+ if (wait_for_completion_timeout(&cmp, msecs_to_jiffies(3000)) == 0)124124+ pr("%s: timeout! (faila: %d failb: %d disks: %d)\n",125125+ __func__, faila, failb, disks);126126+127127+ if (result != 0)128128+ pr("%s: validation failure! faila: %d failb: %d sum_check_flags: %x\n",129129+ __func__, faila, failb, result);130130+}131131+132132+static int test_disks(int i, int j, int disks)133133+{134134+ int erra, errb;135135+136136+ memset(page_address(recovi), 0xf0, PAGE_SIZE);137137+ memset(page_address(recovj), 0xba, PAGE_SIZE);138138+139139+ dataptrs[i] = recovi;140140+ dataptrs[j] = recovj;141141+142142+ raid6_dual_recov(disks, PAGE_SIZE, i, j, dataptrs);143143+144144+ erra = memcmp(page_address(data[i]), page_address(recovi), PAGE_SIZE);145145+ errb = memcmp(page_address(data[j]), page_address(recovj), PAGE_SIZE);146146+147147+ pr("%s(%d, %d): faila=%3d(%c) failb=%3d(%c) %s\n",148148+ __func__, i, j, i, disk_type(i, disks), j, disk_type(j, disks),149149+ (!erra && !errb) ? "OK" : !erra ? "ERRB" : !errb ? "ERRA" : "ERRAB");150150+151151+ dataptrs[i] = data[i];152152+ dataptrs[j] = data[j];153153+154154+ return erra || errb;155155+}156156+157157+static int test(int disks, int *tests)158158+{159159+ struct dma_async_tx_descriptor *tx;160160+ struct async_submit_ctl submit;161161+ struct completion cmp;162162+ int err = 0;163163+ int i, j;164164+165165+ recovi = data[disks];166166+ recovj = data[disks+1];167167+ spare = data[disks+2];168168+169169+ makedata(disks);170170+171171+ /* Nuke syndromes */172172+ memset(page_address(data[disks-2]), 0xee, PAGE_SIZE);173173+ memset(page_address(data[disks-1]), 0xee, PAGE_SIZE);174174+175175+ /* Generate assumed good syndrome */176176+ init_completion(&cmp);177177+ init_async_submit(&submit, ASYNC_TX_ACK, NULL, callback, &cmp, addr_conv);178178+ tx = async_gen_syndrome(dataptrs, 0, disks, PAGE_SIZE, &submit);179179+ async_tx_issue_pending(tx);180180+181181+ if (wait_for_completion_timeout(&cmp, msecs_to_jiffies(3000)) == 0) {182182+ pr("error: initial gen_syndrome(%d) timed out\n", disks);183183+ return 1;184184+ }185185+186186+ pr("testing the %d-disk case...\n", disks);187187+ for (i = 0; i < disks-1; i++)188188+ for (j = i+1; j < disks; j++) {189189+ (*tests)++;190190+ err += test_disks(i, j, disks);191191+ }192192+193193+ return err;194194+}195195+196196+197197+static int raid6_test(void)198198+{199199+ int err = 0;200200+ int tests = 0;201201+ int i;202202+203203+ for (i = 0; i < NDISKS+3; i++) {204204+ data[i] = alloc_page(GFP_KERNEL);205205+ if (!data[i]) {206206+ while (i--)207207+ put_page(data[i]);208208+ return -ENOMEM;209209+ }210210+ }211211+212212+ /* the 4-disk and 5-disk cases are special for the recovery code */213213+ if (NDISKS > 4)214214+ err += test(4, &tests);215215+ if (NDISKS > 5)216216+ err += test(5, &tests);217217+ err += test(NDISKS, &tests);218218+219219+ pr("\n");220220+ pr("complete (%d tests, %d failure%s)\n",221221+ tests, err, err == 1 ? "" : "s");222222+223223+ for (i = 0; i < NDISKS+3; i++)224224+ put_page(data[i]);225225+226226+ return 0;227227+}228228+229229+static void raid6_test_exit(void)230230+{231231+}232232+233233+/* when compiled-in wait for drivers to load first (assumes dma drivers234234+ * are also compliled-in)235235+ */236236+late_initcall(raid6_test);237237+module_exit(raid6_test_exit);238238+MODULE_AUTHOR("Dan Williams <dan.j.williams@intel.com>");239239+MODULE_DESCRIPTION("asynchronous RAID-6 recovery self tests");240240+MODULE_LICENSE("GPL");
···17171818comment "DMA Devices"19192020+config ASYNC_TX_DISABLE_CHANNEL_SWITCH2121+ bool2222+2023config INTEL_IOATDMA2124 tristate "Intel I/OAT DMA support"2225 depends on PCI && X862326 select DMA_ENGINE2427 select DCA2828+ select ASYNC_TX_DISABLE_CHANNEL_SWITCH2529 help2630 Enable support for the Intel(R) I/OAT DMA engine present2731 in recent Intel Xeon chipsets.···10197 Support the TXx9 SoC internal DMA controller. This can be10298 integrated in chips such as the Toshiba TX4927/38/39.10399100100+config SH_DMAE101101+ tristate "Renesas SuperH DMAC support"102102+ depends on SUPERH && SH_DMA103103+ depends on !SH_DMA_API104104+ select DMA_ENGINE105105+ help106106+ Enable support for the Renesas SuperH DMA controllers.107107+104108config DMA_ENGINE105109 bool106110···128116129117config ASYNC_TX_DMA130118 bool "Async_tx: Offload support for the async_tx api"131131- depends on DMA_ENGINE && !HIGHMEM64G119119+ depends on DMA_ENGINE132120 help133121 This allows the async_tx api to take advantage of offload engines for134122 memcpy, memset, xor, and raid6 p+q operations. If your platform has
···608608}609609EXPORT_SYMBOL(dmaengine_put);610610611611+static bool device_has_all_tx_types(struct dma_device *device)612612+{613613+ /* A device that satisfies this test has channels that will never cause614614+ * an async_tx channel switch event as all possible operation types can615615+ * be handled.616616+ */617617+ #ifdef CONFIG_ASYNC_TX_DMA618618+ if (!dma_has_cap(DMA_INTERRUPT, device->cap_mask))619619+ return false;620620+ #endif621621+622622+ #if defined(CONFIG_ASYNC_MEMCPY) || defined(CONFIG_ASYNC_MEMCPY_MODULE)623623+ if (!dma_has_cap(DMA_MEMCPY, device->cap_mask))624624+ return false;625625+ #endif626626+627627+ #if defined(CONFIG_ASYNC_MEMSET) || defined(CONFIG_ASYNC_MEMSET_MODULE)628628+ if (!dma_has_cap(DMA_MEMSET, device->cap_mask))629629+ return false;630630+ #endif631631+632632+ #if defined(CONFIG_ASYNC_XOR) || defined(CONFIG_ASYNC_XOR_MODULE)633633+ if (!dma_has_cap(DMA_XOR, device->cap_mask))634634+ return false;635635+ #endif636636+637637+ #if defined(CONFIG_ASYNC_PQ) || defined(CONFIG_ASYNC_PQ_MODULE)638638+ if (!dma_has_cap(DMA_PQ, device->cap_mask))639639+ return false;640640+ #endif641641+642642+ return true;643643+}644644+611645static int get_dma_id(struct dma_device *device)612646{613647 int rc;···678644 !device->device_prep_dma_memcpy);679645 BUG_ON(dma_has_cap(DMA_XOR, device->cap_mask) &&680646 !device->device_prep_dma_xor);681681- BUG_ON(dma_has_cap(DMA_ZERO_SUM, device->cap_mask) &&682682- !device->device_prep_dma_zero_sum);647647+ BUG_ON(dma_has_cap(DMA_XOR_VAL, device->cap_mask) &&648648+ !device->device_prep_dma_xor_val);649649+ BUG_ON(dma_has_cap(DMA_PQ, device->cap_mask) &&650650+ !device->device_prep_dma_pq);651651+ BUG_ON(dma_has_cap(DMA_PQ_VAL, device->cap_mask) &&652652+ !device->device_prep_dma_pq_val);683653 BUG_ON(dma_has_cap(DMA_MEMSET, device->cap_mask) &&684654 !device->device_prep_dma_memset);685655 BUG_ON(dma_has_cap(DMA_INTERRUPT, device->cap_mask) &&···698660 BUG_ON(!device->device_is_tx_complete);699661 BUG_ON(!device->device_issue_pending);700662 BUG_ON(!device->dev);663663+664664+ /* note: this only matters in the665665+ * CONFIG_ASYNC_TX_DISABLE_CHANNEL_SWITCH=y case666666+ */667667+ if (device_has_all_tx_types(device))668668+ dma_cap_set(DMA_ASYNC_TX, device->cap_mask);701669702670 idr_ref = kmalloc(sizeof(*idr_ref), GFP_KERNEL);703671 if (!idr_ref)···977933{978934 tx->chan = chan;979935 spin_lock_init(&tx->lock);980980- INIT_LIST_HEAD(&tx->tx_list);981936}982937EXPORT_SYMBOL(dma_async_tx_descriptor_init);983938984939/* dma_wait_for_async_tx - spin wait for a transaction to complete985940 * @tx: in-flight transaction to wait on986986- *987987- * This routine assumes that tx was obtained from a call to async_memcpy,988988- * async_xor, async_memset, etc which ensures that tx is "in-flight" (prepped989989- * and submitted). Walking the parent chain is only meant to cover for DMA990990- * drivers that do not implement the DMA_INTERRUPT capability and may race with991991- * the driver's descriptor cleanup routine.992941 */993942enum dma_status994943dma_wait_for_async_tx(struct dma_async_tx_descriptor *tx)995944{996996- enum dma_status status;997997- struct dma_async_tx_descriptor *iter;998998- struct dma_async_tx_descriptor *parent;945945+ unsigned long dma_sync_wait_timeout = jiffies + msecs_to_jiffies(5000);9999461000947 if (!tx)1001948 return DMA_SUCCESS;100294910031003- WARN_ONCE(tx->parent, "%s: speculatively walking dependency chain for"10041004- " %s\n", __func__, dma_chan_name(tx->chan));10051005-10061006- /* poll through the dependency chain, return when tx is complete */10071007- do {10081008- iter = tx;10091009-10101010- /* find the root of the unsubmitted dependency chain */10111011- do {10121012- parent = iter->parent;10131013- if (!parent)10141014- break;10151015- else10161016- iter = parent;10171017- } while (parent);10181018-10191019- /* there is a small window for ->parent == NULL and10201020- * ->cookie == -EBUSY10211021- */10221022- while (iter->cookie == -EBUSY)10231023- cpu_relax();10241024-10251025- status = dma_sync_wait(iter->chan, iter->cookie);10261026- } while (status == DMA_IN_PROGRESS || (iter != tx));10271027-10281028- return status;950950+ while (tx->cookie == -EBUSY) {951951+ if (time_after_eq(jiffies, dma_sync_wait_timeout)) {952952+ pr_err("%s timeout waiting for descriptor submission\n",953953+ __func__);954954+ return DMA_ERROR;955955+ }956956+ cpu_relax();957957+ }958958+ return dma_sync_wait(tx->chan, tx->cookie);1029959}1030960EXPORT_SYMBOL_GPL(dma_wait_for_async_tx);1031961
+40
drivers/dma/dmatest.c
···4848MODULE_PARM_DESC(xor_sources,4949 "Number of xor source buffers (default: 3)");50505151+static unsigned int pq_sources = 3;5252+module_param(pq_sources, uint, S_IRUGO);5353+MODULE_PARM_DESC(pq_sources,5454+ "Number of p+q source buffers (default: 3)");5555+5156/*5257 * Initialization patterns. All bytes in the source buffer has bit 75358 * set, all bytes in the destination buffer has bit 7 cleared.···237232 dma_cookie_t cookie;238233 enum dma_status status;239234 enum dma_ctrl_flags flags;235235+ u8 pq_coefs[pq_sources];240236 int ret;241237 int src_cnt;242238 int dst_cnt;···254248 else if (thread->type == DMA_XOR) {255249 src_cnt = xor_sources | 1; /* force odd to ensure dst = src */256250 dst_cnt = 1;251251+ } else if (thread->type == DMA_PQ) {252252+ src_cnt = pq_sources | 1; /* force odd to ensure dst = src */253253+ dst_cnt = 2;254254+ for (i = 0; i < pq_sources; i++)255255+ pq_coefs[i] = 1;257256 } else258257 goto err_srcs;259258···294283 dma_addr_t dma_dsts[dst_cnt];295284 struct completion cmp;296285 unsigned long tmo = msecs_to_jiffies(3000);286286+ u8 align = 0;297287298288 total_tests++;299289300290 len = dmatest_random() % test_buf_size + 1;301291 src_off = dmatest_random() % (test_buf_size - len + 1);302292 dst_off = dmatest_random() % (test_buf_size - len + 1);293293+294294+ /* honor alignment restrictions */295295+ if (thread->type == DMA_MEMCPY)296296+ align = dev->copy_align;297297+ else if (thread->type == DMA_XOR)298298+ align = dev->xor_align;299299+ else if (thread->type == DMA_PQ)300300+ align = dev->pq_align;301301+302302+ len = (len >> align) << align;303303+ src_off = (src_off >> align) << align;304304+ dst_off = (dst_off >> align) << align;303305304306 dmatest_init_srcs(thread->srcs, src_off, len);305307 dmatest_init_dsts(thread->dsts, dst_off, len);···330306 DMA_BIDIRECTIONAL);331307 }332308309309+333310 if (thread->type == DMA_MEMCPY)334311 tx = dev->device_prep_dma_memcpy(chan,335312 dma_dsts[0] + dst_off,···341316 dma_dsts[0] + dst_off,342317 dma_srcs, xor_sources,343318 len, flags);319319+ else if (thread->type == DMA_PQ) {320320+ dma_addr_t dma_pq[dst_cnt];321321+322322+ for (i = 0; i < dst_cnt; i++)323323+ dma_pq[i] = dma_dsts[i] + dst_off;324324+ tx = dev->device_prep_dma_pq(chan, dma_pq, dma_srcs,325325+ pq_sources, pq_coefs,326326+ len, flags);327327+ }344328345329 if (!tx) {346330 for (i = 0; i < src_cnt; i++)···493459 op = "copy";494460 else if (type == DMA_XOR)495461 op = "xor";462462+ else if (type == DMA_PQ)463463+ op = "pq";496464 else497465 return -EINVAL;498466···549513 if (dma_has_cap(DMA_XOR, dma_dev->cap_mask)) {550514 cnt = dmatest_add_threads(dtc, DMA_XOR);551515 thread_count += cnt > 0 ? cnt : 0;516516+ }517517+ if (dma_has_cap(DMA_PQ, dma_dev->cap_mask)) {518518+ cnt = dmatest_add_threads(dtc, DMA_PQ);519519+ thread_count += cnt > 0 ?: 0;552520 }553521554522 pr_info("dmatest: Started %u threads using %s\n",
+29-21
drivers/dma/dw_dmac.c
···116116{117117 struct dw_desc *child;118118119119- list_for_each_entry(child, &desc->txd.tx_list, desc_node)119119+ list_for_each_entry(child, &desc->tx_list, desc_node)120120 dma_sync_single_for_cpu(chan2parent(&dwc->chan),121121 child->txd.phys, sizeof(child->lli),122122 DMA_TO_DEVICE);···137137 dwc_sync_desc_for_cpu(dwc, desc);138138139139 spin_lock_bh(&dwc->lock);140140- list_for_each_entry(child, &desc->txd.tx_list, desc_node)140140+ list_for_each_entry(child, &desc->tx_list, desc_node)141141 dev_vdbg(chan2dev(&dwc->chan),142142 "moving child desc %p to freelist\n",143143 child);144144- list_splice_init(&desc->txd.tx_list, &dwc->free_list);144144+ list_splice_init(&desc->tx_list, &dwc->free_list);145145 dev_vdbg(chan2dev(&dwc->chan), "moving desc %p to freelist\n", desc);146146 list_add(&desc->desc_node, &dwc->free_list);147147 spin_unlock_bh(&dwc->lock);···209209 param = txd->callback_param;210210211211 dwc_sync_desc_for_cpu(dwc, desc);212212- list_splice_init(&txd->tx_list, &dwc->free_list);212212+ list_splice_init(&desc->tx_list, &dwc->free_list);213213 list_move(&desc->desc_node, &dwc->free_list);214214215215- /*216216- * We use dma_unmap_page() regardless of how the buffers were217217- * mapped before they were submitted...218218- */219219- if (!(txd->flags & DMA_COMPL_SKIP_DEST_UNMAP))220220- dma_unmap_page(chan2parent(&dwc->chan), desc->lli.dar,221221- desc->len, DMA_FROM_DEVICE);222222- if (!(txd->flags & DMA_COMPL_SKIP_SRC_UNMAP))223223- dma_unmap_page(chan2parent(&dwc->chan), desc->lli.sar,224224- desc->len, DMA_TO_DEVICE);215215+ if (!dwc->chan.private) {216216+ struct device *parent = chan2parent(&dwc->chan);217217+ if (!(txd->flags & DMA_COMPL_SKIP_DEST_UNMAP)) {218218+ if (txd->flags & DMA_COMPL_DEST_UNMAP_SINGLE)219219+ dma_unmap_single(parent, desc->lli.dar,220220+ desc->len, DMA_FROM_DEVICE);221221+ else222222+ dma_unmap_page(parent, desc->lli.dar,223223+ desc->len, DMA_FROM_DEVICE);224224+ }225225+ if (!(txd->flags & DMA_COMPL_SKIP_SRC_UNMAP)) {226226+ if (txd->flags & DMA_COMPL_SRC_UNMAP_SINGLE)227227+ dma_unmap_single(parent, desc->lli.sar,228228+ desc->len, DMA_TO_DEVICE);229229+ else230230+ dma_unmap_page(parent, desc->lli.sar,231231+ desc->len, DMA_TO_DEVICE);232232+ }233233+ }225234226235 /*227236 * The API requires that no submissions are done from a···298289 /* This one is currently in progress */299290 return;300291301301- list_for_each_entry(child, &desc->txd.tx_list, desc_node)292292+ list_for_each_entry(child, &desc->tx_list, desc_node)302293 if (child->lli.llp == llp)303294 /* Currently in progress */304295 return;···365356 dev_printk(KERN_CRIT, chan2dev(&dwc->chan),366357 " cookie: %d\n", bad_desc->txd.cookie);367358 dwc_dump_lli(dwc, &bad_desc->lli);368368- list_for_each_entry(child, &bad_desc->txd.tx_list, desc_node)359359+ list_for_each_entry(child, &bad_desc->tx_list, desc_node)369360 dwc_dump_lli(dwc, &child->lli);370361371362 /* Pretend the descriptor completed successfully */···617608 prev->txd.phys, sizeof(prev->lli),618609 DMA_TO_DEVICE);619610 list_add_tail(&desc->desc_node,620620- &first->txd.tx_list);611611+ &first->tx_list);621612 }622613 prev = desc;623614 }···667658 reg_width = dws->reg_width;668659 prev = first = NULL;669660670670- sg_len = dma_map_sg(chan2parent(chan), sgl, sg_len, direction);671671-672661 switch (direction) {673662 case DMA_TO_DEVICE:674663 ctllo = (DWC_DEFAULT_CTLLO···707700 sizeof(prev->lli),708701 DMA_TO_DEVICE);709702 list_add_tail(&desc->desc_node,710710- &first->txd.tx_list);703703+ &first->tx_list);711704 }712705 prev = desc;713706 total_len += len;···753746 sizeof(prev->lli),754747 DMA_TO_DEVICE);755748 list_add_tail(&desc->desc_node,756756- &first->txd.tx_list);749749+ &first->tx_list);757750 }758751 prev = desc;759752 total_len += len;···909902 break;910903 }911904905905+ INIT_LIST_HEAD(&desc->tx_list);912906 dma_async_tx_descriptor_init(&desc->txd, chan);913907 desc->txd.tx_submit = dwc_tx_submit;914908 desc->txd.flags = DMA_CTRL_ACK;
+1
drivers/dma/dw_dmac_regs.h
···217217218218 /* THEN values for driver housekeeping */219219 struct list_head desc_node;220220+ struct list_head tx_list;220221 struct dma_async_tx_descriptor txd;221222 size_t len;222223};
+265-23
drivers/dma/fsldma.c
···3434#include <linux/dmapool.h>3535#include <linux/of_platform.h>36363737+#include <asm/fsldma.h>3738#include "fsldma.h"38393940static void dma_init(struct fsl_dma_chan *fsl_chan)···281280}282281283282/**283283+ * fsl_chan_set_request_count - Set DMA Request Count for external control284284+ * @fsl_chan : Freescale DMA channel285285+ * @size : Number of bytes to transfer in a single request286286+ *287287+ * The Freescale DMA channel can be controlled by the external signal DREQ#.288288+ * The DMA request count is how many bytes are allowed to transfer before289289+ * pausing the channel, after which a new assertion of DREQ# resumes channel290290+ * operation.291291+ *292292+ * A size of 0 disables external pause control. The maximum size is 1024.293293+ */294294+static void fsl_chan_set_request_count(struct fsl_dma_chan *fsl_chan, int size)295295+{296296+ BUG_ON(size > 1024);297297+ DMA_OUT(fsl_chan, &fsl_chan->reg_base->mr,298298+ DMA_IN(fsl_chan, &fsl_chan->reg_base->mr, 32)299299+ | ((__ilog2(size) << 24) & 0x0f000000),300300+ 32);301301+}302302+303303+/**284304 * fsl_chan_toggle_ext_pause - Toggle channel external pause status285305 * @fsl_chan : Freescale DMA channel286286- * @size : Pause control size, 0 for disable external pause control.287287- * The maximum is 1024.306306+ * @enable : 0 is disabled, 1 is enabled.288307 *289289- * The Freescale DMA channel can be controlled by the external290290- * signal DREQ#. The pause control size is how many bytes are allowed291291- * to transfer before pausing the channel, after which a new assertion292292- * of DREQ# resumes channel operation.308308+ * The Freescale DMA channel can be controlled by the external signal DREQ#.309309+ * The DMA Request Count feature should be used in addition to this feature310310+ * to set the number of bytes to transfer before pausing the channel.293311 */294294-static void fsl_chan_toggle_ext_pause(struct fsl_dma_chan *fsl_chan, int size)312312+static void fsl_chan_toggle_ext_pause(struct fsl_dma_chan *fsl_chan, int enable)295313{296296- if (size > 1024)297297- return;298298-299299- if (size) {300300- DMA_OUT(fsl_chan, &fsl_chan->reg_base->mr,301301- DMA_IN(fsl_chan, &fsl_chan->reg_base->mr, 32)302302- | ((__ilog2(size) << 24) & 0x0f000000),303303- 32);314314+ if (enable)304315 fsl_chan->feature |= FSL_DMA_CHAN_PAUSE_EXT;305305- } else316316+ else306317 fsl_chan->feature &= ~FSL_DMA_CHAN_PAUSE_EXT;307318}308319···339326static dma_cookie_t fsl_dma_tx_submit(struct dma_async_tx_descriptor *tx)340327{341328 struct fsl_dma_chan *fsl_chan = to_fsl_chan(tx->chan);342342- struct fsl_desc_sw *desc;329329+ struct fsl_desc_sw *desc = tx_to_fsl_desc(tx);330330+ struct fsl_desc_sw *child;343331 unsigned long flags;344332 dma_cookie_t cookie;345333···348334 spin_lock_irqsave(&fsl_chan->desc_lock, flags);349335350336 cookie = fsl_chan->common.cookie;351351- list_for_each_entry(desc, &tx->tx_list, node) {337337+ list_for_each_entry(child, &desc->tx_list, node) {352338 cookie++;353339 if (cookie < 0)354340 cookie = 1;···357343 }358344359345 fsl_chan->common.cookie = cookie;360360- append_ld_queue(fsl_chan, tx_to_fsl_desc(tx));361361- list_splice_init(&tx->tx_list, fsl_chan->ld_queue.prev);346346+ append_ld_queue(fsl_chan, desc);347347+ list_splice_init(&desc->tx_list, fsl_chan->ld_queue.prev);362348363349 spin_unlock_irqrestore(&fsl_chan->desc_lock, flags);364350···380366 desc_sw = dma_pool_alloc(fsl_chan->desc_pool, GFP_ATOMIC, &pdesc);381367 if (desc_sw) {382368 memset(desc_sw, 0, sizeof(struct fsl_desc_sw));369369+ INIT_LIST_HEAD(&desc_sw->tx_list);383370 dma_async_tx_descriptor_init(&desc_sw->async_tx,384371 &fsl_chan->common);385372 desc_sw->async_tx.tx_submit = fsl_dma_tx_submit;···470455 new->async_tx.flags = flags;471456472457 /* Insert the link descriptor to the LD ring */473473- list_add_tail(&new->node, &new->async_tx.tx_list);458458+ list_add_tail(&new->node, &new->tx_list);474459475460 /* Set End-of-link to the last link descriptor of new list*/476461 set_ld_eol(fsl_chan, new);···528513 dma_dest += copy;529514530515 /* Insert the link descriptor to the LD ring */531531- list_add_tail(&new->node, &first->async_tx.tx_list);516516+ list_add_tail(&new->node, &first->tx_list);532517 } while (len);533518534519 new->async_tx.flags = flags; /* client is in control of this ack */···543528 if (!first)544529 return NULL;545530546546- list = &first->async_tx.tx_list;531531+ list = &first->tx_list;547532 list_for_each_entry_safe_reverse(new, prev, list, node) {548533 list_del(&new->node);549534 dma_pool_free(fsl_chan->desc_pool, new, new->async_tx.phys);550535 }551536552537 return NULL;538538+}539539+540540+/**541541+ * fsl_dma_prep_slave_sg - prepare descriptors for a DMA_SLAVE transaction542542+ * @chan: DMA channel543543+ * @sgl: scatterlist to transfer to/from544544+ * @sg_len: number of entries in @scatterlist545545+ * @direction: DMA direction546546+ * @flags: DMAEngine flags547547+ *548548+ * Prepare a set of descriptors for a DMA_SLAVE transaction. Following the549549+ * DMA_SLAVE API, this gets the device-specific information from the550550+ * chan->private variable.551551+ */552552+static struct dma_async_tx_descriptor *fsl_dma_prep_slave_sg(553553+ struct dma_chan *chan, struct scatterlist *sgl, unsigned int sg_len,554554+ enum dma_data_direction direction, unsigned long flags)555555+{556556+ struct fsl_dma_chan *fsl_chan;557557+ struct fsl_desc_sw *first = NULL, *prev = NULL, *new = NULL;558558+ struct fsl_dma_slave *slave;559559+ struct list_head *tx_list;560560+ size_t copy;561561+562562+ int i;563563+ struct scatterlist *sg;564564+ size_t sg_used;565565+ size_t hw_used;566566+ struct fsl_dma_hw_addr *hw;567567+ dma_addr_t dma_dst, dma_src;568568+569569+ if (!chan)570570+ return NULL;571571+572572+ if (!chan->private)573573+ return NULL;574574+575575+ fsl_chan = to_fsl_chan(chan);576576+ slave = chan->private;577577+578578+ if (list_empty(&slave->addresses))579579+ return NULL;580580+581581+ hw = list_first_entry(&slave->addresses, struct fsl_dma_hw_addr, entry);582582+ hw_used = 0;583583+584584+ /*585585+ * Build the hardware transaction to copy from the scatterlist to586586+ * the hardware, or from the hardware to the scatterlist587587+ *588588+ * If you are copying from the hardware to the scatterlist and it589589+ * takes two hardware entries to fill an entire page, then both590590+ * hardware entries will be coalesced into the same page591591+ *592592+ * If you are copying from the scatterlist to the hardware and a593593+ * single page can fill two hardware entries, then the data will594594+ * be read out of the page into the first hardware entry, and so on595595+ */596596+ for_each_sg(sgl, sg, sg_len, i) {597597+ sg_used = 0;598598+599599+ /* Loop until the entire scatterlist entry is used */600600+ while (sg_used < sg_dma_len(sg)) {601601+602602+ /*603603+ * If we've used up the current hardware address/length604604+ * pair, we need to load a new one605605+ *606606+ * This is done in a while loop so that descriptors with607607+ * length == 0 will be skipped608608+ */609609+ while (hw_used >= hw->length) {610610+611611+ /*612612+ * If the current hardware entry is the last613613+ * entry in the list, we're finished614614+ */615615+ if (list_is_last(&hw->entry, &slave->addresses))616616+ goto finished;617617+618618+ /* Get the next hardware address/length pair */619619+ hw = list_entry(hw->entry.next,620620+ struct fsl_dma_hw_addr, entry);621621+ hw_used = 0;622622+ }623623+624624+ /* Allocate the link descriptor from DMA pool */625625+ new = fsl_dma_alloc_descriptor(fsl_chan);626626+ if (!new) {627627+ dev_err(fsl_chan->dev, "No free memory for "628628+ "link descriptor\n");629629+ goto fail;630630+ }631631+#ifdef FSL_DMA_LD_DEBUG632632+ dev_dbg(fsl_chan->dev, "new link desc alloc %p\n", new);633633+#endif634634+635635+ /*636636+ * Calculate the maximum number of bytes to transfer,637637+ * making sure it is less than the DMA controller limit638638+ */639639+ copy = min_t(size_t, sg_dma_len(sg) - sg_used,640640+ hw->length - hw_used);641641+ copy = min_t(size_t, copy, FSL_DMA_BCR_MAX_CNT);642642+643643+ /*644644+ * DMA_FROM_DEVICE645645+ * from the hardware to the scatterlist646646+ *647647+ * DMA_TO_DEVICE648648+ * from the scatterlist to the hardware649649+ */650650+ if (direction == DMA_FROM_DEVICE) {651651+ dma_src = hw->address + hw_used;652652+ dma_dst = sg_dma_address(sg) + sg_used;653653+ } else {654654+ dma_src = sg_dma_address(sg) + sg_used;655655+ dma_dst = hw->address + hw_used;656656+ }657657+658658+ /* Fill in the descriptor */659659+ set_desc_cnt(fsl_chan, &new->hw, copy);660660+ set_desc_src(fsl_chan, &new->hw, dma_src);661661+ set_desc_dest(fsl_chan, &new->hw, dma_dst);662662+663663+ /*664664+ * If this is not the first descriptor, chain the665665+ * current descriptor after the previous descriptor666666+ */667667+ if (!first) {668668+ first = new;669669+ } else {670670+ set_desc_next(fsl_chan, &prev->hw,671671+ new->async_tx.phys);672672+ }673673+674674+ new->async_tx.cookie = 0;675675+ async_tx_ack(&new->async_tx);676676+677677+ prev = new;678678+ sg_used += copy;679679+ hw_used += copy;680680+681681+ /* Insert the link descriptor into the LD ring */682682+ list_add_tail(&new->node, &first->tx_list);683683+ }684684+ }685685+686686+finished:687687+688688+ /* All of the hardware address/length pairs had length == 0 */689689+ if (!first || !new)690690+ return NULL;691691+692692+ new->async_tx.flags = flags;693693+ new->async_tx.cookie = -EBUSY;694694+695695+ /* Set End-of-link to the last link descriptor of new list */696696+ set_ld_eol(fsl_chan, new);697697+698698+ /* Enable extra controller features */699699+ if (fsl_chan->set_src_loop_size)700700+ fsl_chan->set_src_loop_size(fsl_chan, slave->src_loop_size);701701+702702+ if (fsl_chan->set_dest_loop_size)703703+ fsl_chan->set_dest_loop_size(fsl_chan, slave->dst_loop_size);704704+705705+ if (fsl_chan->toggle_ext_start)706706+ fsl_chan->toggle_ext_start(fsl_chan, slave->external_start);707707+708708+ if (fsl_chan->toggle_ext_pause)709709+ fsl_chan->toggle_ext_pause(fsl_chan, slave->external_pause);710710+711711+ if (fsl_chan->set_request_count)712712+ fsl_chan->set_request_count(fsl_chan, slave->request_count);713713+714714+ return &first->async_tx;715715+716716+fail:717717+ /* If first was not set, then we failed to allocate the very first718718+ * descriptor, and we're done */719719+ if (!first)720720+ return NULL;721721+722722+ /*723723+ * First is set, so all of the descriptors we allocated have been added724724+ * to first->tx_list, INCLUDING "first" itself. Therefore we725725+ * must traverse the list backwards freeing each descriptor in turn726726+ *727727+ * We're re-using variables for the loop, oh well728728+ */729729+ tx_list = &first->tx_list;730730+ list_for_each_entry_safe_reverse(new, prev, tx_list, node) {731731+ list_del_init(&new->node);732732+ dma_pool_free(fsl_chan->desc_pool, new, new->async_tx.phys);733733+ }734734+735735+ return NULL;736736+}737737+738738+static void fsl_dma_device_terminate_all(struct dma_chan *chan)739739+{740740+ struct fsl_dma_chan *fsl_chan;741741+ struct fsl_desc_sw *desc, *tmp;742742+ unsigned long flags;743743+744744+ if (!chan)745745+ return;746746+747747+ fsl_chan = to_fsl_chan(chan);748748+749749+ /* Halt the DMA engine */750750+ dma_halt(fsl_chan);751751+752752+ spin_lock_irqsave(&fsl_chan->desc_lock, flags);753753+754754+ /* Remove and free all of the descriptors in the LD queue */755755+ list_for_each_entry_safe(desc, tmp, &fsl_chan->ld_queue, node) {756756+ list_del(&desc->node);757757+ dma_pool_free(fsl_chan->desc_pool, desc, desc->async_tx.phys);758758+ }759759+760760+ spin_unlock_irqrestore(&fsl_chan->desc_lock, flags);553761}554762555763/**···1121883 new_fsl_chan->toggle_ext_start = fsl_chan_toggle_ext_start;1122884 new_fsl_chan->set_src_loop_size = fsl_chan_set_src_loop_size;1123885 new_fsl_chan->set_dest_loop_size = fsl_chan_set_dest_loop_size;886886+ new_fsl_chan->set_request_count = fsl_chan_set_request_count;1124887 }11258881126889 spin_lock_init(&new_fsl_chan->desc_lock);···12019621202963 dma_cap_set(DMA_MEMCPY, fdev->common.cap_mask);1203964 dma_cap_set(DMA_INTERRUPT, fdev->common.cap_mask);965965+ dma_cap_set(DMA_SLAVE, fdev->common.cap_mask);1204966 fdev->common.device_alloc_chan_resources = fsl_dma_alloc_chan_resources;1205967 fdev->common.device_free_chan_resources = fsl_dma_free_chan_resources;1206968 fdev->common.device_prep_dma_interrupt = fsl_dma_prep_interrupt;1207969 fdev->common.device_prep_dma_memcpy = fsl_dma_prep_memcpy;1208970 fdev->common.device_is_tx_complete = fsl_dma_is_complete;1209971 fdev->common.device_issue_pending = fsl_dma_memcpy_issue_pending;972972+ fdev->common.device_prep_slave_sg = fsl_dma_prep_slave_sg;973973+ fdev->common.device_terminate_all = fsl_dma_device_terminate_all;1210974 fdev->common.dev = &dev->dev;12119751212976 fdev->irq = irq_of_parse_and_map(dev->node, 0);
···11+/*22+ * Intel I/OAT DMA Linux driver33+ * Copyright(c) 2004 - 2009 Intel Corporation.44+ *55+ * This program is free software; you can redistribute it and/or modify it66+ * under the terms and conditions of the GNU General Public License,77+ * version 2, as published by the Free Software Foundation.88+ *99+ * This program is distributed in the hope that it will be useful, but WITHOUT1010+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or1111+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for1212+ * more details.1313+ *1414+ * You should have received a copy of the GNU General Public License along with1515+ * this program; if not, write to the Free Software Foundation, Inc.,1616+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.1717+ *1818+ * The full GNU General Public License is included in this distribution in1919+ * the file called "COPYING".2020+ *2121+ */2222+2323+/*2424+ * This driver supports an Intel I/OAT DMA engine, which does asynchronous2525+ * copy operations.2626+ */2727+2828+#include <linux/init.h>2929+#include <linux/module.h>3030+#include <linux/pci.h>3131+#include <linux/interrupt.h>3232+#include <linux/dmaengine.h>3333+#include <linux/delay.h>3434+#include <linux/dma-mapping.h>3535+#include <linux/workqueue.h>3636+#include <linux/i7300_idle.h>3737+#include "dma.h"3838+#include "registers.h"3939+#include "hw.h"4040+4141+int ioat_pending_level = 4;4242+module_param(ioat_pending_level, int, 0644);4343+MODULE_PARM_DESC(ioat_pending_level,4444+ "high-water mark for pushing ioat descriptors (default: 4)");4545+4646+/* internal functions */4747+static void ioat1_cleanup(struct ioat_dma_chan *ioat);4848+static void ioat1_dma_start_null_desc(struct ioat_dma_chan *ioat);4949+5050+/**5151+ * ioat_dma_do_interrupt - handler used for single vector interrupt mode5252+ * @irq: interrupt id5353+ * @data: interrupt data5454+ */5555+static irqreturn_t ioat_dma_do_interrupt(int irq, void *data)5656+{5757+ struct ioatdma_device *instance = data;5858+ struct ioat_chan_common *chan;5959+ unsigned long attnstatus;6060+ int bit;6161+ u8 intrctrl;6262+6363+ intrctrl = readb(instance->reg_base + IOAT_INTRCTRL_OFFSET);6464+6565+ if (!(intrctrl & IOAT_INTRCTRL_MASTER_INT_EN))6666+ return IRQ_NONE;6767+6868+ if (!(intrctrl & IOAT_INTRCTRL_INT_STATUS)) {6969+ writeb(intrctrl, instance->reg_base + IOAT_INTRCTRL_OFFSET);7070+ return IRQ_NONE;7171+ }7272+7373+ attnstatus = readl(instance->reg_base + IOAT_ATTNSTATUS_OFFSET);7474+ for_each_bit(bit, &attnstatus, BITS_PER_LONG) {7575+ chan = ioat_chan_by_index(instance, bit);7676+ tasklet_schedule(&chan->cleanup_task);7777+ }7878+7979+ writeb(intrctrl, instance->reg_base + IOAT_INTRCTRL_OFFSET);8080+ return IRQ_HANDLED;8181+}8282+8383+/**8484+ * ioat_dma_do_interrupt_msix - handler used for vector-per-channel interrupt mode8585+ * @irq: interrupt id8686+ * @data: interrupt data8787+ */8888+static irqreturn_t ioat_dma_do_interrupt_msix(int irq, void *data)8989+{9090+ struct ioat_chan_common *chan = data;9191+9292+ tasklet_schedule(&chan->cleanup_task);9393+9494+ return IRQ_HANDLED;9595+}9696+9797+static void ioat1_cleanup_tasklet(unsigned long data);9898+9999+/* common channel initialization */100100+void ioat_init_channel(struct ioatdma_device *device,101101+ struct ioat_chan_common *chan, int idx,102102+ void (*timer_fn)(unsigned long),103103+ void (*tasklet)(unsigned long),104104+ unsigned long ioat)105105+{106106+ struct dma_device *dma = &device->common;107107+108108+ chan->device = device;109109+ chan->reg_base = device->reg_base + (0x80 * (idx + 1));110110+ spin_lock_init(&chan->cleanup_lock);111111+ chan->common.device = dma;112112+ list_add_tail(&chan->common.device_node, &dma->channels);113113+ device->idx[idx] = chan;114114+ init_timer(&chan->timer);115115+ chan->timer.function = timer_fn;116116+ chan->timer.data = ioat;117117+ tasklet_init(&chan->cleanup_task, tasklet, ioat);118118+ tasklet_disable(&chan->cleanup_task);119119+}120120+121121+static void ioat1_timer_event(unsigned long data);122122+123123+/**124124+ * ioat1_dma_enumerate_channels - find and initialize the device's channels125125+ * @device: the device to be enumerated126126+ */127127+static int ioat1_enumerate_channels(struct ioatdma_device *device)128128+{129129+ u8 xfercap_scale;130130+ u32 xfercap;131131+ int i;132132+ struct ioat_dma_chan *ioat;133133+ struct device *dev = &device->pdev->dev;134134+ struct dma_device *dma = &device->common;135135+136136+ INIT_LIST_HEAD(&dma->channels);137137+ dma->chancnt = readb(device->reg_base + IOAT_CHANCNT_OFFSET);138138+ dma->chancnt &= 0x1f; /* bits [4:0] valid */139139+ if (dma->chancnt > ARRAY_SIZE(device->idx)) {140140+ dev_warn(dev, "(%d) exceeds max supported channels (%zu)\n",141141+ dma->chancnt, ARRAY_SIZE(device->idx));142142+ dma->chancnt = ARRAY_SIZE(device->idx);143143+ }144144+ xfercap_scale = readb(device->reg_base + IOAT_XFERCAP_OFFSET);145145+ xfercap_scale &= 0x1f; /* bits [4:0] valid */146146+ xfercap = (xfercap_scale == 0 ? -1 : (1UL << xfercap_scale));147147+ dev_dbg(dev, "%s: xfercap = %d\n", __func__, xfercap);148148+149149+#ifdef CONFIG_I7300_IDLE_IOAT_CHANNEL150150+ if (i7300_idle_platform_probe(NULL, NULL, 1) == 0)151151+ dma->chancnt--;152152+#endif153153+ for (i = 0; i < dma->chancnt; i++) {154154+ ioat = devm_kzalloc(dev, sizeof(*ioat), GFP_KERNEL);155155+ if (!ioat)156156+ break;157157+158158+ ioat_init_channel(device, &ioat->base, i,159159+ ioat1_timer_event,160160+ ioat1_cleanup_tasklet,161161+ (unsigned long) ioat);162162+ ioat->xfercap = xfercap;163163+ spin_lock_init(&ioat->desc_lock);164164+ INIT_LIST_HEAD(&ioat->free_desc);165165+ INIT_LIST_HEAD(&ioat->used_desc);166166+ }167167+ dma->chancnt = i;168168+ return i;169169+}170170+171171+/**172172+ * ioat_dma_memcpy_issue_pending - push potentially unrecognized appended173173+ * descriptors to hw174174+ * @chan: DMA channel handle175175+ */176176+static inline void177177+__ioat1_dma_memcpy_issue_pending(struct ioat_dma_chan *ioat)178178+{179179+ void __iomem *reg_base = ioat->base.reg_base;180180+181181+ dev_dbg(to_dev(&ioat->base), "%s: pending: %d\n",182182+ __func__, ioat->pending);183183+ ioat->pending = 0;184184+ writeb(IOAT_CHANCMD_APPEND, reg_base + IOAT1_CHANCMD_OFFSET);185185+}186186+187187+static void ioat1_dma_memcpy_issue_pending(struct dma_chan *chan)188188+{189189+ struct ioat_dma_chan *ioat = to_ioat_chan(chan);190190+191191+ if (ioat->pending > 0) {192192+ spin_lock_bh(&ioat->desc_lock);193193+ __ioat1_dma_memcpy_issue_pending(ioat);194194+ spin_unlock_bh(&ioat->desc_lock);195195+ }196196+}197197+198198+/**199199+ * ioat1_reset_channel - restart a channel200200+ * @ioat: IOAT DMA channel handle201201+ */202202+static void ioat1_reset_channel(struct ioat_dma_chan *ioat)203203+{204204+ struct ioat_chan_common *chan = &ioat->base;205205+ void __iomem *reg_base = chan->reg_base;206206+ u32 chansts, chanerr;207207+208208+ dev_warn(to_dev(chan), "reset\n");209209+ chanerr = readl(reg_base + IOAT_CHANERR_OFFSET);210210+ chansts = *chan->completion & IOAT_CHANSTS_STATUS;211211+ if (chanerr) {212212+ dev_err(to_dev(chan),213213+ "chan%d, CHANSTS = 0x%08x CHANERR = 0x%04x, clearing\n",214214+ chan_num(chan), chansts, chanerr);215215+ writel(chanerr, reg_base + IOAT_CHANERR_OFFSET);216216+ }217217+218218+ /*219219+ * whack it upside the head with a reset220220+ * and wait for things to settle out.221221+ * force the pending count to a really big negative222222+ * to make sure no one forces an issue_pending223223+ * while we're waiting.224224+ */225225+226226+ ioat->pending = INT_MIN;227227+ writeb(IOAT_CHANCMD_RESET,228228+ reg_base + IOAT_CHANCMD_OFFSET(chan->device->version));229229+ set_bit(IOAT_RESET_PENDING, &chan->state);230230+ mod_timer(&chan->timer, jiffies + RESET_DELAY);231231+}232232+233233+static dma_cookie_t ioat1_tx_submit(struct dma_async_tx_descriptor *tx)234234+{235235+ struct dma_chan *c = tx->chan;236236+ struct ioat_dma_chan *ioat = to_ioat_chan(c);237237+ struct ioat_desc_sw *desc = tx_to_ioat_desc(tx);238238+ struct ioat_chan_common *chan = &ioat->base;239239+ struct ioat_desc_sw *first;240240+ struct ioat_desc_sw *chain_tail;241241+ dma_cookie_t cookie;242242+243243+ spin_lock_bh(&ioat->desc_lock);244244+ /* cookie incr and addition to used_list must be atomic */245245+ cookie = c->cookie;246246+ cookie++;247247+ if (cookie < 0)248248+ cookie = 1;249249+ c->cookie = cookie;250250+ tx->cookie = cookie;251251+ dev_dbg(to_dev(&ioat->base), "%s: cookie: %d\n", __func__, cookie);252252+253253+ /* write address into NextDescriptor field of last desc in chain */254254+ first = to_ioat_desc(desc->tx_list.next);255255+ chain_tail = to_ioat_desc(ioat->used_desc.prev);256256+ /* make descriptor updates globally visible before chaining */257257+ wmb();258258+ chain_tail->hw->next = first->txd.phys;259259+ list_splice_tail_init(&desc->tx_list, &ioat->used_desc);260260+ dump_desc_dbg(ioat, chain_tail);261261+ dump_desc_dbg(ioat, first);262262+263263+ if (!test_and_set_bit(IOAT_COMPLETION_PENDING, &chan->state))264264+ mod_timer(&chan->timer, jiffies + COMPLETION_TIMEOUT);265265+266266+ ioat->active += desc->hw->tx_cnt;267267+ ioat->pending += desc->hw->tx_cnt;268268+ if (ioat->pending >= ioat_pending_level)269269+ __ioat1_dma_memcpy_issue_pending(ioat);270270+ spin_unlock_bh(&ioat->desc_lock);271271+272272+ return cookie;273273+}274274+275275+/**276276+ * ioat_dma_alloc_descriptor - allocate and return a sw and hw descriptor pair277277+ * @ioat: the channel supplying the memory pool for the descriptors278278+ * @flags: allocation flags279279+ */280280+static struct ioat_desc_sw *281281+ioat_dma_alloc_descriptor(struct ioat_dma_chan *ioat, gfp_t flags)282282+{283283+ struct ioat_dma_descriptor *desc;284284+ struct ioat_desc_sw *desc_sw;285285+ struct ioatdma_device *ioatdma_device;286286+ dma_addr_t phys;287287+288288+ ioatdma_device = ioat->base.device;289289+ desc = pci_pool_alloc(ioatdma_device->dma_pool, flags, &phys);290290+ if (unlikely(!desc))291291+ return NULL;292292+293293+ desc_sw = kzalloc(sizeof(*desc_sw), flags);294294+ if (unlikely(!desc_sw)) {295295+ pci_pool_free(ioatdma_device->dma_pool, desc, phys);296296+ return NULL;297297+ }298298+299299+ memset(desc, 0, sizeof(*desc));300300+301301+ INIT_LIST_HEAD(&desc_sw->tx_list);302302+ dma_async_tx_descriptor_init(&desc_sw->txd, &ioat->base.common);303303+ desc_sw->txd.tx_submit = ioat1_tx_submit;304304+ desc_sw->hw = desc;305305+ desc_sw->txd.phys = phys;306306+ set_desc_id(desc_sw, -1);307307+308308+ return desc_sw;309309+}310310+311311+static int ioat_initial_desc_count = 256;312312+module_param(ioat_initial_desc_count, int, 0644);313313+MODULE_PARM_DESC(ioat_initial_desc_count,314314+ "ioat1: initial descriptors per channel (default: 256)");315315+/**316316+ * ioat1_dma_alloc_chan_resources - returns the number of allocated descriptors317317+ * @chan: the channel to be filled out318318+ */319319+static int ioat1_dma_alloc_chan_resources(struct dma_chan *c)320320+{321321+ struct ioat_dma_chan *ioat = to_ioat_chan(c);322322+ struct ioat_chan_common *chan = &ioat->base;323323+ struct ioat_desc_sw *desc;324324+ u32 chanerr;325325+ int i;326326+ LIST_HEAD(tmp_list);327327+328328+ /* have we already been set up? */329329+ if (!list_empty(&ioat->free_desc))330330+ return ioat->desccount;331331+332332+ /* Setup register to interrupt and write completion status on error */333333+ writew(IOAT_CHANCTRL_RUN, chan->reg_base + IOAT_CHANCTRL_OFFSET);334334+335335+ chanerr = readl(chan->reg_base + IOAT_CHANERR_OFFSET);336336+ if (chanerr) {337337+ dev_err(to_dev(chan), "CHANERR = %x, clearing\n", chanerr);338338+ writel(chanerr, chan->reg_base + IOAT_CHANERR_OFFSET);339339+ }340340+341341+ /* Allocate descriptors */342342+ for (i = 0; i < ioat_initial_desc_count; i++) {343343+ desc = ioat_dma_alloc_descriptor(ioat, GFP_KERNEL);344344+ if (!desc) {345345+ dev_err(to_dev(chan), "Only %d initial descriptors\n", i);346346+ break;347347+ }348348+ set_desc_id(desc, i);349349+ list_add_tail(&desc->node, &tmp_list);350350+ }351351+ spin_lock_bh(&ioat->desc_lock);352352+ ioat->desccount = i;353353+ list_splice(&tmp_list, &ioat->free_desc);354354+ spin_unlock_bh(&ioat->desc_lock);355355+356356+ /* allocate a completion writeback area */357357+ /* doing 2 32bit writes to mmio since 1 64b write doesn't work */358358+ chan->completion = pci_pool_alloc(chan->device->completion_pool,359359+ GFP_KERNEL, &chan->completion_dma);360360+ memset(chan->completion, 0, sizeof(*chan->completion));361361+ writel(((u64) chan->completion_dma) & 0x00000000FFFFFFFF,362362+ chan->reg_base + IOAT_CHANCMP_OFFSET_LOW);363363+ writel(((u64) chan->completion_dma) >> 32,364364+ chan->reg_base + IOAT_CHANCMP_OFFSET_HIGH);365365+366366+ tasklet_enable(&chan->cleanup_task);367367+ ioat1_dma_start_null_desc(ioat); /* give chain to dma device */368368+ dev_dbg(to_dev(chan), "%s: allocated %d descriptors\n",369369+ __func__, ioat->desccount);370370+ return ioat->desccount;371371+}372372+373373+/**374374+ * ioat1_dma_free_chan_resources - release all the descriptors375375+ * @chan: the channel to be cleaned376376+ */377377+static void ioat1_dma_free_chan_resources(struct dma_chan *c)378378+{379379+ struct ioat_dma_chan *ioat = to_ioat_chan(c);380380+ struct ioat_chan_common *chan = &ioat->base;381381+ struct ioatdma_device *ioatdma_device = chan->device;382382+ struct ioat_desc_sw *desc, *_desc;383383+ int in_use_descs = 0;384384+385385+ /* Before freeing channel resources first check386386+ * if they have been previously allocated for this channel.387387+ */388388+ if (ioat->desccount == 0)389389+ return;390390+391391+ tasklet_disable(&chan->cleanup_task);392392+ del_timer_sync(&chan->timer);393393+ ioat1_cleanup(ioat);394394+395395+ /* Delay 100ms after reset to allow internal DMA logic to quiesce396396+ * before removing DMA descriptor resources.397397+ */398398+ writeb(IOAT_CHANCMD_RESET,399399+ chan->reg_base + IOAT_CHANCMD_OFFSET(chan->device->version));400400+ mdelay(100);401401+402402+ spin_lock_bh(&ioat->desc_lock);403403+ list_for_each_entry_safe(desc, _desc, &ioat->used_desc, node) {404404+ dev_dbg(to_dev(chan), "%s: freeing %d from used list\n",405405+ __func__, desc_id(desc));406406+ dump_desc_dbg(ioat, desc);407407+ in_use_descs++;408408+ list_del(&desc->node);409409+ pci_pool_free(ioatdma_device->dma_pool, desc->hw,410410+ desc->txd.phys);411411+ kfree(desc);412412+ }413413+ list_for_each_entry_safe(desc, _desc,414414+ &ioat->free_desc, node) {415415+ list_del(&desc->node);416416+ pci_pool_free(ioatdma_device->dma_pool, desc->hw,417417+ desc->txd.phys);418418+ kfree(desc);419419+ }420420+ spin_unlock_bh(&ioat->desc_lock);421421+422422+ pci_pool_free(ioatdma_device->completion_pool,423423+ chan->completion,424424+ chan->completion_dma);425425+426426+ /* one is ok since we left it on there on purpose */427427+ if (in_use_descs > 1)428428+ dev_err(to_dev(chan), "Freeing %d in use descriptors!\n",429429+ in_use_descs - 1);430430+431431+ chan->last_completion = 0;432432+ chan->completion_dma = 0;433433+ ioat->pending = 0;434434+ ioat->desccount = 0;435435+}436436+437437+/**438438+ * ioat1_dma_get_next_descriptor - return the next available descriptor439439+ * @ioat: IOAT DMA channel handle440440+ *441441+ * Gets the next descriptor from the chain, and must be called with the442442+ * channel's desc_lock held. Allocates more descriptors if the channel443443+ * has run out.444444+ */445445+static struct ioat_desc_sw *446446+ioat1_dma_get_next_descriptor(struct ioat_dma_chan *ioat)447447+{448448+ struct ioat_desc_sw *new;449449+450450+ if (!list_empty(&ioat->free_desc)) {451451+ new = to_ioat_desc(ioat->free_desc.next);452452+ list_del(&new->node);453453+ } else {454454+ /* try to get another desc */455455+ new = ioat_dma_alloc_descriptor(ioat, GFP_ATOMIC);456456+ if (!new) {457457+ dev_err(to_dev(&ioat->base), "alloc failed\n");458458+ return NULL;459459+ }460460+ }461461+ dev_dbg(to_dev(&ioat->base), "%s: allocated: %d\n",462462+ __func__, desc_id(new));463463+ prefetch(new->hw);464464+ return new;465465+}466466+467467+static struct dma_async_tx_descriptor *468468+ioat1_dma_prep_memcpy(struct dma_chan *c, dma_addr_t dma_dest,469469+ dma_addr_t dma_src, size_t len, unsigned long flags)470470+{471471+ struct ioat_dma_chan *ioat = to_ioat_chan(c);472472+ struct ioat_desc_sw *desc;473473+ size_t copy;474474+ LIST_HEAD(chain);475475+ dma_addr_t src = dma_src;476476+ dma_addr_t dest = dma_dest;477477+ size_t total_len = len;478478+ struct ioat_dma_descriptor *hw = NULL;479479+ int tx_cnt = 0;480480+481481+ spin_lock_bh(&ioat->desc_lock);482482+ desc = ioat1_dma_get_next_descriptor(ioat);483483+ do {484484+ if (!desc)485485+ break;486486+487487+ tx_cnt++;488488+ copy = min_t(size_t, len, ioat->xfercap);489489+490490+ hw = desc->hw;491491+ hw->size = copy;492492+ hw->ctl = 0;493493+ hw->src_addr = src;494494+ hw->dst_addr = dest;495495+496496+ list_add_tail(&desc->node, &chain);497497+498498+ len -= copy;499499+ dest += copy;500500+ src += copy;501501+ if (len) {502502+ struct ioat_desc_sw *next;503503+504504+ async_tx_ack(&desc->txd);505505+ next = ioat1_dma_get_next_descriptor(ioat);506506+ hw->next = next ? next->txd.phys : 0;507507+ dump_desc_dbg(ioat, desc);508508+ desc = next;509509+ } else510510+ hw->next = 0;511511+ } while (len);512512+513513+ if (!desc) {514514+ struct ioat_chan_common *chan = &ioat->base;515515+516516+ dev_err(to_dev(chan),517517+ "chan%d - get_next_desc failed\n", chan_num(chan));518518+ list_splice(&chain, &ioat->free_desc);519519+ spin_unlock_bh(&ioat->desc_lock);520520+ return NULL;521521+ }522522+ spin_unlock_bh(&ioat->desc_lock);523523+524524+ desc->txd.flags = flags;525525+ desc->len = total_len;526526+ list_splice(&chain, &desc->tx_list);527527+ hw->ctl_f.int_en = !!(flags & DMA_PREP_INTERRUPT);528528+ hw->ctl_f.compl_write = 1;529529+ hw->tx_cnt = tx_cnt;530530+ dump_desc_dbg(ioat, desc);531531+532532+ return &desc->txd;533533+}534534+535535+static void ioat1_cleanup_tasklet(unsigned long data)536536+{537537+ struct ioat_dma_chan *chan = (void *)data;538538+539539+ ioat1_cleanup(chan);540540+ writew(IOAT_CHANCTRL_RUN, chan->base.reg_base + IOAT_CHANCTRL_OFFSET);541541+}542542+543543+void ioat_dma_unmap(struct ioat_chan_common *chan, enum dma_ctrl_flags flags,544544+ size_t len, struct ioat_dma_descriptor *hw)545545+{546546+ struct pci_dev *pdev = chan->device->pdev;547547+ size_t offset = len - hw->size;548548+549549+ if (!(flags & DMA_COMPL_SKIP_DEST_UNMAP))550550+ ioat_unmap(pdev, hw->dst_addr - offset, len,551551+ PCI_DMA_FROMDEVICE, flags, 1);552552+553553+ if (!(flags & DMA_COMPL_SKIP_SRC_UNMAP))554554+ ioat_unmap(pdev, hw->src_addr - offset, len,555555+ PCI_DMA_TODEVICE, flags, 0);556556+}557557+558558+unsigned long ioat_get_current_completion(struct ioat_chan_common *chan)559559+{560560+ unsigned long phys_complete;561561+ u64 completion;562562+563563+ completion = *chan->completion;564564+ phys_complete = ioat_chansts_to_addr(completion);565565+566566+ dev_dbg(to_dev(chan), "%s: phys_complete: %#llx\n", __func__,567567+ (unsigned long long) phys_complete);568568+569569+ if (is_ioat_halted(completion)) {570570+ u32 chanerr = readl(chan->reg_base + IOAT_CHANERR_OFFSET);571571+ dev_err(to_dev(chan), "Channel halted, chanerr = %x\n",572572+ chanerr);573573+574574+ /* TODO do something to salvage the situation */575575+ }576576+577577+ return phys_complete;578578+}579579+580580+bool ioat_cleanup_preamble(struct ioat_chan_common *chan,581581+ unsigned long *phys_complete)582582+{583583+ *phys_complete = ioat_get_current_completion(chan);584584+ if (*phys_complete == chan->last_completion)585585+ return false;586586+ clear_bit(IOAT_COMPLETION_ACK, &chan->state);587587+ mod_timer(&chan->timer, jiffies + COMPLETION_TIMEOUT);588588+589589+ return true;590590+}591591+592592+static void __cleanup(struct ioat_dma_chan *ioat, unsigned long phys_complete)593593+{594594+ struct ioat_chan_common *chan = &ioat->base;595595+ struct list_head *_desc, *n;596596+ struct dma_async_tx_descriptor *tx;597597+598598+ dev_dbg(to_dev(chan), "%s: phys_complete: %lx\n",599599+ __func__, phys_complete);600600+ list_for_each_safe(_desc, n, &ioat->used_desc) {601601+ struct ioat_desc_sw *desc;602602+603603+ prefetch(n);604604+ desc = list_entry(_desc, typeof(*desc), node);605605+ tx = &desc->txd;606606+ /*607607+ * Incoming DMA requests may use multiple descriptors,608608+ * due to exceeding xfercap, perhaps. If so, only the609609+ * last one will have a cookie, and require unmapping.610610+ */611611+ dump_desc_dbg(ioat, desc);612612+ if (tx->cookie) {613613+ chan->completed_cookie = tx->cookie;614614+ tx->cookie = 0;615615+ ioat_dma_unmap(chan, tx->flags, desc->len, desc->hw);616616+ ioat->active -= desc->hw->tx_cnt;617617+ if (tx->callback) {618618+ tx->callback(tx->callback_param);619619+ tx->callback = NULL;620620+ }621621+ }622622+623623+ if (tx->phys != phys_complete) {624624+ /*625625+ * a completed entry, but not the last, so clean626626+ * up if the client is done with the descriptor627627+ */628628+ if (async_tx_test_ack(tx))629629+ list_move_tail(&desc->node, &ioat->free_desc);630630+ } else {631631+ /*632632+ * last used desc. Do not remove, so we can633633+ * append from it.634634+ */635635+636636+ /* if nothing else is pending, cancel the637637+ * completion timeout638638+ */639639+ if (n == &ioat->used_desc) {640640+ dev_dbg(to_dev(chan),641641+ "%s cancel completion timeout\n",642642+ __func__);643643+ clear_bit(IOAT_COMPLETION_PENDING, &chan->state);644644+ }645645+646646+ /* TODO check status bits? */647647+ break;648648+ }649649+ }650650+651651+ chan->last_completion = phys_complete;652652+}653653+654654+/**655655+ * ioat1_cleanup - cleanup up finished descriptors656656+ * @chan: ioat channel to be cleaned up657657+ *658658+ * To prevent lock contention we defer cleanup when the locks are659659+ * contended with a terminal timeout that forces cleanup and catches660660+ * completion notification errors.661661+ */662662+static void ioat1_cleanup(struct ioat_dma_chan *ioat)663663+{664664+ struct ioat_chan_common *chan = &ioat->base;665665+ unsigned long phys_complete;666666+667667+ prefetch(chan->completion);668668+669669+ if (!spin_trylock_bh(&chan->cleanup_lock))670670+ return;671671+672672+ if (!ioat_cleanup_preamble(chan, &phys_complete)) {673673+ spin_unlock_bh(&chan->cleanup_lock);674674+ return;675675+ }676676+677677+ if (!spin_trylock_bh(&ioat->desc_lock)) {678678+ spin_unlock_bh(&chan->cleanup_lock);679679+ return;680680+ }681681+682682+ __cleanup(ioat, phys_complete);683683+684684+ spin_unlock_bh(&ioat->desc_lock);685685+ spin_unlock_bh(&chan->cleanup_lock);686686+}687687+688688+static void ioat1_timer_event(unsigned long data)689689+{690690+ struct ioat_dma_chan *ioat = (void *) data;691691+ struct ioat_chan_common *chan = &ioat->base;692692+693693+ dev_dbg(to_dev(chan), "%s: state: %lx\n", __func__, chan->state);694694+695695+ spin_lock_bh(&chan->cleanup_lock);696696+ if (test_and_clear_bit(IOAT_RESET_PENDING, &chan->state)) {697697+ struct ioat_desc_sw *desc;698698+699699+ spin_lock_bh(&ioat->desc_lock);700700+701701+ /* restart active descriptors */702702+ desc = to_ioat_desc(ioat->used_desc.prev);703703+ ioat_set_chainaddr(ioat, desc->txd.phys);704704+ ioat_start(chan);705705+706706+ ioat->pending = 0;707707+ set_bit(IOAT_COMPLETION_PENDING, &chan->state);708708+ mod_timer(&chan->timer, jiffies + COMPLETION_TIMEOUT);709709+ spin_unlock_bh(&ioat->desc_lock);710710+ } else if (test_bit(IOAT_COMPLETION_PENDING, &chan->state)) {711711+ unsigned long phys_complete;712712+713713+ spin_lock_bh(&ioat->desc_lock);714714+ /* if we haven't made progress and we have already715715+ * acknowledged a pending completion once, then be more716716+ * forceful with a restart717717+ */718718+ if (ioat_cleanup_preamble(chan, &phys_complete))719719+ __cleanup(ioat, phys_complete);720720+ else if (test_bit(IOAT_COMPLETION_ACK, &chan->state))721721+ ioat1_reset_channel(ioat);722722+ else {723723+ u64 status = ioat_chansts(chan);724724+725725+ /* manually update the last completion address */726726+ if (ioat_chansts_to_addr(status) != 0)727727+ *chan->completion = status;728728+729729+ set_bit(IOAT_COMPLETION_ACK, &chan->state);730730+ mod_timer(&chan->timer, jiffies + COMPLETION_TIMEOUT);731731+ }732732+ spin_unlock_bh(&ioat->desc_lock);733733+ }734734+ spin_unlock_bh(&chan->cleanup_lock);735735+}736736+737737+static enum dma_status738738+ioat1_dma_is_complete(struct dma_chan *c, dma_cookie_t cookie,739739+ dma_cookie_t *done, dma_cookie_t *used)740740+{741741+ struct ioat_dma_chan *ioat = to_ioat_chan(c);742742+743743+ if (ioat_is_complete(c, cookie, done, used) == DMA_SUCCESS)744744+ return DMA_SUCCESS;745745+746746+ ioat1_cleanup(ioat);747747+748748+ return ioat_is_complete(c, cookie, done, used);749749+}750750+751751+static void ioat1_dma_start_null_desc(struct ioat_dma_chan *ioat)752752+{753753+ struct ioat_chan_common *chan = &ioat->base;754754+ struct ioat_desc_sw *desc;755755+ struct ioat_dma_descriptor *hw;756756+757757+ spin_lock_bh(&ioat->desc_lock);758758+759759+ desc = ioat1_dma_get_next_descriptor(ioat);760760+761761+ if (!desc) {762762+ dev_err(to_dev(chan),763763+ "Unable to start null desc - get next desc failed\n");764764+ spin_unlock_bh(&ioat->desc_lock);765765+ return;766766+ }767767+768768+ hw = desc->hw;769769+ hw->ctl = 0;770770+ hw->ctl_f.null = 1;771771+ hw->ctl_f.int_en = 1;772772+ hw->ctl_f.compl_write = 1;773773+ /* set size to non-zero value (channel returns error when size is 0) */774774+ hw->size = NULL_DESC_BUFFER_SIZE;775775+ hw->src_addr = 0;776776+ hw->dst_addr = 0;777777+ async_tx_ack(&desc->txd);778778+ hw->next = 0;779779+ list_add_tail(&desc->node, &ioat->used_desc);780780+ dump_desc_dbg(ioat, desc);781781+782782+ ioat_set_chainaddr(ioat, desc->txd.phys);783783+ ioat_start(chan);784784+ spin_unlock_bh(&ioat->desc_lock);785785+}786786+787787+/*788788+ * Perform a IOAT transaction to verify the HW works.789789+ */790790+#define IOAT_TEST_SIZE 2000791791+792792+static void __devinit ioat_dma_test_callback(void *dma_async_param)793793+{794794+ struct completion *cmp = dma_async_param;795795+796796+ complete(cmp);797797+}798798+799799+/**800800+ * ioat_dma_self_test - Perform a IOAT transaction to verify the HW works.801801+ * @device: device to be tested802802+ */803803+int __devinit ioat_dma_self_test(struct ioatdma_device *device)804804+{805805+ int i;806806+ u8 *src;807807+ u8 *dest;808808+ struct dma_device *dma = &device->common;809809+ struct device *dev = &device->pdev->dev;810810+ struct dma_chan *dma_chan;811811+ struct dma_async_tx_descriptor *tx;812812+ dma_addr_t dma_dest, dma_src;813813+ dma_cookie_t cookie;814814+ int err = 0;815815+ struct completion cmp;816816+ unsigned long tmo;817817+ unsigned long flags;818818+819819+ src = kzalloc(sizeof(u8) * IOAT_TEST_SIZE, GFP_KERNEL);820820+ if (!src)821821+ return -ENOMEM;822822+ dest = kzalloc(sizeof(u8) * IOAT_TEST_SIZE, GFP_KERNEL);823823+ if (!dest) {824824+ kfree(src);825825+ return -ENOMEM;826826+ }827827+828828+ /* Fill in src buffer */829829+ for (i = 0; i < IOAT_TEST_SIZE; i++)830830+ src[i] = (u8)i;831831+832832+ /* Start copy, using first DMA channel */833833+ dma_chan = container_of(dma->channels.next, struct dma_chan,834834+ device_node);835835+ if (dma->device_alloc_chan_resources(dma_chan) < 1) {836836+ dev_err(dev, "selftest cannot allocate chan resource\n");837837+ err = -ENODEV;838838+ goto out;839839+ }840840+841841+ dma_src = dma_map_single(dev, src, IOAT_TEST_SIZE, DMA_TO_DEVICE);842842+ dma_dest = dma_map_single(dev, dest, IOAT_TEST_SIZE, DMA_FROM_DEVICE);843843+ flags = DMA_COMPL_SRC_UNMAP_SINGLE | DMA_COMPL_DEST_UNMAP_SINGLE |844844+ DMA_PREP_INTERRUPT;845845+ tx = device->common.device_prep_dma_memcpy(dma_chan, dma_dest, dma_src,846846+ IOAT_TEST_SIZE, flags);847847+ if (!tx) {848848+ dev_err(dev, "Self-test prep failed, disabling\n");849849+ err = -ENODEV;850850+ goto free_resources;851851+ }852852+853853+ async_tx_ack(tx);854854+ init_completion(&cmp);855855+ tx->callback = ioat_dma_test_callback;856856+ tx->callback_param = &cmp;857857+ cookie = tx->tx_submit(tx);858858+ if (cookie < 0) {859859+ dev_err(dev, "Self-test setup failed, disabling\n");860860+ err = -ENODEV;861861+ goto free_resources;862862+ }863863+ dma->device_issue_pending(dma_chan);864864+865865+ tmo = wait_for_completion_timeout(&cmp, msecs_to_jiffies(3000));866866+867867+ if (tmo == 0 ||868868+ dma->device_is_tx_complete(dma_chan, cookie, NULL, NULL)869869+ != DMA_SUCCESS) {870870+ dev_err(dev, "Self-test copy timed out, disabling\n");871871+ err = -ENODEV;872872+ goto free_resources;873873+ }874874+ if (memcmp(src, dest, IOAT_TEST_SIZE)) {875875+ dev_err(dev, "Self-test copy failed compare, disabling\n");876876+ err = -ENODEV;877877+ goto free_resources;878878+ }879879+880880+free_resources:881881+ dma->device_free_chan_resources(dma_chan);882882+out:883883+ kfree(src);884884+ kfree(dest);885885+ return err;886886+}887887+888888+static char ioat_interrupt_style[32] = "msix";889889+module_param_string(ioat_interrupt_style, ioat_interrupt_style,890890+ sizeof(ioat_interrupt_style), 0644);891891+MODULE_PARM_DESC(ioat_interrupt_style,892892+ "set ioat interrupt style: msix (default), "893893+ "msix-single-vector, msi, intx)");894894+895895+/**896896+ * ioat_dma_setup_interrupts - setup interrupt handler897897+ * @device: ioat device898898+ */899899+static int ioat_dma_setup_interrupts(struct ioatdma_device *device)900900+{901901+ struct ioat_chan_common *chan;902902+ struct pci_dev *pdev = device->pdev;903903+ struct device *dev = &pdev->dev;904904+ struct msix_entry *msix;905905+ int i, j, msixcnt;906906+ int err = -EINVAL;907907+ u8 intrctrl = 0;908908+909909+ if (!strcmp(ioat_interrupt_style, "msix"))910910+ goto msix;911911+ if (!strcmp(ioat_interrupt_style, "msix-single-vector"))912912+ goto msix_single_vector;913913+ if (!strcmp(ioat_interrupt_style, "msi"))914914+ goto msi;915915+ if (!strcmp(ioat_interrupt_style, "intx"))916916+ goto intx;917917+ dev_err(dev, "invalid ioat_interrupt_style %s\n", ioat_interrupt_style);918918+ goto err_no_irq;919919+920920+msix:921921+ /* The number of MSI-X vectors should equal the number of channels */922922+ msixcnt = device->common.chancnt;923923+ for (i = 0; i < msixcnt; i++)924924+ device->msix_entries[i].entry = i;925925+926926+ err = pci_enable_msix(pdev, device->msix_entries, msixcnt);927927+ if (err < 0)928928+ goto msi;929929+ if (err > 0)930930+ goto msix_single_vector;931931+932932+ for (i = 0; i < msixcnt; i++) {933933+ msix = &device->msix_entries[i];934934+ chan = ioat_chan_by_index(device, i);935935+ err = devm_request_irq(dev, msix->vector,936936+ ioat_dma_do_interrupt_msix, 0,937937+ "ioat-msix", chan);938938+ if (err) {939939+ for (j = 0; j < i; j++) {940940+ msix = &device->msix_entries[j];941941+ chan = ioat_chan_by_index(device, j);942942+ devm_free_irq(dev, msix->vector, chan);943943+ }944944+ goto msix_single_vector;945945+ }946946+ }947947+ intrctrl |= IOAT_INTRCTRL_MSIX_VECTOR_CONTROL;948948+ goto done;949949+950950+msix_single_vector:951951+ msix = &device->msix_entries[0];952952+ msix->entry = 0;953953+ err = pci_enable_msix(pdev, device->msix_entries, 1);954954+ if (err)955955+ goto msi;956956+957957+ err = devm_request_irq(dev, msix->vector, ioat_dma_do_interrupt, 0,958958+ "ioat-msix", device);959959+ if (err) {960960+ pci_disable_msix(pdev);961961+ goto msi;962962+ }963963+ goto done;964964+965965+msi:966966+ err = pci_enable_msi(pdev);967967+ if (err)968968+ goto intx;969969+970970+ err = devm_request_irq(dev, pdev->irq, ioat_dma_do_interrupt, 0,971971+ "ioat-msi", device);972972+ if (err) {973973+ pci_disable_msi(pdev);974974+ goto intx;975975+ }976976+ goto done;977977+978978+intx:979979+ err = devm_request_irq(dev, pdev->irq, ioat_dma_do_interrupt,980980+ IRQF_SHARED, "ioat-intx", device);981981+ if (err)982982+ goto err_no_irq;983983+984984+done:985985+ if (device->intr_quirk)986986+ device->intr_quirk(device);987987+ intrctrl |= IOAT_INTRCTRL_MASTER_INT_EN;988988+ writeb(intrctrl, device->reg_base + IOAT_INTRCTRL_OFFSET);989989+ return 0;990990+991991+err_no_irq:992992+ /* Disable all interrupt generation */993993+ writeb(0, device->reg_base + IOAT_INTRCTRL_OFFSET);994994+ dev_err(dev, "no usable interrupts\n");995995+ return err;996996+}997997+998998+static void ioat_disable_interrupts(struct ioatdma_device *device)999999+{10001000+ /* Disable all interrupt generation */10011001+ writeb(0, device->reg_base + IOAT_INTRCTRL_OFFSET);10021002+}10031003+10041004+int __devinit ioat_probe(struct ioatdma_device *device)10051005+{10061006+ int err = -ENODEV;10071007+ struct dma_device *dma = &device->common;10081008+ struct pci_dev *pdev = device->pdev;10091009+ struct device *dev = &pdev->dev;10101010+10111011+ /* DMA coherent memory pool for DMA descriptor allocations */10121012+ device->dma_pool = pci_pool_create("dma_desc_pool", pdev,10131013+ sizeof(struct ioat_dma_descriptor),10141014+ 64, 0);10151015+ if (!device->dma_pool) {10161016+ err = -ENOMEM;10171017+ goto err_dma_pool;10181018+ }10191019+10201020+ device->completion_pool = pci_pool_create("completion_pool", pdev,10211021+ sizeof(u64), SMP_CACHE_BYTES,10221022+ SMP_CACHE_BYTES);10231023+10241024+ if (!device->completion_pool) {10251025+ err = -ENOMEM;10261026+ goto err_completion_pool;10271027+ }10281028+10291029+ device->enumerate_channels(device);10301030+10311031+ dma_cap_set(DMA_MEMCPY, dma->cap_mask);10321032+ dma->dev = &pdev->dev;10331033+10341034+ if (!dma->chancnt) {10351035+ dev_err(dev, "zero channels detected\n");10361036+ goto err_setup_interrupts;10371037+ }10381038+10391039+ err = ioat_dma_setup_interrupts(device);10401040+ if (err)10411041+ goto err_setup_interrupts;10421042+10431043+ err = device->self_test(device);10441044+ if (err)10451045+ goto err_self_test;10461046+10471047+ return 0;10481048+10491049+err_self_test:10501050+ ioat_disable_interrupts(device);10511051+err_setup_interrupts:10521052+ pci_pool_destroy(device->completion_pool);10531053+err_completion_pool:10541054+ pci_pool_destroy(device->dma_pool);10551055+err_dma_pool:10561056+ return err;10571057+}10581058+10591059+int __devinit ioat_register(struct ioatdma_device *device)10601060+{10611061+ int err = dma_async_device_register(&device->common);10621062+10631063+ if (err) {10641064+ ioat_disable_interrupts(device);10651065+ pci_pool_destroy(device->completion_pool);10661066+ pci_pool_destroy(device->dma_pool);10671067+ }10681068+10691069+ return err;10701070+}10711071+10721072+/* ioat1_intr_quirk - fix up dma ctrl register to enable / disable msi */10731073+static void ioat1_intr_quirk(struct ioatdma_device *device)10741074+{10751075+ struct pci_dev *pdev = device->pdev;10761076+ u32 dmactrl;10771077+10781078+ pci_read_config_dword(pdev, IOAT_PCI_DMACTRL_OFFSET, &dmactrl);10791079+ if (pdev->msi_enabled)10801080+ dmactrl |= IOAT_PCI_DMACTRL_MSI_EN;10811081+ else10821082+ dmactrl &= ~IOAT_PCI_DMACTRL_MSI_EN;10831083+ pci_write_config_dword(pdev, IOAT_PCI_DMACTRL_OFFSET, dmactrl);10841084+}10851085+10861086+static ssize_t ring_size_show(struct dma_chan *c, char *page)10871087+{10881088+ struct ioat_dma_chan *ioat = to_ioat_chan(c);10891089+10901090+ return sprintf(page, "%d\n", ioat->desccount);10911091+}10921092+static struct ioat_sysfs_entry ring_size_attr = __ATTR_RO(ring_size);10931093+10941094+static ssize_t ring_active_show(struct dma_chan *c, char *page)10951095+{10961096+ struct ioat_dma_chan *ioat = to_ioat_chan(c);10971097+10981098+ return sprintf(page, "%d\n", ioat->active);10991099+}11001100+static struct ioat_sysfs_entry ring_active_attr = __ATTR_RO(ring_active);11011101+11021102+static ssize_t cap_show(struct dma_chan *c, char *page)11031103+{11041104+ struct dma_device *dma = c->device;11051105+11061106+ return sprintf(page, "copy%s%s%s%s%s%s\n",11071107+ dma_has_cap(DMA_PQ, dma->cap_mask) ? " pq" : "",11081108+ dma_has_cap(DMA_PQ_VAL, dma->cap_mask) ? " pq_val" : "",11091109+ dma_has_cap(DMA_XOR, dma->cap_mask) ? " xor" : "",11101110+ dma_has_cap(DMA_XOR_VAL, dma->cap_mask) ? " xor_val" : "",11111111+ dma_has_cap(DMA_MEMSET, dma->cap_mask) ? " fill" : "",11121112+ dma_has_cap(DMA_INTERRUPT, dma->cap_mask) ? " intr" : "");11131113+11141114+}11151115+struct ioat_sysfs_entry ioat_cap_attr = __ATTR_RO(cap);11161116+11171117+static ssize_t version_show(struct dma_chan *c, char *page)11181118+{11191119+ struct dma_device *dma = c->device;11201120+ struct ioatdma_device *device = to_ioatdma_device(dma);11211121+11221122+ return sprintf(page, "%d.%d\n",11231123+ device->version >> 4, device->version & 0xf);11241124+}11251125+struct ioat_sysfs_entry ioat_version_attr = __ATTR_RO(version);11261126+11271127+static struct attribute *ioat1_attrs[] = {11281128+ &ring_size_attr.attr,11291129+ &ring_active_attr.attr,11301130+ &ioat_cap_attr.attr,11311131+ &ioat_version_attr.attr,11321132+ NULL,11331133+};11341134+11351135+static ssize_t11361136+ioat_attr_show(struct kobject *kobj, struct attribute *attr, char *page)11371137+{11381138+ struct ioat_sysfs_entry *entry;11391139+ struct ioat_chan_common *chan;11401140+11411141+ entry = container_of(attr, struct ioat_sysfs_entry, attr);11421142+ chan = container_of(kobj, struct ioat_chan_common, kobj);11431143+11441144+ if (!entry->show)11451145+ return -EIO;11461146+ return entry->show(&chan->common, page);11471147+}11481148+11491149+struct sysfs_ops ioat_sysfs_ops = {11501150+ .show = ioat_attr_show,11511151+};11521152+11531153+static struct kobj_type ioat1_ktype = {11541154+ .sysfs_ops = &ioat_sysfs_ops,11551155+ .default_attrs = ioat1_attrs,11561156+};11571157+11581158+void ioat_kobject_add(struct ioatdma_device *device, struct kobj_type *type)11591159+{11601160+ struct dma_device *dma = &device->common;11611161+ struct dma_chan *c;11621162+11631163+ list_for_each_entry(c, &dma->channels, device_node) {11641164+ struct ioat_chan_common *chan = to_chan_common(c);11651165+ struct kobject *parent = &c->dev->device.kobj;11661166+ int err;11671167+11681168+ err = kobject_init_and_add(&chan->kobj, type, parent, "quickdata");11691169+ if (err) {11701170+ dev_warn(to_dev(chan),11711171+ "sysfs init error (%d), continuing...\n", err);11721172+ kobject_put(&chan->kobj);11731173+ set_bit(IOAT_KOBJ_INIT_FAIL, &chan->state);11741174+ }11751175+ }11761176+}11771177+11781178+void ioat_kobject_del(struct ioatdma_device *device)11791179+{11801180+ struct dma_device *dma = &device->common;11811181+ struct dma_chan *c;11821182+11831183+ list_for_each_entry(c, &dma->channels, device_node) {11841184+ struct ioat_chan_common *chan = to_chan_common(c);11851185+11861186+ if (!test_bit(IOAT_KOBJ_INIT_FAIL, &chan->state)) {11871187+ kobject_del(&chan->kobj);11881188+ kobject_put(&chan->kobj);11891189+ }11901190+ }11911191+}11921192+11931193+int __devinit ioat1_dma_probe(struct ioatdma_device *device, int dca)11941194+{11951195+ struct pci_dev *pdev = device->pdev;11961196+ struct dma_device *dma;11971197+ int err;11981198+11991199+ device->intr_quirk = ioat1_intr_quirk;12001200+ device->enumerate_channels = ioat1_enumerate_channels;12011201+ device->self_test = ioat_dma_self_test;12021202+ dma = &device->common;12031203+ dma->device_prep_dma_memcpy = ioat1_dma_prep_memcpy;12041204+ dma->device_issue_pending = ioat1_dma_memcpy_issue_pending;12051205+ dma->device_alloc_chan_resources = ioat1_dma_alloc_chan_resources;12061206+ dma->device_free_chan_resources = ioat1_dma_free_chan_resources;12071207+ dma->device_is_tx_complete = ioat1_dma_is_complete;12081208+12091209+ err = ioat_probe(device);12101210+ if (err)12111211+ return err;12121212+ ioat_set_tcp_copy_break(4096);12131213+ err = ioat_register(device);12141214+ if (err)12151215+ return err;12161216+ ioat_kobject_add(device, &ioat1_ktype);12171217+12181218+ if (dca)12191219+ device->dca = ioat_dca_init(pdev, device->reg_base);12201220+12211221+ return err;12221222+}12231223+12241224+void __devexit ioat_dma_remove(struct ioatdma_device *device)12251225+{12261226+ struct dma_device *dma = &device->common;12271227+12281228+ ioat_disable_interrupts(device);12291229+12301230+ ioat_kobject_del(device);12311231+12321232+ dma_async_device_unregister(dma);12331233+12341234+ pci_pool_destroy(device->dma_pool);12351235+ pci_pool_destroy(device->completion_pool);12361236+12371237+ INIT_LIST_HEAD(&dma->channels);12381238+}
+337
drivers/dma/ioat/dma.h
···11+/*22+ * Copyright(c) 2004 - 2009 Intel Corporation. All rights reserved.33+ *44+ * This program is free software; you can redistribute it and/or modify it55+ * under the terms of the GNU General Public License as published by the Free66+ * Software Foundation; either version 2 of the License, or (at your option)77+ * any later version.88+ *99+ * This program is distributed in the hope that it will be useful, but WITHOUT1010+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or1111+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for1212+ * more details.1313+ *1414+ * You should have received a copy of the GNU General Public License along with1515+ * this program; if not, write to the Free Software Foundation, Inc., 591616+ * Temple Place - Suite 330, Boston, MA 02111-1307, USA.1717+ *1818+ * The full GNU General Public License is included in this distribution in the1919+ * file called COPYING.2020+ */2121+#ifndef IOATDMA_H2222+#define IOATDMA_H2323+2424+#include <linux/dmaengine.h>2525+#include "hw.h"2626+#include "registers.h"2727+#include <linux/init.h>2828+#include <linux/dmapool.h>2929+#include <linux/cache.h>3030+#include <linux/pci_ids.h>3131+#include <net/tcp.h>3232+3333+#define IOAT_DMA_VERSION "4.00"3434+3535+#define IOAT_LOW_COMPLETION_MASK 0xffffffc03636+#define IOAT_DMA_DCA_ANY_CPU ~03737+3838+#define to_ioatdma_device(dev) container_of(dev, struct ioatdma_device, common)3939+#define to_ioat_desc(lh) container_of(lh, struct ioat_desc_sw, node)4040+#define tx_to_ioat_desc(tx) container_of(tx, struct ioat_desc_sw, txd)4141+#define to_dev(ioat_chan) (&(ioat_chan)->device->pdev->dev)4242+4343+#define chan_num(ch) ((int)((ch)->reg_base - (ch)->device->reg_base) / 0x80)4444+4545+/*4646+ * workaround for IOAT ver.3.0 null descriptor issue4747+ * (channel returns error when size is 0)4848+ */4949+#define NULL_DESC_BUFFER_SIZE 15050+5151+/**5252+ * struct ioatdma_device - internal representation of a IOAT device5353+ * @pdev: PCI-Express device5454+ * @reg_base: MMIO register space base address5555+ * @dma_pool: for allocating DMA descriptors5656+ * @common: embedded struct dma_device5757+ * @version: version of ioatdma device5858+ * @msix_entries: irq handlers5959+ * @idx: per channel data6060+ * @dca: direct cache access context6161+ * @intr_quirk: interrupt setup quirk (for ioat_v1 devices)6262+ * @enumerate_channels: hw version specific channel enumeration6363+ * @cleanup_tasklet: select between the v2 and v3 cleanup routines6464+ * @timer_fn: select between the v2 and v3 timer watchdog routines6565+ * @self_test: hardware version specific self test for each supported op type6666+ *6767+ * Note: the v3 cleanup routine supports raid operations6868+ */6969+struct ioatdma_device {7070+ struct pci_dev *pdev;7171+ void __iomem *reg_base;7272+ struct pci_pool *dma_pool;7373+ struct pci_pool *completion_pool;7474+ struct dma_device common;7575+ u8 version;7676+ struct msix_entry msix_entries[4];7777+ struct ioat_chan_common *idx[4];7878+ struct dca_provider *dca;7979+ void (*intr_quirk)(struct ioatdma_device *device);8080+ int (*enumerate_channels)(struct ioatdma_device *device);8181+ void (*cleanup_tasklet)(unsigned long data);8282+ void (*timer_fn)(unsigned long data);8383+ int (*self_test)(struct ioatdma_device *device);8484+};8585+8686+struct ioat_chan_common {8787+ struct dma_chan common;8888+ void __iomem *reg_base;8989+ unsigned long last_completion;9090+ spinlock_t cleanup_lock;9191+ dma_cookie_t completed_cookie;9292+ unsigned long state;9393+ #define IOAT_COMPLETION_PENDING 09494+ #define IOAT_COMPLETION_ACK 19595+ #define IOAT_RESET_PENDING 29696+ #define IOAT_KOBJ_INIT_FAIL 39797+ struct timer_list timer;9898+ #define COMPLETION_TIMEOUT msecs_to_jiffies(100)9999+ #define IDLE_TIMEOUT msecs_to_jiffies(2000)100100+ #define RESET_DELAY msecs_to_jiffies(100)101101+ struct ioatdma_device *device;102102+ dma_addr_t completion_dma;103103+ u64 *completion;104104+ struct tasklet_struct cleanup_task;105105+ struct kobject kobj;106106+};107107+108108+struct ioat_sysfs_entry {109109+ struct attribute attr;110110+ ssize_t (*show)(struct dma_chan *, char *);111111+};112112+113113+/**114114+ * struct ioat_dma_chan - internal representation of a DMA channel115115+ */116116+struct ioat_dma_chan {117117+ struct ioat_chan_common base;118118+119119+ size_t xfercap; /* XFERCAP register value expanded out */120120+121121+ spinlock_t desc_lock;122122+ struct list_head free_desc;123123+ struct list_head used_desc;124124+125125+ int pending;126126+ u16 desccount;127127+ u16 active;128128+};129129+130130+static inline struct ioat_chan_common *to_chan_common(struct dma_chan *c)131131+{132132+ return container_of(c, struct ioat_chan_common, common);133133+}134134+135135+static inline struct ioat_dma_chan *to_ioat_chan(struct dma_chan *c)136136+{137137+ struct ioat_chan_common *chan = to_chan_common(c);138138+139139+ return container_of(chan, struct ioat_dma_chan, base);140140+}141141+142142+/**143143+ * ioat_is_complete - poll the status of an ioat transaction144144+ * @c: channel handle145145+ * @cookie: transaction identifier146146+ * @done: if set, updated with last completed transaction147147+ * @used: if set, updated with last used transaction148148+ */149149+static inline enum dma_status150150+ioat_is_complete(struct dma_chan *c, dma_cookie_t cookie,151151+ dma_cookie_t *done, dma_cookie_t *used)152152+{153153+ struct ioat_chan_common *chan = to_chan_common(c);154154+ dma_cookie_t last_used;155155+ dma_cookie_t last_complete;156156+157157+ last_used = c->cookie;158158+ last_complete = chan->completed_cookie;159159+160160+ if (done)161161+ *done = last_complete;162162+ if (used)163163+ *used = last_used;164164+165165+ return dma_async_is_complete(cookie, last_complete, last_used);166166+}167167+168168+/* wrapper around hardware descriptor format + additional software fields */169169+170170+/**171171+ * struct ioat_desc_sw - wrapper around hardware descriptor172172+ * @hw: hardware DMA descriptor (for memcpy)173173+ * @node: this descriptor will either be on the free list,174174+ * or attached to a transaction list (tx_list)175175+ * @txd: the generic software descriptor for all engines176176+ * @id: identifier for debug177177+ */178178+struct ioat_desc_sw {179179+ struct ioat_dma_descriptor *hw;180180+ struct list_head node;181181+ size_t len;182182+ struct list_head tx_list;183183+ struct dma_async_tx_descriptor txd;184184+ #ifdef DEBUG185185+ int id;186186+ #endif187187+};188188+189189+#ifdef DEBUG190190+#define set_desc_id(desc, i) ((desc)->id = (i))191191+#define desc_id(desc) ((desc)->id)192192+#else193193+#define set_desc_id(desc, i)194194+#define desc_id(desc) (0)195195+#endif196196+197197+static inline void198198+__dump_desc_dbg(struct ioat_chan_common *chan, struct ioat_dma_descriptor *hw,199199+ struct dma_async_tx_descriptor *tx, int id)200200+{201201+ struct device *dev = to_dev(chan);202202+203203+ dev_dbg(dev, "desc[%d]: (%#llx->%#llx) cookie: %d flags: %#x"204204+ " ctl: %#x (op: %d int_en: %d compl: %d)\n", id,205205+ (unsigned long long) tx->phys,206206+ (unsigned long long) hw->next, tx->cookie, tx->flags,207207+ hw->ctl, hw->ctl_f.op, hw->ctl_f.int_en, hw->ctl_f.compl_write);208208+}209209+210210+#define dump_desc_dbg(c, d) \211211+ ({ if (d) __dump_desc_dbg(&c->base, d->hw, &d->txd, desc_id(d)); 0; })212212+213213+static inline void ioat_set_tcp_copy_break(unsigned long copybreak)214214+{215215+ #ifdef CONFIG_NET_DMA216216+ sysctl_tcp_dma_copybreak = copybreak;217217+ #endif218218+}219219+220220+static inline struct ioat_chan_common *221221+ioat_chan_by_index(struct ioatdma_device *device, int index)222222+{223223+ return device->idx[index];224224+}225225+226226+static inline u64 ioat_chansts(struct ioat_chan_common *chan)227227+{228228+ u8 ver = chan->device->version;229229+ u64 status;230230+ u32 status_lo;231231+232232+ /* We need to read the low address first as this causes the233233+ * chipset to latch the upper bits for the subsequent read234234+ */235235+ status_lo = readl(chan->reg_base + IOAT_CHANSTS_OFFSET_LOW(ver));236236+ status = readl(chan->reg_base + IOAT_CHANSTS_OFFSET_HIGH(ver));237237+ status <<= 32;238238+ status |= status_lo;239239+240240+ return status;241241+}242242+243243+static inline void ioat_start(struct ioat_chan_common *chan)244244+{245245+ u8 ver = chan->device->version;246246+247247+ writeb(IOAT_CHANCMD_START, chan->reg_base + IOAT_CHANCMD_OFFSET(ver));248248+}249249+250250+static inline u64 ioat_chansts_to_addr(u64 status)251251+{252252+ return status & IOAT_CHANSTS_COMPLETED_DESCRIPTOR_ADDR;253253+}254254+255255+static inline u32 ioat_chanerr(struct ioat_chan_common *chan)256256+{257257+ return readl(chan->reg_base + IOAT_CHANERR_OFFSET);258258+}259259+260260+static inline void ioat_suspend(struct ioat_chan_common *chan)261261+{262262+ u8 ver = chan->device->version;263263+264264+ writeb(IOAT_CHANCMD_SUSPEND, chan->reg_base + IOAT_CHANCMD_OFFSET(ver));265265+}266266+267267+static inline void ioat_set_chainaddr(struct ioat_dma_chan *ioat, u64 addr)268268+{269269+ struct ioat_chan_common *chan = &ioat->base;270270+271271+ writel(addr & 0x00000000FFFFFFFF,272272+ chan->reg_base + IOAT1_CHAINADDR_OFFSET_LOW);273273+ writel(addr >> 32,274274+ chan->reg_base + IOAT1_CHAINADDR_OFFSET_HIGH);275275+}276276+277277+static inline bool is_ioat_active(unsigned long status)278278+{279279+ return ((status & IOAT_CHANSTS_STATUS) == IOAT_CHANSTS_ACTIVE);280280+}281281+282282+static inline bool is_ioat_idle(unsigned long status)283283+{284284+ return ((status & IOAT_CHANSTS_STATUS) == IOAT_CHANSTS_DONE);285285+}286286+287287+static inline bool is_ioat_halted(unsigned long status)288288+{289289+ return ((status & IOAT_CHANSTS_STATUS) == IOAT_CHANSTS_HALTED);290290+}291291+292292+static inline bool is_ioat_suspended(unsigned long status)293293+{294294+ return ((status & IOAT_CHANSTS_STATUS) == IOAT_CHANSTS_SUSPENDED);295295+}296296+297297+/* channel was fatally programmed */298298+static inline bool is_ioat_bug(unsigned long err)299299+{300300+ return !!(err & (IOAT_CHANERR_SRC_ADDR_ERR|IOAT_CHANERR_DEST_ADDR_ERR|301301+ IOAT_CHANERR_NEXT_ADDR_ERR|IOAT_CHANERR_CONTROL_ERR|302302+ IOAT_CHANERR_LENGTH_ERR));303303+}304304+305305+static inline void ioat_unmap(struct pci_dev *pdev, dma_addr_t addr, size_t len,306306+ int direction, enum dma_ctrl_flags flags, bool dst)307307+{308308+ if ((dst && (flags & DMA_COMPL_DEST_UNMAP_SINGLE)) ||309309+ (!dst && (flags & DMA_COMPL_SRC_UNMAP_SINGLE)))310310+ pci_unmap_single(pdev, addr, len, direction);311311+ else312312+ pci_unmap_page(pdev, addr, len, direction);313313+}314314+315315+int __devinit ioat_probe(struct ioatdma_device *device);316316+int __devinit ioat_register(struct ioatdma_device *device);317317+int __devinit ioat1_dma_probe(struct ioatdma_device *dev, int dca);318318+int __devinit ioat_dma_self_test(struct ioatdma_device *device);319319+void __devexit ioat_dma_remove(struct ioatdma_device *device);320320+struct dca_provider * __devinit ioat_dca_init(struct pci_dev *pdev,321321+ void __iomem *iobase);322322+unsigned long ioat_get_current_completion(struct ioat_chan_common *chan);323323+void ioat_init_channel(struct ioatdma_device *device,324324+ struct ioat_chan_common *chan, int idx,325325+ void (*timer_fn)(unsigned long),326326+ void (*tasklet)(unsigned long),327327+ unsigned long ioat);328328+void ioat_dma_unmap(struct ioat_chan_common *chan, enum dma_ctrl_flags flags,329329+ size_t len, struct ioat_dma_descriptor *hw);330330+bool ioat_cleanup_preamble(struct ioat_chan_common *chan,331331+ unsigned long *phys_complete);332332+void ioat_kobject_add(struct ioatdma_device *device, struct kobj_type *type);333333+void ioat_kobject_del(struct ioatdma_device *device);334334+extern struct sysfs_ops ioat_sysfs_ops;335335+extern struct ioat_sysfs_entry ioat_version_attr;336336+extern struct ioat_sysfs_entry ioat_cap_attr;337337+#endif /* IOATDMA_H */
+871
drivers/dma/ioat/dma_v2.c
···11+/*22+ * Intel I/OAT DMA Linux driver33+ * Copyright(c) 2004 - 2009 Intel Corporation.44+ *55+ * This program is free software; you can redistribute it and/or modify it66+ * under the terms and conditions of the GNU General Public License,77+ * version 2, as published by the Free Software Foundation.88+ *99+ * This program is distributed in the hope that it will be useful, but WITHOUT1010+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or1111+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for1212+ * more details.1313+ *1414+ * You should have received a copy of the GNU General Public License along with1515+ * this program; if not, write to the Free Software Foundation, Inc.,1616+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.1717+ *1818+ * The full GNU General Public License is included in this distribution in1919+ * the file called "COPYING".2020+ *2121+ */2222+2323+/*2424+ * This driver supports an Intel I/OAT DMA engine (versions >= 2), which2525+ * does asynchronous data movement and checksumming operations.2626+ */2727+2828+#include <linux/init.h>2929+#include <linux/module.h>3030+#include <linux/pci.h>3131+#include <linux/interrupt.h>3232+#include <linux/dmaengine.h>3333+#include <linux/delay.h>3434+#include <linux/dma-mapping.h>3535+#include <linux/workqueue.h>3636+#include <linux/i7300_idle.h>3737+#include "dma.h"3838+#include "dma_v2.h"3939+#include "registers.h"4040+#include "hw.h"4141+4242+int ioat_ring_alloc_order = 8;4343+module_param(ioat_ring_alloc_order, int, 0644);4444+MODULE_PARM_DESC(ioat_ring_alloc_order,4545+ "ioat2+: allocate 2^n descriptors per channel"4646+ " (default: 8 max: 16)");4747+static int ioat_ring_max_alloc_order = IOAT_MAX_ORDER;4848+module_param(ioat_ring_max_alloc_order, int, 0644);4949+MODULE_PARM_DESC(ioat_ring_max_alloc_order,5050+ "ioat2+: upper limit for ring size (default: 16)");5151+5252+void __ioat2_issue_pending(struct ioat2_dma_chan *ioat)5353+{5454+ void * __iomem reg_base = ioat->base.reg_base;5555+5656+ ioat->pending = 0;5757+ ioat->dmacount += ioat2_ring_pending(ioat);5858+ ioat->issued = ioat->head;5959+ /* make descriptor updates globally visible before notifying channel */6060+ wmb();6161+ writew(ioat->dmacount, reg_base + IOAT_CHAN_DMACOUNT_OFFSET);6262+ dev_dbg(to_dev(&ioat->base),6363+ "%s: head: %#x tail: %#x issued: %#x count: %#x\n",6464+ __func__, ioat->head, ioat->tail, ioat->issued, ioat->dmacount);6565+}6666+6767+void ioat2_issue_pending(struct dma_chan *chan)6868+{6969+ struct ioat2_dma_chan *ioat = to_ioat2_chan(chan);7070+7171+ spin_lock_bh(&ioat->ring_lock);7272+ if (ioat->pending == 1)7373+ __ioat2_issue_pending(ioat);7474+ spin_unlock_bh(&ioat->ring_lock);7575+}7676+7777+/**7878+ * ioat2_update_pending - log pending descriptors7979+ * @ioat: ioat2+ channel8080+ *8181+ * set pending to '1' unless pending is already set to '2', pending == 28282+ * indicates that submission is temporarily blocked due to an in-flight8383+ * reset. If we are already above the ioat_pending_level threshold then8484+ * just issue pending.8585+ *8686+ * called with ring_lock held8787+ */8888+static void ioat2_update_pending(struct ioat2_dma_chan *ioat)8989+{9090+ if (unlikely(ioat->pending == 2))9191+ return;9292+ else if (ioat2_ring_pending(ioat) > ioat_pending_level)9393+ __ioat2_issue_pending(ioat);9494+ else9595+ ioat->pending = 1;9696+}9797+9898+static void __ioat2_start_null_desc(struct ioat2_dma_chan *ioat)9999+{100100+ struct ioat_ring_ent *desc;101101+ struct ioat_dma_descriptor *hw;102102+ int idx;103103+104104+ if (ioat2_ring_space(ioat) < 1) {105105+ dev_err(to_dev(&ioat->base),106106+ "Unable to start null desc - ring full\n");107107+ return;108108+ }109109+110110+ dev_dbg(to_dev(&ioat->base), "%s: head: %#x tail: %#x issued: %#x\n",111111+ __func__, ioat->head, ioat->tail, ioat->issued);112112+ idx = ioat2_desc_alloc(ioat, 1);113113+ desc = ioat2_get_ring_ent(ioat, idx);114114+115115+ hw = desc->hw;116116+ hw->ctl = 0;117117+ hw->ctl_f.null = 1;118118+ hw->ctl_f.int_en = 1;119119+ hw->ctl_f.compl_write = 1;120120+ /* set size to non-zero value (channel returns error when size is 0) */121121+ hw->size = NULL_DESC_BUFFER_SIZE;122122+ hw->src_addr = 0;123123+ hw->dst_addr = 0;124124+ async_tx_ack(&desc->txd);125125+ ioat2_set_chainaddr(ioat, desc->txd.phys);126126+ dump_desc_dbg(ioat, desc);127127+ __ioat2_issue_pending(ioat);128128+}129129+130130+static void ioat2_start_null_desc(struct ioat2_dma_chan *ioat)131131+{132132+ spin_lock_bh(&ioat->ring_lock);133133+ __ioat2_start_null_desc(ioat);134134+ spin_unlock_bh(&ioat->ring_lock);135135+}136136+137137+static void __cleanup(struct ioat2_dma_chan *ioat, unsigned long phys_complete)138138+{139139+ struct ioat_chan_common *chan = &ioat->base;140140+ struct dma_async_tx_descriptor *tx;141141+ struct ioat_ring_ent *desc;142142+ bool seen_current = false;143143+ u16 active;144144+ int i;145145+146146+ dev_dbg(to_dev(chan), "%s: head: %#x tail: %#x issued: %#x\n",147147+ __func__, ioat->head, ioat->tail, ioat->issued);148148+149149+ active = ioat2_ring_active(ioat);150150+ for (i = 0; i < active && !seen_current; i++) {151151+ prefetch(ioat2_get_ring_ent(ioat, ioat->tail + i + 1));152152+ desc = ioat2_get_ring_ent(ioat, ioat->tail + i);153153+ tx = &desc->txd;154154+ dump_desc_dbg(ioat, desc);155155+ if (tx->cookie) {156156+ ioat_dma_unmap(chan, tx->flags, desc->len, desc->hw);157157+ chan->completed_cookie = tx->cookie;158158+ tx->cookie = 0;159159+ if (tx->callback) {160160+ tx->callback(tx->callback_param);161161+ tx->callback = NULL;162162+ }163163+ }164164+165165+ if (tx->phys == phys_complete)166166+ seen_current = true;167167+ }168168+ ioat->tail += i;169169+ BUG_ON(!seen_current); /* no active descs have written a completion? */170170+171171+ chan->last_completion = phys_complete;172172+ if (ioat->head == ioat->tail) {173173+ dev_dbg(to_dev(chan), "%s: cancel completion timeout\n",174174+ __func__);175175+ clear_bit(IOAT_COMPLETION_PENDING, &chan->state);176176+ mod_timer(&chan->timer, jiffies + IDLE_TIMEOUT);177177+ }178178+}179179+180180+/**181181+ * ioat2_cleanup - clean finished descriptors (advance tail pointer)182182+ * @chan: ioat channel to be cleaned up183183+ */184184+static void ioat2_cleanup(struct ioat2_dma_chan *ioat)185185+{186186+ struct ioat_chan_common *chan = &ioat->base;187187+ unsigned long phys_complete;188188+189189+ prefetch(chan->completion);190190+191191+ if (!spin_trylock_bh(&chan->cleanup_lock))192192+ return;193193+194194+ if (!ioat_cleanup_preamble(chan, &phys_complete)) {195195+ spin_unlock_bh(&chan->cleanup_lock);196196+ return;197197+ }198198+199199+ if (!spin_trylock_bh(&ioat->ring_lock)) {200200+ spin_unlock_bh(&chan->cleanup_lock);201201+ return;202202+ }203203+204204+ __cleanup(ioat, phys_complete);205205+206206+ spin_unlock_bh(&ioat->ring_lock);207207+ spin_unlock_bh(&chan->cleanup_lock);208208+}209209+210210+void ioat2_cleanup_tasklet(unsigned long data)211211+{212212+ struct ioat2_dma_chan *ioat = (void *) data;213213+214214+ ioat2_cleanup(ioat);215215+ writew(IOAT_CHANCTRL_RUN, ioat->base.reg_base + IOAT_CHANCTRL_OFFSET);216216+}217217+218218+void __ioat2_restart_chan(struct ioat2_dma_chan *ioat)219219+{220220+ struct ioat_chan_common *chan = &ioat->base;221221+222222+ /* set the tail to be re-issued */223223+ ioat->issued = ioat->tail;224224+ ioat->dmacount = 0;225225+ set_bit(IOAT_COMPLETION_PENDING, &chan->state);226226+ mod_timer(&chan->timer, jiffies + COMPLETION_TIMEOUT);227227+228228+ dev_dbg(to_dev(chan),229229+ "%s: head: %#x tail: %#x issued: %#x count: %#x\n",230230+ __func__, ioat->head, ioat->tail, ioat->issued, ioat->dmacount);231231+232232+ if (ioat2_ring_pending(ioat)) {233233+ struct ioat_ring_ent *desc;234234+235235+ desc = ioat2_get_ring_ent(ioat, ioat->tail);236236+ ioat2_set_chainaddr(ioat, desc->txd.phys);237237+ __ioat2_issue_pending(ioat);238238+ } else239239+ __ioat2_start_null_desc(ioat);240240+}241241+242242+static void ioat2_restart_channel(struct ioat2_dma_chan *ioat)243243+{244244+ struct ioat_chan_common *chan = &ioat->base;245245+ unsigned long phys_complete;246246+ u32 status;247247+248248+ status = ioat_chansts(chan);249249+ if (is_ioat_active(status) || is_ioat_idle(status))250250+ ioat_suspend(chan);251251+ while (is_ioat_active(status) || is_ioat_idle(status)) {252252+ status = ioat_chansts(chan);253253+ cpu_relax();254254+ }255255+256256+ if (ioat_cleanup_preamble(chan, &phys_complete))257257+ __cleanup(ioat, phys_complete);258258+259259+ __ioat2_restart_chan(ioat);260260+}261261+262262+void ioat2_timer_event(unsigned long data)263263+{264264+ struct ioat2_dma_chan *ioat = (void *) data;265265+ struct ioat_chan_common *chan = &ioat->base;266266+267267+ spin_lock_bh(&chan->cleanup_lock);268268+ if (test_bit(IOAT_COMPLETION_PENDING, &chan->state)) {269269+ unsigned long phys_complete;270270+ u64 status;271271+272272+ spin_lock_bh(&ioat->ring_lock);273273+ status = ioat_chansts(chan);274274+275275+ /* when halted due to errors check for channel276276+ * programming errors before advancing the completion state277277+ */278278+ if (is_ioat_halted(status)) {279279+ u32 chanerr;280280+281281+ chanerr = readl(chan->reg_base + IOAT_CHANERR_OFFSET);282282+ BUG_ON(is_ioat_bug(chanerr));283283+ }284284+285285+ /* if we haven't made progress and we have already286286+ * acknowledged a pending completion once, then be more287287+ * forceful with a restart288288+ */289289+ if (ioat_cleanup_preamble(chan, &phys_complete))290290+ __cleanup(ioat, phys_complete);291291+ else if (test_bit(IOAT_COMPLETION_ACK, &chan->state))292292+ ioat2_restart_channel(ioat);293293+ else {294294+ set_bit(IOAT_COMPLETION_ACK, &chan->state);295295+ mod_timer(&chan->timer, jiffies + COMPLETION_TIMEOUT);296296+ }297297+ spin_unlock_bh(&ioat->ring_lock);298298+ } else {299299+ u16 active;300300+301301+ /* if the ring is idle, empty, and oversized try to step302302+ * down the size303303+ */304304+ spin_lock_bh(&ioat->ring_lock);305305+ active = ioat2_ring_active(ioat);306306+ if (active == 0 && ioat->alloc_order > ioat_get_alloc_order())307307+ reshape_ring(ioat, ioat->alloc_order-1);308308+ spin_unlock_bh(&ioat->ring_lock);309309+310310+ /* keep shrinking until we get back to our minimum311311+ * default size312312+ */313313+ if (ioat->alloc_order > ioat_get_alloc_order())314314+ mod_timer(&chan->timer, jiffies + IDLE_TIMEOUT);315315+ }316316+ spin_unlock_bh(&chan->cleanup_lock);317317+}318318+319319+/**320320+ * ioat2_enumerate_channels - find and initialize the device's channels321321+ * @device: the device to be enumerated322322+ */323323+int ioat2_enumerate_channels(struct ioatdma_device *device)324324+{325325+ struct ioat2_dma_chan *ioat;326326+ struct device *dev = &device->pdev->dev;327327+ struct dma_device *dma = &device->common;328328+ u8 xfercap_log;329329+ int i;330330+331331+ INIT_LIST_HEAD(&dma->channels);332332+ dma->chancnt = readb(device->reg_base + IOAT_CHANCNT_OFFSET);333333+ dma->chancnt &= 0x1f; /* bits [4:0] valid */334334+ if (dma->chancnt > ARRAY_SIZE(device->idx)) {335335+ dev_warn(dev, "(%d) exceeds max supported channels (%zu)\n",336336+ dma->chancnt, ARRAY_SIZE(device->idx));337337+ dma->chancnt = ARRAY_SIZE(device->idx);338338+ }339339+ xfercap_log = readb(device->reg_base + IOAT_XFERCAP_OFFSET);340340+ xfercap_log &= 0x1f; /* bits [4:0] valid */341341+ if (xfercap_log == 0)342342+ return 0;343343+ dev_dbg(dev, "%s: xfercap = %d\n", __func__, 1 << xfercap_log);344344+345345+ /* FIXME which i/oat version is i7300? */346346+#ifdef CONFIG_I7300_IDLE_IOAT_CHANNEL347347+ if (i7300_idle_platform_probe(NULL, NULL, 1) == 0)348348+ dma->chancnt--;349349+#endif350350+ for (i = 0; i < dma->chancnt; i++) {351351+ ioat = devm_kzalloc(dev, sizeof(*ioat), GFP_KERNEL);352352+ if (!ioat)353353+ break;354354+355355+ ioat_init_channel(device, &ioat->base, i,356356+ device->timer_fn,357357+ device->cleanup_tasklet,358358+ (unsigned long) ioat);359359+ ioat->xfercap_log = xfercap_log;360360+ spin_lock_init(&ioat->ring_lock);361361+ }362362+ dma->chancnt = i;363363+ return i;364364+}365365+366366+static dma_cookie_t ioat2_tx_submit_unlock(struct dma_async_tx_descriptor *tx)367367+{368368+ struct dma_chan *c = tx->chan;369369+ struct ioat2_dma_chan *ioat = to_ioat2_chan(c);370370+ struct ioat_chan_common *chan = &ioat->base;371371+ dma_cookie_t cookie = c->cookie;372372+373373+ cookie++;374374+ if (cookie < 0)375375+ cookie = 1;376376+ tx->cookie = cookie;377377+ c->cookie = cookie;378378+ dev_dbg(to_dev(&ioat->base), "%s: cookie: %d\n", __func__, cookie);379379+380380+ if (!test_and_set_bit(IOAT_COMPLETION_PENDING, &chan->state))381381+ mod_timer(&chan->timer, jiffies + COMPLETION_TIMEOUT);382382+ ioat2_update_pending(ioat);383383+ spin_unlock_bh(&ioat->ring_lock);384384+385385+ return cookie;386386+}387387+388388+static struct ioat_ring_ent *ioat2_alloc_ring_ent(struct dma_chan *chan, gfp_t flags)389389+{390390+ struct ioat_dma_descriptor *hw;391391+ struct ioat_ring_ent *desc;392392+ struct ioatdma_device *dma;393393+ dma_addr_t phys;394394+395395+ dma = to_ioatdma_device(chan->device);396396+ hw = pci_pool_alloc(dma->dma_pool, flags, &phys);397397+ if (!hw)398398+ return NULL;399399+ memset(hw, 0, sizeof(*hw));400400+401401+ desc = kmem_cache_alloc(ioat2_cache, flags);402402+ if (!desc) {403403+ pci_pool_free(dma->dma_pool, hw, phys);404404+ return NULL;405405+ }406406+ memset(desc, 0, sizeof(*desc));407407+408408+ dma_async_tx_descriptor_init(&desc->txd, chan);409409+ desc->txd.tx_submit = ioat2_tx_submit_unlock;410410+ desc->hw = hw;411411+ desc->txd.phys = phys;412412+ return desc;413413+}414414+415415+static void ioat2_free_ring_ent(struct ioat_ring_ent *desc, struct dma_chan *chan)416416+{417417+ struct ioatdma_device *dma;418418+419419+ dma = to_ioatdma_device(chan->device);420420+ pci_pool_free(dma->dma_pool, desc->hw, desc->txd.phys);421421+ kmem_cache_free(ioat2_cache, desc);422422+}423423+424424+static struct ioat_ring_ent **ioat2_alloc_ring(struct dma_chan *c, int order, gfp_t flags)425425+{426426+ struct ioat_ring_ent **ring;427427+ int descs = 1 << order;428428+ int i;429429+430430+ if (order > ioat_get_max_alloc_order())431431+ return NULL;432432+433433+ /* allocate the array to hold the software ring */434434+ ring = kcalloc(descs, sizeof(*ring), flags);435435+ if (!ring)436436+ return NULL;437437+ for (i = 0; i < descs; i++) {438438+ ring[i] = ioat2_alloc_ring_ent(c, flags);439439+ if (!ring[i]) {440440+ while (i--)441441+ ioat2_free_ring_ent(ring[i], c);442442+ kfree(ring);443443+ return NULL;444444+ }445445+ set_desc_id(ring[i], i);446446+ }447447+448448+ /* link descs */449449+ for (i = 0; i < descs-1; i++) {450450+ struct ioat_ring_ent *next = ring[i+1];451451+ struct ioat_dma_descriptor *hw = ring[i]->hw;452452+453453+ hw->next = next->txd.phys;454454+ }455455+ ring[i]->hw->next = ring[0]->txd.phys;456456+457457+ return ring;458458+}459459+460460+/* ioat2_alloc_chan_resources - allocate/initialize ioat2 descriptor ring461461+ * @chan: channel to be initialized462462+ */463463+int ioat2_alloc_chan_resources(struct dma_chan *c)464464+{465465+ struct ioat2_dma_chan *ioat = to_ioat2_chan(c);466466+ struct ioat_chan_common *chan = &ioat->base;467467+ struct ioat_ring_ent **ring;468468+ u32 chanerr;469469+ int order;470470+471471+ /* have we already been set up? */472472+ if (ioat->ring)473473+ return 1 << ioat->alloc_order;474474+475475+ /* Setup register to interrupt and write completion status on error */476476+ writew(IOAT_CHANCTRL_RUN, chan->reg_base + IOAT_CHANCTRL_OFFSET);477477+478478+ chanerr = readl(chan->reg_base + IOAT_CHANERR_OFFSET);479479+ if (chanerr) {480480+ dev_err(to_dev(chan), "CHANERR = %x, clearing\n", chanerr);481481+ writel(chanerr, chan->reg_base + IOAT_CHANERR_OFFSET);482482+ }483483+484484+ /* allocate a completion writeback area */485485+ /* doing 2 32bit writes to mmio since 1 64b write doesn't work */486486+ chan->completion = pci_pool_alloc(chan->device->completion_pool,487487+ GFP_KERNEL, &chan->completion_dma);488488+ if (!chan->completion)489489+ return -ENOMEM;490490+491491+ memset(chan->completion, 0, sizeof(*chan->completion));492492+ writel(((u64) chan->completion_dma) & 0x00000000FFFFFFFF,493493+ chan->reg_base + IOAT_CHANCMP_OFFSET_LOW);494494+ writel(((u64) chan->completion_dma) >> 32,495495+ chan->reg_base + IOAT_CHANCMP_OFFSET_HIGH);496496+497497+ order = ioat_get_alloc_order();498498+ ring = ioat2_alloc_ring(c, order, GFP_KERNEL);499499+ if (!ring)500500+ return -ENOMEM;501501+502502+ spin_lock_bh(&ioat->ring_lock);503503+ ioat->ring = ring;504504+ ioat->head = 0;505505+ ioat->issued = 0;506506+ ioat->tail = 0;507507+ ioat->pending = 0;508508+ ioat->alloc_order = order;509509+ spin_unlock_bh(&ioat->ring_lock);510510+511511+ tasklet_enable(&chan->cleanup_task);512512+ ioat2_start_null_desc(ioat);513513+514514+ return 1 << ioat->alloc_order;515515+}516516+517517+bool reshape_ring(struct ioat2_dma_chan *ioat, int order)518518+{519519+ /* reshape differs from normal ring allocation in that we want520520+ * to allocate a new software ring while only521521+ * extending/truncating the hardware ring522522+ */523523+ struct ioat_chan_common *chan = &ioat->base;524524+ struct dma_chan *c = &chan->common;525525+ const u16 curr_size = ioat2_ring_mask(ioat) + 1;526526+ const u16 active = ioat2_ring_active(ioat);527527+ const u16 new_size = 1 << order;528528+ struct ioat_ring_ent **ring;529529+ u16 i;530530+531531+ if (order > ioat_get_max_alloc_order())532532+ return false;533533+534534+ /* double check that we have at least 1 free descriptor */535535+ if (active == curr_size)536536+ return false;537537+538538+ /* when shrinking, verify that we can hold the current active539539+ * set in the new ring540540+ */541541+ if (active >= new_size)542542+ return false;543543+544544+ /* allocate the array to hold the software ring */545545+ ring = kcalloc(new_size, sizeof(*ring), GFP_NOWAIT);546546+ if (!ring)547547+ return false;548548+549549+ /* allocate/trim descriptors as needed */550550+ if (new_size > curr_size) {551551+ /* copy current descriptors to the new ring */552552+ for (i = 0; i < curr_size; i++) {553553+ u16 curr_idx = (ioat->tail+i) & (curr_size-1);554554+ u16 new_idx = (ioat->tail+i) & (new_size-1);555555+556556+ ring[new_idx] = ioat->ring[curr_idx];557557+ set_desc_id(ring[new_idx], new_idx);558558+ }559559+560560+ /* add new descriptors to the ring */561561+ for (i = curr_size; i < new_size; i++) {562562+ u16 new_idx = (ioat->tail+i) & (new_size-1);563563+564564+ ring[new_idx] = ioat2_alloc_ring_ent(c, GFP_NOWAIT);565565+ if (!ring[new_idx]) {566566+ while (i--) {567567+ u16 new_idx = (ioat->tail+i) & (new_size-1);568568+569569+ ioat2_free_ring_ent(ring[new_idx], c);570570+ }571571+ kfree(ring);572572+ return false;573573+ }574574+ set_desc_id(ring[new_idx], new_idx);575575+ }576576+577577+ /* hw link new descriptors */578578+ for (i = curr_size-1; i < new_size; i++) {579579+ u16 new_idx = (ioat->tail+i) & (new_size-1);580580+ struct ioat_ring_ent *next = ring[(new_idx+1) & (new_size-1)];581581+ struct ioat_dma_descriptor *hw = ring[new_idx]->hw;582582+583583+ hw->next = next->txd.phys;584584+ }585585+ } else {586586+ struct ioat_dma_descriptor *hw;587587+ struct ioat_ring_ent *next;588588+589589+ /* copy current descriptors to the new ring, dropping the590590+ * removed descriptors591591+ */592592+ for (i = 0; i < new_size; i++) {593593+ u16 curr_idx = (ioat->tail+i) & (curr_size-1);594594+ u16 new_idx = (ioat->tail+i) & (new_size-1);595595+596596+ ring[new_idx] = ioat->ring[curr_idx];597597+ set_desc_id(ring[new_idx], new_idx);598598+ }599599+600600+ /* free deleted descriptors */601601+ for (i = new_size; i < curr_size; i++) {602602+ struct ioat_ring_ent *ent;603603+604604+ ent = ioat2_get_ring_ent(ioat, ioat->tail+i);605605+ ioat2_free_ring_ent(ent, c);606606+ }607607+608608+ /* fix up hardware ring */609609+ hw = ring[(ioat->tail+new_size-1) & (new_size-1)]->hw;610610+ next = ring[(ioat->tail+new_size) & (new_size-1)];611611+ hw->next = next->txd.phys;612612+ }613613+614614+ dev_dbg(to_dev(chan), "%s: allocated %d descriptors\n",615615+ __func__, new_size);616616+617617+ kfree(ioat->ring);618618+ ioat->ring = ring;619619+ ioat->alloc_order = order;620620+621621+ return true;622622+}623623+624624+/**625625+ * ioat2_alloc_and_lock - common descriptor alloc boilerplate for ioat2,3 ops626626+ * @idx: gets starting descriptor index on successful allocation627627+ * @ioat: ioat2,3 channel (ring) to operate on628628+ * @num_descs: allocation length629629+ */630630+int ioat2_alloc_and_lock(u16 *idx, struct ioat2_dma_chan *ioat, int num_descs)631631+{632632+ struct ioat_chan_common *chan = &ioat->base;633633+634634+ spin_lock_bh(&ioat->ring_lock);635635+ /* never allow the last descriptor to be consumed, we need at636636+ * least one free at all times to allow for on-the-fly ring637637+ * resizing.638638+ */639639+ while (unlikely(ioat2_ring_space(ioat) <= num_descs)) {640640+ if (reshape_ring(ioat, ioat->alloc_order + 1) &&641641+ ioat2_ring_space(ioat) > num_descs)642642+ break;643643+644644+ if (printk_ratelimit())645645+ dev_dbg(to_dev(chan),646646+ "%s: ring full! num_descs: %d (%x:%x:%x)\n",647647+ __func__, num_descs, ioat->head, ioat->tail,648648+ ioat->issued);649649+ spin_unlock_bh(&ioat->ring_lock);650650+651651+ /* progress reclaim in the allocation failure case we652652+ * may be called under bh_disabled so we need to trigger653653+ * the timer event directly654654+ */655655+ spin_lock_bh(&chan->cleanup_lock);656656+ if (jiffies > chan->timer.expires &&657657+ timer_pending(&chan->timer)) {658658+ struct ioatdma_device *device = chan->device;659659+660660+ mod_timer(&chan->timer, jiffies + COMPLETION_TIMEOUT);661661+ spin_unlock_bh(&chan->cleanup_lock);662662+ device->timer_fn((unsigned long) ioat);663663+ } else664664+ spin_unlock_bh(&chan->cleanup_lock);665665+ return -ENOMEM;666666+ }667667+668668+ dev_dbg(to_dev(chan), "%s: num_descs: %d (%x:%x:%x)\n",669669+ __func__, num_descs, ioat->head, ioat->tail, ioat->issued);670670+671671+ *idx = ioat2_desc_alloc(ioat, num_descs);672672+ return 0; /* with ioat->ring_lock held */673673+}674674+675675+struct dma_async_tx_descriptor *676676+ioat2_dma_prep_memcpy_lock(struct dma_chan *c, dma_addr_t dma_dest,677677+ dma_addr_t dma_src, size_t len, unsigned long flags)678678+{679679+ struct ioat2_dma_chan *ioat = to_ioat2_chan(c);680680+ struct ioat_dma_descriptor *hw;681681+ struct ioat_ring_ent *desc;682682+ dma_addr_t dst = dma_dest;683683+ dma_addr_t src = dma_src;684684+ size_t total_len = len;685685+ int num_descs;686686+ u16 idx;687687+ int i;688688+689689+ num_descs = ioat2_xferlen_to_descs(ioat, len);690690+ if (likely(num_descs) &&691691+ ioat2_alloc_and_lock(&idx, ioat, num_descs) == 0)692692+ /* pass */;693693+ else694694+ return NULL;695695+ i = 0;696696+ do {697697+ size_t copy = min_t(size_t, len, 1 << ioat->xfercap_log);698698+699699+ desc = ioat2_get_ring_ent(ioat, idx + i);700700+ hw = desc->hw;701701+702702+ hw->size = copy;703703+ hw->ctl = 0;704704+ hw->src_addr = src;705705+ hw->dst_addr = dst;706706+707707+ len -= copy;708708+ dst += copy;709709+ src += copy;710710+ dump_desc_dbg(ioat, desc);711711+ } while (++i < num_descs);712712+713713+ desc->txd.flags = flags;714714+ desc->len = total_len;715715+ hw->ctl_f.int_en = !!(flags & DMA_PREP_INTERRUPT);716716+ hw->ctl_f.fence = !!(flags & DMA_PREP_FENCE);717717+ hw->ctl_f.compl_write = 1;718718+ dump_desc_dbg(ioat, desc);719719+ /* we leave the channel locked to ensure in order submission */720720+721721+ return &desc->txd;722722+}723723+724724+/**725725+ * ioat2_free_chan_resources - release all the descriptors726726+ * @chan: the channel to be cleaned727727+ */728728+void ioat2_free_chan_resources(struct dma_chan *c)729729+{730730+ struct ioat2_dma_chan *ioat = to_ioat2_chan(c);731731+ struct ioat_chan_common *chan = &ioat->base;732732+ struct ioatdma_device *device = chan->device;733733+ struct ioat_ring_ent *desc;734734+ const u16 total_descs = 1 << ioat->alloc_order;735735+ int descs;736736+ int i;737737+738738+ /* Before freeing channel resources first check739739+ * if they have been previously allocated for this channel.740740+ */741741+ if (!ioat->ring)742742+ return;743743+744744+ tasklet_disable(&chan->cleanup_task);745745+ del_timer_sync(&chan->timer);746746+ device->cleanup_tasklet((unsigned long) ioat);747747+748748+ /* Delay 100ms after reset to allow internal DMA logic to quiesce749749+ * before removing DMA descriptor resources.750750+ */751751+ writeb(IOAT_CHANCMD_RESET,752752+ chan->reg_base + IOAT_CHANCMD_OFFSET(chan->device->version));753753+ mdelay(100);754754+755755+ spin_lock_bh(&ioat->ring_lock);756756+ descs = ioat2_ring_space(ioat);757757+ dev_dbg(to_dev(chan), "freeing %d idle descriptors\n", descs);758758+ for (i = 0; i < descs; i++) {759759+ desc = ioat2_get_ring_ent(ioat, ioat->head + i);760760+ ioat2_free_ring_ent(desc, c);761761+ }762762+763763+ if (descs < total_descs)764764+ dev_err(to_dev(chan), "Freeing %d in use descriptors!\n",765765+ total_descs - descs);766766+767767+ for (i = 0; i < total_descs - descs; i++) {768768+ desc = ioat2_get_ring_ent(ioat, ioat->tail + i);769769+ dump_desc_dbg(ioat, desc);770770+ ioat2_free_ring_ent(desc, c);771771+ }772772+773773+ kfree(ioat->ring);774774+ ioat->ring = NULL;775775+ ioat->alloc_order = 0;776776+ pci_pool_free(device->completion_pool, chan->completion,777777+ chan->completion_dma);778778+ spin_unlock_bh(&ioat->ring_lock);779779+780780+ chan->last_completion = 0;781781+ chan->completion_dma = 0;782782+ ioat->pending = 0;783783+ ioat->dmacount = 0;784784+}785785+786786+enum dma_status787787+ioat2_is_complete(struct dma_chan *c, dma_cookie_t cookie,788788+ dma_cookie_t *done, dma_cookie_t *used)789789+{790790+ struct ioat2_dma_chan *ioat = to_ioat2_chan(c);791791+ struct ioatdma_device *device = ioat->base.device;792792+793793+ if (ioat_is_complete(c, cookie, done, used) == DMA_SUCCESS)794794+ return DMA_SUCCESS;795795+796796+ device->cleanup_tasklet((unsigned long) ioat);797797+798798+ return ioat_is_complete(c, cookie, done, used);799799+}800800+801801+static ssize_t ring_size_show(struct dma_chan *c, char *page)802802+{803803+ struct ioat2_dma_chan *ioat = to_ioat2_chan(c);804804+805805+ return sprintf(page, "%d\n", (1 << ioat->alloc_order) & ~1);806806+}807807+static struct ioat_sysfs_entry ring_size_attr = __ATTR_RO(ring_size);808808+809809+static ssize_t ring_active_show(struct dma_chan *c, char *page)810810+{811811+ struct ioat2_dma_chan *ioat = to_ioat2_chan(c);812812+813813+ /* ...taken outside the lock, no need to be precise */814814+ return sprintf(page, "%d\n", ioat2_ring_active(ioat));815815+}816816+static struct ioat_sysfs_entry ring_active_attr = __ATTR_RO(ring_active);817817+818818+static struct attribute *ioat2_attrs[] = {819819+ &ring_size_attr.attr,820820+ &ring_active_attr.attr,821821+ &ioat_cap_attr.attr,822822+ &ioat_version_attr.attr,823823+ NULL,824824+};825825+826826+struct kobj_type ioat2_ktype = {827827+ .sysfs_ops = &ioat_sysfs_ops,828828+ .default_attrs = ioat2_attrs,829829+};830830+831831+int __devinit ioat2_dma_probe(struct ioatdma_device *device, int dca)832832+{833833+ struct pci_dev *pdev = device->pdev;834834+ struct dma_device *dma;835835+ struct dma_chan *c;836836+ struct ioat_chan_common *chan;837837+ int err;838838+839839+ device->enumerate_channels = ioat2_enumerate_channels;840840+ device->cleanup_tasklet = ioat2_cleanup_tasklet;841841+ device->timer_fn = ioat2_timer_event;842842+ device->self_test = ioat_dma_self_test;843843+ dma = &device->common;844844+ dma->device_prep_dma_memcpy = ioat2_dma_prep_memcpy_lock;845845+ dma->device_issue_pending = ioat2_issue_pending;846846+ dma->device_alloc_chan_resources = ioat2_alloc_chan_resources;847847+ dma->device_free_chan_resources = ioat2_free_chan_resources;848848+ dma->device_is_tx_complete = ioat2_is_complete;849849+850850+ err = ioat_probe(device);851851+ if (err)852852+ return err;853853+ ioat_set_tcp_copy_break(2048);854854+855855+ list_for_each_entry(c, &dma->channels, device_node) {856856+ chan = to_chan_common(c);857857+ writel(IOAT_DCACTRL_CMPL_WRITE_ENABLE | IOAT_DMA_DCA_ANY_CPU,858858+ chan->reg_base + IOAT_DCACTRL_OFFSET);859859+ }860860+861861+ err = ioat_register(device);862862+ if (err)863863+ return err;864864+865865+ ioat_kobject_add(device, &ioat2_ktype);866866+867867+ if (dca)868868+ device->dca = ioat2_dca_init(pdev, device->reg_base);869869+870870+ return err;871871+}
+190
drivers/dma/ioat/dma_v2.h
···11+/*22+ * Copyright(c) 2004 - 2009 Intel Corporation. All rights reserved.33+ *44+ * This program is free software; you can redistribute it and/or modify it55+ * under the terms of the GNU General Public License as published by the Free66+ * Software Foundation; either version 2 of the License, or (at your option)77+ * any later version.88+ *99+ * This program is distributed in the hope that it will be useful, but WITHOUT1010+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or1111+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for1212+ * more details.1313+ *1414+ * You should have received a copy of the GNU General Public License along with1515+ * this program; if not, write to the Free Software Foundation, Inc., 591616+ * Temple Place - Suite 330, Boston, MA 02111-1307, USA.1717+ *1818+ * The full GNU General Public License is included in this distribution in the1919+ * file called COPYING.2020+ */2121+#ifndef IOATDMA_V2_H2222+#define IOATDMA_V2_H2323+2424+#include <linux/dmaengine.h>2525+#include "dma.h"2626+#include "hw.h"2727+2828+2929+extern int ioat_pending_level;3030+extern int ioat_ring_alloc_order;3131+3232+/*3333+ * workaround for IOAT ver.3.0 null descriptor issue3434+ * (channel returns error when size is 0)3535+ */3636+#define NULL_DESC_BUFFER_SIZE 13737+3838+#define IOAT_MAX_ORDER 163939+#define ioat_get_alloc_order() \4040+ (min(ioat_ring_alloc_order, IOAT_MAX_ORDER))4141+#define ioat_get_max_alloc_order() \4242+ (min(ioat_ring_max_alloc_order, IOAT_MAX_ORDER))4343+4444+/* struct ioat2_dma_chan - ioat v2 / v3 channel attributes4545+ * @base: common ioat channel parameters4646+ * @xfercap_log; log2 of channel max transfer length (for fast division)4747+ * @head: allocated index4848+ * @issued: hardware notification point4949+ * @tail: cleanup index5050+ * @pending: lock free indicator for issued != head5151+ * @dmacount: identical to 'head' except for occasionally resetting to zero5252+ * @alloc_order: log2 of the number of allocated descriptors5353+ * @ring: software ring buffer implementation of hardware ring5454+ * @ring_lock: protects ring attributes5555+ */5656+struct ioat2_dma_chan {5757+ struct ioat_chan_common base;5858+ size_t xfercap_log;5959+ u16 head;6060+ u16 issued;6161+ u16 tail;6262+ u16 dmacount;6363+ u16 alloc_order;6464+ int pending;6565+ struct ioat_ring_ent **ring;6666+ spinlock_t ring_lock;6767+};6868+6969+static inline struct ioat2_dma_chan *to_ioat2_chan(struct dma_chan *c)7070+{7171+ struct ioat_chan_common *chan = to_chan_common(c);7272+7373+ return container_of(chan, struct ioat2_dma_chan, base);7474+}7575+7676+static inline u16 ioat2_ring_mask(struct ioat2_dma_chan *ioat)7777+{7878+ return (1 << ioat->alloc_order) - 1;7979+}8080+8181+/* count of descriptors in flight with the engine */8282+static inline u16 ioat2_ring_active(struct ioat2_dma_chan *ioat)8383+{8484+ return (ioat->head - ioat->tail) & ioat2_ring_mask(ioat);8585+}8686+8787+/* count of descriptors pending submission to hardware */8888+static inline u16 ioat2_ring_pending(struct ioat2_dma_chan *ioat)8989+{9090+ return (ioat->head - ioat->issued) & ioat2_ring_mask(ioat);9191+}9292+9393+static inline u16 ioat2_ring_space(struct ioat2_dma_chan *ioat)9494+{9595+ u16 num_descs = ioat2_ring_mask(ioat) + 1;9696+ u16 active = ioat2_ring_active(ioat);9797+9898+ BUG_ON(active > num_descs);9999+100100+ return num_descs - active;101101+}102102+103103+/* assumes caller already checked space */104104+static inline u16 ioat2_desc_alloc(struct ioat2_dma_chan *ioat, u16 len)105105+{106106+ ioat->head += len;107107+ return ioat->head - len;108108+}109109+110110+static inline u16 ioat2_xferlen_to_descs(struct ioat2_dma_chan *ioat, size_t len)111111+{112112+ u16 num_descs = len >> ioat->xfercap_log;113113+114114+ num_descs += !!(len & ((1 << ioat->xfercap_log) - 1));115115+ return num_descs;116116+}117117+118118+/**119119+ * struct ioat_ring_ent - wrapper around hardware descriptor120120+ * @hw: hardware DMA descriptor (for memcpy)121121+ * @fill: hardware fill descriptor122122+ * @xor: hardware xor descriptor123123+ * @xor_ex: hardware xor extension descriptor124124+ * @pq: hardware pq descriptor125125+ * @pq_ex: hardware pq extension descriptor126126+ * @pqu: hardware pq update descriptor127127+ * @raw: hardware raw (un-typed) descriptor128128+ * @txd: the generic software descriptor for all engines129129+ * @len: total transaction length for unmap130130+ * @result: asynchronous result of validate operations131131+ * @id: identifier for debug132132+ */133133+134134+struct ioat_ring_ent {135135+ union {136136+ struct ioat_dma_descriptor *hw;137137+ struct ioat_fill_descriptor *fill;138138+ struct ioat_xor_descriptor *xor;139139+ struct ioat_xor_ext_descriptor *xor_ex;140140+ struct ioat_pq_descriptor *pq;141141+ struct ioat_pq_ext_descriptor *pq_ex;142142+ struct ioat_pq_update_descriptor *pqu;143143+ struct ioat_raw_descriptor *raw;144144+ };145145+ size_t len;146146+ struct dma_async_tx_descriptor txd;147147+ enum sum_check_flags *result;148148+ #ifdef DEBUG149149+ int id;150150+ #endif151151+};152152+153153+static inline struct ioat_ring_ent *154154+ioat2_get_ring_ent(struct ioat2_dma_chan *ioat, u16 idx)155155+{156156+ return ioat->ring[idx & ioat2_ring_mask(ioat)];157157+}158158+159159+static inline void ioat2_set_chainaddr(struct ioat2_dma_chan *ioat, u64 addr)160160+{161161+ struct ioat_chan_common *chan = &ioat->base;162162+163163+ writel(addr & 0x00000000FFFFFFFF,164164+ chan->reg_base + IOAT2_CHAINADDR_OFFSET_LOW);165165+ writel(addr >> 32,166166+ chan->reg_base + IOAT2_CHAINADDR_OFFSET_HIGH);167167+}168168+169169+int __devinit ioat2_dma_probe(struct ioatdma_device *dev, int dca);170170+int __devinit ioat3_dma_probe(struct ioatdma_device *dev, int dca);171171+struct dca_provider * __devinit ioat2_dca_init(struct pci_dev *pdev, void __iomem *iobase);172172+struct dca_provider * __devinit ioat3_dca_init(struct pci_dev *pdev, void __iomem *iobase);173173+int ioat2_alloc_and_lock(u16 *idx, struct ioat2_dma_chan *ioat, int num_descs);174174+int ioat2_enumerate_channels(struct ioatdma_device *device);175175+struct dma_async_tx_descriptor *176176+ioat2_dma_prep_memcpy_lock(struct dma_chan *c, dma_addr_t dma_dest,177177+ dma_addr_t dma_src, size_t len, unsigned long flags);178178+void ioat2_issue_pending(struct dma_chan *chan);179179+int ioat2_alloc_chan_resources(struct dma_chan *c);180180+void ioat2_free_chan_resources(struct dma_chan *c);181181+enum dma_status ioat2_is_complete(struct dma_chan *c, dma_cookie_t cookie,182182+ dma_cookie_t *done, dma_cookie_t *used);183183+void __ioat2_restart_chan(struct ioat2_dma_chan *ioat);184184+bool reshape_ring(struct ioat2_dma_chan *ioat, int order);185185+void __ioat2_issue_pending(struct ioat2_dma_chan *ioat);186186+void ioat2_cleanup_tasklet(unsigned long data);187187+void ioat2_timer_event(unsigned long data);188188+extern struct kobj_type ioat2_ktype;189189+extern struct kmem_cache *ioat2_cache;190190+#endif /* IOATDMA_V2_H */
+1223
drivers/dma/ioat/dma_v3.c
···11+/*22+ * This file is provided under a dual BSD/GPLv2 license. When using or33+ * redistributing this file, you may do so under either license.44+ *55+ * GPL LICENSE SUMMARY66+ *77+ * Copyright(c) 2004 - 2009 Intel Corporation. All rights reserved.88+ *99+ * This program is free software; you can redistribute it and/or modify it1010+ * under the terms and conditions of the GNU General Public License,1111+ * version 2, as published by the Free Software Foundation.1212+ *1313+ * This program is distributed in the hope that it will be useful, but WITHOUT1414+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or1515+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for1616+ * more details.1717+ *1818+ * You should have received a copy of the GNU General Public License along with1919+ * this program; if not, write to the Free Software Foundation, Inc.,2020+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.2121+ *2222+ * The full GNU General Public License is included in this distribution in2323+ * the file called "COPYING".2424+ *2525+ * BSD LICENSE2626+ *2727+ * Copyright(c) 2004-2009 Intel Corporation. All rights reserved.2828+ *2929+ * Redistribution and use in source and binary forms, with or without3030+ * modification, are permitted provided that the following conditions are met:3131+ *3232+ * * Redistributions of source code must retain the above copyright3333+ * notice, this list of conditions and the following disclaimer.3434+ * * Redistributions in binary form must reproduce the above copyright3535+ * notice, this list of conditions and the following disclaimer in3636+ * the documentation and/or other materials provided with the3737+ * distribution.3838+ * * Neither the name of Intel Corporation nor the names of its3939+ * contributors may be used to endorse or promote products derived4040+ * from this software without specific prior written permission.4141+ *4242+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"4343+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE4444+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE4545+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE4646+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR4747+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF4848+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS4949+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN5050+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)5151+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE5252+ * POSSIBILITY OF SUCH DAMAGE.5353+ */5454+5555+/*5656+ * Support routines for v3+ hardware5757+ */5858+5959+#include <linux/pci.h>6060+#include <linux/dmaengine.h>6161+#include <linux/dma-mapping.h>6262+#include "registers.h"6363+#include "hw.h"6464+#include "dma.h"6565+#include "dma_v2.h"6666+6767+/* ioat hardware assumes at least two sources for raid operations */6868+#define src_cnt_to_sw(x) ((x) + 2)6969+#define src_cnt_to_hw(x) ((x) - 2)7070+7171+/* provide a lookup table for setting the source address in the base or7272+ * extended descriptor of an xor or pq descriptor7373+ */7474+static const u8 xor_idx_to_desc __read_mostly = 0xd0;7575+static const u8 xor_idx_to_field[] __read_mostly = { 1, 4, 5, 6, 7, 0, 1, 2 };7676+static const u8 pq_idx_to_desc __read_mostly = 0xf8;7777+static const u8 pq_idx_to_field[] __read_mostly = { 1, 4, 5, 0, 1, 2, 4, 5 };7878+7979+static dma_addr_t xor_get_src(struct ioat_raw_descriptor *descs[2], int idx)8080+{8181+ struct ioat_raw_descriptor *raw = descs[xor_idx_to_desc >> idx & 1];8282+8383+ return raw->field[xor_idx_to_field[idx]];8484+}8585+8686+static void xor_set_src(struct ioat_raw_descriptor *descs[2],8787+ dma_addr_t addr, u32 offset, int idx)8888+{8989+ struct ioat_raw_descriptor *raw = descs[xor_idx_to_desc >> idx & 1];9090+9191+ raw->field[xor_idx_to_field[idx]] = addr + offset;9292+}9393+9494+static dma_addr_t pq_get_src(struct ioat_raw_descriptor *descs[2], int idx)9595+{9696+ struct ioat_raw_descriptor *raw = descs[pq_idx_to_desc >> idx & 1];9797+9898+ return raw->field[pq_idx_to_field[idx]];9999+}100100+101101+static void pq_set_src(struct ioat_raw_descriptor *descs[2],102102+ dma_addr_t addr, u32 offset, u8 coef, int idx)103103+{104104+ struct ioat_pq_descriptor *pq = (struct ioat_pq_descriptor *) descs[0];105105+ struct ioat_raw_descriptor *raw = descs[pq_idx_to_desc >> idx & 1];106106+107107+ raw->field[pq_idx_to_field[idx]] = addr + offset;108108+ pq->coef[idx] = coef;109109+}110110+111111+static void ioat3_dma_unmap(struct ioat2_dma_chan *ioat,112112+ struct ioat_ring_ent *desc, int idx)113113+{114114+ struct ioat_chan_common *chan = &ioat->base;115115+ struct pci_dev *pdev = chan->device->pdev;116116+ size_t len = desc->len;117117+ size_t offset = len - desc->hw->size;118118+ struct dma_async_tx_descriptor *tx = &desc->txd;119119+ enum dma_ctrl_flags flags = tx->flags;120120+121121+ switch (desc->hw->ctl_f.op) {122122+ case IOAT_OP_COPY:123123+ if (!desc->hw->ctl_f.null) /* skip 'interrupt' ops */124124+ ioat_dma_unmap(chan, flags, len, desc->hw);125125+ break;126126+ case IOAT_OP_FILL: {127127+ struct ioat_fill_descriptor *hw = desc->fill;128128+129129+ if (!(flags & DMA_COMPL_SKIP_DEST_UNMAP))130130+ ioat_unmap(pdev, hw->dst_addr - offset, len,131131+ PCI_DMA_FROMDEVICE, flags, 1);132132+ break;133133+ }134134+ case IOAT_OP_XOR_VAL:135135+ case IOAT_OP_XOR: {136136+ struct ioat_xor_descriptor *xor = desc->xor;137137+ struct ioat_ring_ent *ext;138138+ struct ioat_xor_ext_descriptor *xor_ex = NULL;139139+ int src_cnt = src_cnt_to_sw(xor->ctl_f.src_cnt);140140+ struct ioat_raw_descriptor *descs[2];141141+ int i;142142+143143+ if (src_cnt > 5) {144144+ ext = ioat2_get_ring_ent(ioat, idx + 1);145145+ xor_ex = ext->xor_ex;146146+ }147147+148148+ if (!(flags & DMA_COMPL_SKIP_SRC_UNMAP)) {149149+ descs[0] = (struct ioat_raw_descriptor *) xor;150150+ descs[1] = (struct ioat_raw_descriptor *) xor_ex;151151+ for (i = 0; i < src_cnt; i++) {152152+ dma_addr_t src = xor_get_src(descs, i);153153+154154+ ioat_unmap(pdev, src - offset, len,155155+ PCI_DMA_TODEVICE, flags, 0);156156+ }157157+158158+ /* dest is a source in xor validate operations */159159+ if (xor->ctl_f.op == IOAT_OP_XOR_VAL) {160160+ ioat_unmap(pdev, xor->dst_addr - offset, len,161161+ PCI_DMA_TODEVICE, flags, 1);162162+ break;163163+ }164164+ }165165+166166+ if (!(flags & DMA_COMPL_SKIP_DEST_UNMAP))167167+ ioat_unmap(pdev, xor->dst_addr - offset, len,168168+ PCI_DMA_FROMDEVICE, flags, 1);169169+ break;170170+ }171171+ case IOAT_OP_PQ_VAL:172172+ case IOAT_OP_PQ: {173173+ struct ioat_pq_descriptor *pq = desc->pq;174174+ struct ioat_ring_ent *ext;175175+ struct ioat_pq_ext_descriptor *pq_ex = NULL;176176+ int src_cnt = src_cnt_to_sw(pq->ctl_f.src_cnt);177177+ struct ioat_raw_descriptor *descs[2];178178+ int i;179179+180180+ if (src_cnt > 3) {181181+ ext = ioat2_get_ring_ent(ioat, idx + 1);182182+ pq_ex = ext->pq_ex;183183+ }184184+185185+ /* in the 'continue' case don't unmap the dests as sources */186186+ if (dmaf_p_disabled_continue(flags))187187+ src_cnt--;188188+ else if (dmaf_continue(flags))189189+ src_cnt -= 3;190190+191191+ if (!(flags & DMA_COMPL_SKIP_SRC_UNMAP)) {192192+ descs[0] = (struct ioat_raw_descriptor *) pq;193193+ descs[1] = (struct ioat_raw_descriptor *) pq_ex;194194+ for (i = 0; i < src_cnt; i++) {195195+ dma_addr_t src = pq_get_src(descs, i);196196+197197+ ioat_unmap(pdev, src - offset, len,198198+ PCI_DMA_TODEVICE, flags, 0);199199+ }200200+201201+ /* the dests are sources in pq validate operations */202202+ if (pq->ctl_f.op == IOAT_OP_XOR_VAL) {203203+ if (!(flags & DMA_PREP_PQ_DISABLE_P))204204+ ioat_unmap(pdev, pq->p_addr - offset,205205+ len, PCI_DMA_TODEVICE, flags, 0);206206+ if (!(flags & DMA_PREP_PQ_DISABLE_Q))207207+ ioat_unmap(pdev, pq->q_addr - offset,208208+ len, PCI_DMA_TODEVICE, flags, 0);209209+ break;210210+ }211211+ }212212+213213+ if (!(flags & DMA_COMPL_SKIP_DEST_UNMAP)) {214214+ if (!(flags & DMA_PREP_PQ_DISABLE_P))215215+ ioat_unmap(pdev, pq->p_addr - offset, len,216216+ PCI_DMA_BIDIRECTIONAL, flags, 1);217217+ if (!(flags & DMA_PREP_PQ_DISABLE_Q))218218+ ioat_unmap(pdev, pq->q_addr - offset, len,219219+ PCI_DMA_BIDIRECTIONAL, flags, 1);220220+ }221221+ break;222222+ }223223+ default:224224+ dev_err(&pdev->dev, "%s: unknown op type: %#x\n",225225+ __func__, desc->hw->ctl_f.op);226226+ }227227+}228228+229229+static bool desc_has_ext(struct ioat_ring_ent *desc)230230+{231231+ struct ioat_dma_descriptor *hw = desc->hw;232232+233233+ if (hw->ctl_f.op == IOAT_OP_XOR ||234234+ hw->ctl_f.op == IOAT_OP_XOR_VAL) {235235+ struct ioat_xor_descriptor *xor = desc->xor;236236+237237+ if (src_cnt_to_sw(xor->ctl_f.src_cnt) > 5)238238+ return true;239239+ } else if (hw->ctl_f.op == IOAT_OP_PQ ||240240+ hw->ctl_f.op == IOAT_OP_PQ_VAL) {241241+ struct ioat_pq_descriptor *pq = desc->pq;242242+243243+ if (src_cnt_to_sw(pq->ctl_f.src_cnt) > 3)244244+ return true;245245+ }246246+247247+ return false;248248+}249249+250250+/**251251+ * __cleanup - reclaim used descriptors252252+ * @ioat: channel (ring) to clean253253+ *254254+ * The difference from the dma_v2.c __cleanup() is that this routine255255+ * handles extended descriptors and dma-unmapping raid operations.256256+ */257257+static void __cleanup(struct ioat2_dma_chan *ioat, unsigned long phys_complete)258258+{259259+ struct ioat_chan_common *chan = &ioat->base;260260+ struct ioat_ring_ent *desc;261261+ bool seen_current = false;262262+ u16 active;263263+ int i;264264+265265+ dev_dbg(to_dev(chan), "%s: head: %#x tail: %#x issued: %#x\n",266266+ __func__, ioat->head, ioat->tail, ioat->issued);267267+268268+ active = ioat2_ring_active(ioat);269269+ for (i = 0; i < active && !seen_current; i++) {270270+ struct dma_async_tx_descriptor *tx;271271+272272+ prefetch(ioat2_get_ring_ent(ioat, ioat->tail + i + 1));273273+ desc = ioat2_get_ring_ent(ioat, ioat->tail + i);274274+ dump_desc_dbg(ioat, desc);275275+ tx = &desc->txd;276276+ if (tx->cookie) {277277+ chan->completed_cookie = tx->cookie;278278+ ioat3_dma_unmap(ioat, desc, ioat->tail + i);279279+ tx->cookie = 0;280280+ if (tx->callback) {281281+ tx->callback(tx->callback_param);282282+ tx->callback = NULL;283283+ }284284+ }285285+286286+ if (tx->phys == phys_complete)287287+ seen_current = true;288288+289289+ /* skip extended descriptors */290290+ if (desc_has_ext(desc)) {291291+ BUG_ON(i + 1 >= active);292292+ i++;293293+ }294294+ }295295+ ioat->tail += i;296296+ BUG_ON(!seen_current); /* no active descs have written a completion? */297297+ chan->last_completion = phys_complete;298298+ if (ioat->head == ioat->tail) {299299+ dev_dbg(to_dev(chan), "%s: cancel completion timeout\n",300300+ __func__);301301+ clear_bit(IOAT_COMPLETION_PENDING, &chan->state);302302+ mod_timer(&chan->timer, jiffies + IDLE_TIMEOUT);303303+ }304304+}305305+306306+static void ioat3_cleanup(struct ioat2_dma_chan *ioat)307307+{308308+ struct ioat_chan_common *chan = &ioat->base;309309+ unsigned long phys_complete;310310+311311+ prefetch(chan->completion);312312+313313+ if (!spin_trylock_bh(&chan->cleanup_lock))314314+ return;315315+316316+ if (!ioat_cleanup_preamble(chan, &phys_complete)) {317317+ spin_unlock_bh(&chan->cleanup_lock);318318+ return;319319+ }320320+321321+ if (!spin_trylock_bh(&ioat->ring_lock)) {322322+ spin_unlock_bh(&chan->cleanup_lock);323323+ return;324324+ }325325+326326+ __cleanup(ioat, phys_complete);327327+328328+ spin_unlock_bh(&ioat->ring_lock);329329+ spin_unlock_bh(&chan->cleanup_lock);330330+}331331+332332+static void ioat3_cleanup_tasklet(unsigned long data)333333+{334334+ struct ioat2_dma_chan *ioat = (void *) data;335335+336336+ ioat3_cleanup(ioat);337337+ writew(IOAT_CHANCTRL_RUN | IOAT3_CHANCTRL_COMPL_DCA_EN,338338+ ioat->base.reg_base + IOAT_CHANCTRL_OFFSET);339339+}340340+341341+static void ioat3_restart_channel(struct ioat2_dma_chan *ioat)342342+{343343+ struct ioat_chan_common *chan = &ioat->base;344344+ unsigned long phys_complete;345345+ u32 status;346346+347347+ status = ioat_chansts(chan);348348+ if (is_ioat_active(status) || is_ioat_idle(status))349349+ ioat_suspend(chan);350350+ while (is_ioat_active(status) || is_ioat_idle(status)) {351351+ status = ioat_chansts(chan);352352+ cpu_relax();353353+ }354354+355355+ if (ioat_cleanup_preamble(chan, &phys_complete))356356+ __cleanup(ioat, phys_complete);357357+358358+ __ioat2_restart_chan(ioat);359359+}360360+361361+static void ioat3_timer_event(unsigned long data)362362+{363363+ struct ioat2_dma_chan *ioat = (void *) data;364364+ struct ioat_chan_common *chan = &ioat->base;365365+366366+ spin_lock_bh(&chan->cleanup_lock);367367+ if (test_bit(IOAT_COMPLETION_PENDING, &chan->state)) {368368+ unsigned long phys_complete;369369+ u64 status;370370+371371+ spin_lock_bh(&ioat->ring_lock);372372+ status = ioat_chansts(chan);373373+374374+ /* when halted due to errors check for channel375375+ * programming errors before advancing the completion state376376+ */377377+ if (is_ioat_halted(status)) {378378+ u32 chanerr;379379+380380+ chanerr = readl(chan->reg_base + IOAT_CHANERR_OFFSET);381381+ BUG_ON(is_ioat_bug(chanerr));382382+ }383383+384384+ /* if we haven't made progress and we have already385385+ * acknowledged a pending completion once, then be more386386+ * forceful with a restart387387+ */388388+ if (ioat_cleanup_preamble(chan, &phys_complete))389389+ __cleanup(ioat, phys_complete);390390+ else if (test_bit(IOAT_COMPLETION_ACK, &chan->state))391391+ ioat3_restart_channel(ioat);392392+ else {393393+ set_bit(IOAT_COMPLETION_ACK, &chan->state);394394+ mod_timer(&chan->timer, jiffies + COMPLETION_TIMEOUT);395395+ }396396+ spin_unlock_bh(&ioat->ring_lock);397397+ } else {398398+ u16 active;399399+400400+ /* if the ring is idle, empty, and oversized try to step401401+ * down the size402402+ */403403+ spin_lock_bh(&ioat->ring_lock);404404+ active = ioat2_ring_active(ioat);405405+ if (active == 0 && ioat->alloc_order > ioat_get_alloc_order())406406+ reshape_ring(ioat, ioat->alloc_order-1);407407+ spin_unlock_bh(&ioat->ring_lock);408408+409409+ /* keep shrinking until we get back to our minimum410410+ * default size411411+ */412412+ if (ioat->alloc_order > ioat_get_alloc_order())413413+ mod_timer(&chan->timer, jiffies + IDLE_TIMEOUT);414414+ }415415+ spin_unlock_bh(&chan->cleanup_lock);416416+}417417+418418+static enum dma_status419419+ioat3_is_complete(struct dma_chan *c, dma_cookie_t cookie,420420+ dma_cookie_t *done, dma_cookie_t *used)421421+{422422+ struct ioat2_dma_chan *ioat = to_ioat2_chan(c);423423+424424+ if (ioat_is_complete(c, cookie, done, used) == DMA_SUCCESS)425425+ return DMA_SUCCESS;426426+427427+ ioat3_cleanup(ioat);428428+429429+ return ioat_is_complete(c, cookie, done, used);430430+}431431+432432+static struct dma_async_tx_descriptor *433433+ioat3_prep_memset_lock(struct dma_chan *c, dma_addr_t dest, int value,434434+ size_t len, unsigned long flags)435435+{436436+ struct ioat2_dma_chan *ioat = to_ioat2_chan(c);437437+ struct ioat_ring_ent *desc;438438+ size_t total_len = len;439439+ struct ioat_fill_descriptor *fill;440440+ int num_descs;441441+ u64 src_data = (0x0101010101010101ULL) * (value & 0xff);442442+ u16 idx;443443+ int i;444444+445445+ num_descs = ioat2_xferlen_to_descs(ioat, len);446446+ if (likely(num_descs) &&447447+ ioat2_alloc_and_lock(&idx, ioat, num_descs) == 0)448448+ /* pass */;449449+ else450450+ return NULL;451451+ i = 0;452452+ do {453453+ size_t xfer_size = min_t(size_t, len, 1 << ioat->xfercap_log);454454+455455+ desc = ioat2_get_ring_ent(ioat, idx + i);456456+ fill = desc->fill;457457+458458+ fill->size = xfer_size;459459+ fill->src_data = src_data;460460+ fill->dst_addr = dest;461461+ fill->ctl = 0;462462+ fill->ctl_f.op = IOAT_OP_FILL;463463+464464+ len -= xfer_size;465465+ dest += xfer_size;466466+ dump_desc_dbg(ioat, desc);467467+ } while (++i < num_descs);468468+469469+ desc->txd.flags = flags;470470+ desc->len = total_len;471471+ fill->ctl_f.int_en = !!(flags & DMA_PREP_INTERRUPT);472472+ fill->ctl_f.fence = !!(flags & DMA_PREP_FENCE);473473+ fill->ctl_f.compl_write = 1;474474+ dump_desc_dbg(ioat, desc);475475+476476+ /* we leave the channel locked to ensure in order submission */477477+ return &desc->txd;478478+}479479+480480+static struct dma_async_tx_descriptor *481481+__ioat3_prep_xor_lock(struct dma_chan *c, enum sum_check_flags *result,482482+ dma_addr_t dest, dma_addr_t *src, unsigned int src_cnt,483483+ size_t len, unsigned long flags)484484+{485485+ struct ioat2_dma_chan *ioat = to_ioat2_chan(c);486486+ struct ioat_ring_ent *compl_desc;487487+ struct ioat_ring_ent *desc;488488+ struct ioat_ring_ent *ext;489489+ size_t total_len = len;490490+ struct ioat_xor_descriptor *xor;491491+ struct ioat_xor_ext_descriptor *xor_ex = NULL;492492+ struct ioat_dma_descriptor *hw;493493+ u32 offset = 0;494494+ int num_descs;495495+ int with_ext;496496+ int i;497497+ u16 idx;498498+ u8 op = result ? IOAT_OP_XOR_VAL : IOAT_OP_XOR;499499+500500+ BUG_ON(src_cnt < 2);501501+502502+ num_descs = ioat2_xferlen_to_descs(ioat, len);503503+ /* we need 2x the number of descriptors to cover greater than 5504504+ * sources505505+ */506506+ if (src_cnt > 5) {507507+ with_ext = 1;508508+ num_descs *= 2;509509+ } else510510+ with_ext = 0;511511+512512+ /* completion writes from the raid engine may pass completion513513+ * writes from the legacy engine, so we need one extra null514514+ * (legacy) descriptor to ensure all completion writes arrive in515515+ * order.516516+ */517517+ if (likely(num_descs) &&518518+ ioat2_alloc_and_lock(&idx, ioat, num_descs+1) == 0)519519+ /* pass */;520520+ else521521+ return NULL;522522+ i = 0;523523+ do {524524+ struct ioat_raw_descriptor *descs[2];525525+ size_t xfer_size = min_t(size_t, len, 1 << ioat->xfercap_log);526526+ int s;527527+528528+ desc = ioat2_get_ring_ent(ioat, idx + i);529529+ xor = desc->xor;530530+531531+ /* save a branch by unconditionally retrieving the532532+ * extended descriptor xor_set_src() knows to not write533533+ * to it in the single descriptor case534534+ */535535+ ext = ioat2_get_ring_ent(ioat, idx + i + 1);536536+ xor_ex = ext->xor_ex;537537+538538+ descs[0] = (struct ioat_raw_descriptor *) xor;539539+ descs[1] = (struct ioat_raw_descriptor *) xor_ex;540540+ for (s = 0; s < src_cnt; s++)541541+ xor_set_src(descs, src[s], offset, s);542542+ xor->size = xfer_size;543543+ xor->dst_addr = dest + offset;544544+ xor->ctl = 0;545545+ xor->ctl_f.op = op;546546+ xor->ctl_f.src_cnt = src_cnt_to_hw(src_cnt);547547+548548+ len -= xfer_size;549549+ offset += xfer_size;550550+ dump_desc_dbg(ioat, desc);551551+ } while ((i += 1 + with_ext) < num_descs);552552+553553+ /* last xor descriptor carries the unmap parameters and fence bit */554554+ desc->txd.flags = flags;555555+ desc->len = total_len;556556+ if (result)557557+ desc->result = result;558558+ xor->ctl_f.fence = !!(flags & DMA_PREP_FENCE);559559+560560+ /* completion descriptor carries interrupt bit */561561+ compl_desc = ioat2_get_ring_ent(ioat, idx + i);562562+ compl_desc->txd.flags = flags & DMA_PREP_INTERRUPT;563563+ hw = compl_desc->hw;564564+ hw->ctl = 0;565565+ hw->ctl_f.null = 1;566566+ hw->ctl_f.int_en = !!(flags & DMA_PREP_INTERRUPT);567567+ hw->ctl_f.compl_write = 1;568568+ hw->size = NULL_DESC_BUFFER_SIZE;569569+ dump_desc_dbg(ioat, compl_desc);570570+571571+ /* we leave the channel locked to ensure in order submission */572572+ return &desc->txd;573573+}574574+575575+static struct dma_async_tx_descriptor *576576+ioat3_prep_xor(struct dma_chan *chan, dma_addr_t dest, dma_addr_t *src,577577+ unsigned int src_cnt, size_t len, unsigned long flags)578578+{579579+ return __ioat3_prep_xor_lock(chan, NULL, dest, src, src_cnt, len, flags);580580+}581581+582582+struct dma_async_tx_descriptor *583583+ioat3_prep_xor_val(struct dma_chan *chan, dma_addr_t *src,584584+ unsigned int src_cnt, size_t len,585585+ enum sum_check_flags *result, unsigned long flags)586586+{587587+ /* the cleanup routine only sets bits on validate failure, it588588+ * does not clear bits on validate success... so clear it here589589+ */590590+ *result = 0;591591+592592+ return __ioat3_prep_xor_lock(chan, result, src[0], &src[1],593593+ src_cnt - 1, len, flags);594594+}595595+596596+static void597597+dump_pq_desc_dbg(struct ioat2_dma_chan *ioat, struct ioat_ring_ent *desc, struct ioat_ring_ent *ext)598598+{599599+ struct device *dev = to_dev(&ioat->base);600600+ struct ioat_pq_descriptor *pq = desc->pq;601601+ struct ioat_pq_ext_descriptor *pq_ex = ext ? ext->pq_ex : NULL;602602+ struct ioat_raw_descriptor *descs[] = { (void *) pq, (void *) pq_ex };603603+ int src_cnt = src_cnt_to_sw(pq->ctl_f.src_cnt);604604+ int i;605605+606606+ dev_dbg(dev, "desc[%d]: (%#llx->%#llx) flags: %#x"607607+ " sz: %#x ctl: %#x (op: %d int: %d compl: %d pq: '%s%s' src_cnt: %d)\n",608608+ desc_id(desc), (unsigned long long) desc->txd.phys,609609+ (unsigned long long) (pq_ex ? pq_ex->next : pq->next),610610+ desc->txd.flags, pq->size, pq->ctl, pq->ctl_f.op, pq->ctl_f.int_en,611611+ pq->ctl_f.compl_write,612612+ pq->ctl_f.p_disable ? "" : "p", pq->ctl_f.q_disable ? "" : "q",613613+ pq->ctl_f.src_cnt);614614+ for (i = 0; i < src_cnt; i++)615615+ dev_dbg(dev, "\tsrc[%d]: %#llx coef: %#x\n", i,616616+ (unsigned long long) pq_get_src(descs, i), pq->coef[i]);617617+ dev_dbg(dev, "\tP: %#llx\n", pq->p_addr);618618+ dev_dbg(dev, "\tQ: %#llx\n", pq->q_addr);619619+}620620+621621+static struct dma_async_tx_descriptor *622622+__ioat3_prep_pq_lock(struct dma_chan *c, enum sum_check_flags *result,623623+ const dma_addr_t *dst, const dma_addr_t *src,624624+ unsigned int src_cnt, const unsigned char *scf,625625+ size_t len, unsigned long flags)626626+{627627+ struct ioat2_dma_chan *ioat = to_ioat2_chan(c);628628+ struct ioat_chan_common *chan = &ioat->base;629629+ struct ioat_ring_ent *compl_desc;630630+ struct ioat_ring_ent *desc;631631+ struct ioat_ring_ent *ext;632632+ size_t total_len = len;633633+ struct ioat_pq_descriptor *pq;634634+ struct ioat_pq_ext_descriptor *pq_ex = NULL;635635+ struct ioat_dma_descriptor *hw;636636+ u32 offset = 0;637637+ int num_descs;638638+ int with_ext;639639+ int i, s;640640+ u16 idx;641641+ u8 op = result ? IOAT_OP_PQ_VAL : IOAT_OP_PQ;642642+643643+ dev_dbg(to_dev(chan), "%s\n", __func__);644644+ /* the engine requires at least two sources (we provide645645+ * at least 1 implied source in the DMA_PREP_CONTINUE case)646646+ */647647+ BUG_ON(src_cnt + dmaf_continue(flags) < 2);648648+649649+ num_descs = ioat2_xferlen_to_descs(ioat, len);650650+ /* we need 2x the number of descriptors to cover greater than 3651651+ * sources652652+ */653653+ if (src_cnt > 3 || flags & DMA_PREP_CONTINUE) {654654+ with_ext = 1;655655+ num_descs *= 2;656656+ } else657657+ with_ext = 0;658658+659659+ /* completion writes from the raid engine may pass completion660660+ * writes from the legacy engine, so we need one extra null661661+ * (legacy) descriptor to ensure all completion writes arrive in662662+ * order.663663+ */664664+ if (likely(num_descs) &&665665+ ioat2_alloc_and_lock(&idx, ioat, num_descs+1) == 0)666666+ /* pass */;667667+ else668668+ return NULL;669669+ i = 0;670670+ do {671671+ struct ioat_raw_descriptor *descs[2];672672+ size_t xfer_size = min_t(size_t, len, 1 << ioat->xfercap_log);673673+674674+ desc = ioat2_get_ring_ent(ioat, idx + i);675675+ pq = desc->pq;676676+677677+ /* save a branch by unconditionally retrieving the678678+ * extended descriptor pq_set_src() knows to not write679679+ * to it in the single descriptor case680680+ */681681+ ext = ioat2_get_ring_ent(ioat, idx + i + with_ext);682682+ pq_ex = ext->pq_ex;683683+684684+ descs[0] = (struct ioat_raw_descriptor *) pq;685685+ descs[1] = (struct ioat_raw_descriptor *) pq_ex;686686+687687+ for (s = 0; s < src_cnt; s++)688688+ pq_set_src(descs, src[s], offset, scf[s], s);689689+690690+ /* see the comment for dma_maxpq in include/linux/dmaengine.h */691691+ if (dmaf_p_disabled_continue(flags))692692+ pq_set_src(descs, dst[1], offset, 1, s++);693693+ else if (dmaf_continue(flags)) {694694+ pq_set_src(descs, dst[0], offset, 0, s++);695695+ pq_set_src(descs, dst[1], offset, 1, s++);696696+ pq_set_src(descs, dst[1], offset, 0, s++);697697+ }698698+ pq->size = xfer_size;699699+ pq->p_addr = dst[0] + offset;700700+ pq->q_addr = dst[1] + offset;701701+ pq->ctl = 0;702702+ pq->ctl_f.op = op;703703+ pq->ctl_f.src_cnt = src_cnt_to_hw(s);704704+ pq->ctl_f.p_disable = !!(flags & DMA_PREP_PQ_DISABLE_P);705705+ pq->ctl_f.q_disable = !!(flags & DMA_PREP_PQ_DISABLE_Q);706706+707707+ len -= xfer_size;708708+ offset += xfer_size;709709+ } while ((i += 1 + with_ext) < num_descs);710710+711711+ /* last pq descriptor carries the unmap parameters and fence bit */712712+ desc->txd.flags = flags;713713+ desc->len = total_len;714714+ if (result)715715+ desc->result = result;716716+ pq->ctl_f.fence = !!(flags & DMA_PREP_FENCE);717717+ dump_pq_desc_dbg(ioat, desc, ext);718718+719719+ /* completion descriptor carries interrupt bit */720720+ compl_desc = ioat2_get_ring_ent(ioat, idx + i);721721+ compl_desc->txd.flags = flags & DMA_PREP_INTERRUPT;722722+ hw = compl_desc->hw;723723+ hw->ctl = 0;724724+ hw->ctl_f.null = 1;725725+ hw->ctl_f.int_en = !!(flags & DMA_PREP_INTERRUPT);726726+ hw->ctl_f.compl_write = 1;727727+ hw->size = NULL_DESC_BUFFER_SIZE;728728+ dump_desc_dbg(ioat, compl_desc);729729+730730+ /* we leave the channel locked to ensure in order submission */731731+ return &desc->txd;732732+}733733+734734+static struct dma_async_tx_descriptor *735735+ioat3_prep_pq(struct dma_chan *chan, dma_addr_t *dst, dma_addr_t *src,736736+ unsigned int src_cnt, const unsigned char *scf, size_t len,737737+ unsigned long flags)738738+{739739+ /* handle the single source multiply case from the raid6740740+ * recovery path741741+ */742742+ if (unlikely((flags & DMA_PREP_PQ_DISABLE_P) && src_cnt == 1)) {743743+ dma_addr_t single_source[2];744744+ unsigned char single_source_coef[2];745745+746746+ BUG_ON(flags & DMA_PREP_PQ_DISABLE_Q);747747+ single_source[0] = src[0];748748+ single_source[1] = src[0];749749+ single_source_coef[0] = scf[0];750750+ single_source_coef[1] = 0;751751+752752+ return __ioat3_prep_pq_lock(chan, NULL, dst, single_source, 2,753753+ single_source_coef, len, flags);754754+ } else755755+ return __ioat3_prep_pq_lock(chan, NULL, dst, src, src_cnt, scf,756756+ len, flags);757757+}758758+759759+struct dma_async_tx_descriptor *760760+ioat3_prep_pq_val(struct dma_chan *chan, dma_addr_t *pq, dma_addr_t *src,761761+ unsigned int src_cnt, const unsigned char *scf, size_t len,762762+ enum sum_check_flags *pqres, unsigned long flags)763763+{764764+ /* the cleanup routine only sets bits on validate failure, it765765+ * does not clear bits on validate success... so clear it here766766+ */767767+ *pqres = 0;768768+769769+ return __ioat3_prep_pq_lock(chan, pqres, pq, src, src_cnt, scf, len,770770+ flags);771771+}772772+773773+static struct dma_async_tx_descriptor *774774+ioat3_prep_pqxor(struct dma_chan *chan, dma_addr_t dst, dma_addr_t *src,775775+ unsigned int src_cnt, size_t len, unsigned long flags)776776+{777777+ unsigned char scf[src_cnt];778778+ dma_addr_t pq[2];779779+780780+ memset(scf, 0, src_cnt);781781+ flags |= DMA_PREP_PQ_DISABLE_Q;782782+ pq[0] = dst;783783+ pq[1] = ~0;784784+785785+ return __ioat3_prep_pq_lock(chan, NULL, pq, src, src_cnt, scf, len,786786+ flags);787787+}788788+789789+struct dma_async_tx_descriptor *790790+ioat3_prep_pqxor_val(struct dma_chan *chan, dma_addr_t *src,791791+ unsigned int src_cnt, size_t len,792792+ enum sum_check_flags *result, unsigned long flags)793793+{794794+ unsigned char scf[src_cnt];795795+ dma_addr_t pq[2];796796+797797+ /* the cleanup routine only sets bits on validate failure, it798798+ * does not clear bits on validate success... so clear it here799799+ */800800+ *result = 0;801801+802802+ memset(scf, 0, src_cnt);803803+ flags |= DMA_PREP_PQ_DISABLE_Q;804804+ pq[0] = src[0];805805+ pq[1] = ~0;806806+807807+ return __ioat3_prep_pq_lock(chan, result, pq, &src[1], src_cnt - 1, scf,808808+ len, flags);809809+}810810+811811+static struct dma_async_tx_descriptor *812812+ioat3_prep_interrupt_lock(struct dma_chan *c, unsigned long flags)813813+{814814+ struct ioat2_dma_chan *ioat = to_ioat2_chan(c);815815+ struct ioat_ring_ent *desc;816816+ struct ioat_dma_descriptor *hw;817817+ u16 idx;818818+819819+ if (ioat2_alloc_and_lock(&idx, ioat, 1) == 0)820820+ desc = ioat2_get_ring_ent(ioat, idx);821821+ else822822+ return NULL;823823+824824+ hw = desc->hw;825825+ hw->ctl = 0;826826+ hw->ctl_f.null = 1;827827+ hw->ctl_f.int_en = 1;828828+ hw->ctl_f.fence = !!(flags & DMA_PREP_FENCE);829829+ hw->ctl_f.compl_write = 1;830830+ hw->size = NULL_DESC_BUFFER_SIZE;831831+ hw->src_addr = 0;832832+ hw->dst_addr = 0;833833+834834+ desc->txd.flags = flags;835835+ desc->len = 1;836836+837837+ dump_desc_dbg(ioat, desc);838838+839839+ /* we leave the channel locked to ensure in order submission */840840+ return &desc->txd;841841+}842842+843843+static void __devinit ioat3_dma_test_callback(void *dma_async_param)844844+{845845+ struct completion *cmp = dma_async_param;846846+847847+ complete(cmp);848848+}849849+850850+#define IOAT_NUM_SRC_TEST 6 /* must be <= 8 */851851+static int __devinit ioat_xor_val_self_test(struct ioatdma_device *device)852852+{853853+ int i, src_idx;854854+ struct page *dest;855855+ struct page *xor_srcs[IOAT_NUM_SRC_TEST];856856+ struct page *xor_val_srcs[IOAT_NUM_SRC_TEST + 1];857857+ dma_addr_t dma_srcs[IOAT_NUM_SRC_TEST + 1];858858+ dma_addr_t dma_addr, dest_dma;859859+ struct dma_async_tx_descriptor *tx;860860+ struct dma_chan *dma_chan;861861+ dma_cookie_t cookie;862862+ u8 cmp_byte = 0;863863+ u32 cmp_word;864864+ u32 xor_val_result;865865+ int err = 0;866866+ struct completion cmp;867867+ unsigned long tmo;868868+ struct device *dev = &device->pdev->dev;869869+ struct dma_device *dma = &device->common;870870+871871+ dev_dbg(dev, "%s\n", __func__);872872+873873+ if (!dma_has_cap(DMA_XOR, dma->cap_mask))874874+ return 0;875875+876876+ for (src_idx = 0; src_idx < IOAT_NUM_SRC_TEST; src_idx++) {877877+ xor_srcs[src_idx] = alloc_page(GFP_KERNEL);878878+ if (!xor_srcs[src_idx]) {879879+ while (src_idx--)880880+ __free_page(xor_srcs[src_idx]);881881+ return -ENOMEM;882882+ }883883+ }884884+885885+ dest = alloc_page(GFP_KERNEL);886886+ if (!dest) {887887+ while (src_idx--)888888+ __free_page(xor_srcs[src_idx]);889889+ return -ENOMEM;890890+ }891891+892892+ /* Fill in src buffers */893893+ for (src_idx = 0; src_idx < IOAT_NUM_SRC_TEST; src_idx++) {894894+ u8 *ptr = page_address(xor_srcs[src_idx]);895895+ for (i = 0; i < PAGE_SIZE; i++)896896+ ptr[i] = (1 << src_idx);897897+ }898898+899899+ for (src_idx = 0; src_idx < IOAT_NUM_SRC_TEST; src_idx++)900900+ cmp_byte ^= (u8) (1 << src_idx);901901+902902+ cmp_word = (cmp_byte << 24) | (cmp_byte << 16) |903903+ (cmp_byte << 8) | cmp_byte;904904+905905+ memset(page_address(dest), 0, PAGE_SIZE);906906+907907+ dma_chan = container_of(dma->channels.next, struct dma_chan,908908+ device_node);909909+ if (dma->device_alloc_chan_resources(dma_chan) < 1) {910910+ err = -ENODEV;911911+ goto out;912912+ }913913+914914+ /* test xor */915915+ dest_dma = dma_map_page(dev, dest, 0, PAGE_SIZE, DMA_FROM_DEVICE);916916+ for (i = 0; i < IOAT_NUM_SRC_TEST; i++)917917+ dma_srcs[i] = dma_map_page(dev, xor_srcs[i], 0, PAGE_SIZE,918918+ DMA_TO_DEVICE);919919+ tx = dma->device_prep_dma_xor(dma_chan, dest_dma, dma_srcs,920920+ IOAT_NUM_SRC_TEST, PAGE_SIZE,921921+ DMA_PREP_INTERRUPT);922922+923923+ if (!tx) {924924+ dev_err(dev, "Self-test xor prep failed\n");925925+ err = -ENODEV;926926+ goto free_resources;927927+ }928928+929929+ async_tx_ack(tx);930930+ init_completion(&cmp);931931+ tx->callback = ioat3_dma_test_callback;932932+ tx->callback_param = &cmp;933933+ cookie = tx->tx_submit(tx);934934+ if (cookie < 0) {935935+ dev_err(dev, "Self-test xor setup failed\n");936936+ err = -ENODEV;937937+ goto free_resources;938938+ }939939+ dma->device_issue_pending(dma_chan);940940+941941+ tmo = wait_for_completion_timeout(&cmp, msecs_to_jiffies(3000));942942+943943+ if (dma->device_is_tx_complete(dma_chan, cookie, NULL, NULL) != DMA_SUCCESS) {944944+ dev_err(dev, "Self-test xor timed out\n");945945+ err = -ENODEV;946946+ goto free_resources;947947+ }948948+949949+ dma_sync_single_for_cpu(dev, dest_dma, PAGE_SIZE, DMA_FROM_DEVICE);950950+ for (i = 0; i < (PAGE_SIZE / sizeof(u32)); i++) {951951+ u32 *ptr = page_address(dest);952952+ if (ptr[i] != cmp_word) {953953+ dev_err(dev, "Self-test xor failed compare\n");954954+ err = -ENODEV;955955+ goto free_resources;956956+ }957957+ }958958+ dma_sync_single_for_device(dev, dest_dma, PAGE_SIZE, DMA_TO_DEVICE);959959+960960+ /* skip validate if the capability is not present */961961+ if (!dma_has_cap(DMA_XOR_VAL, dma_chan->device->cap_mask))962962+ goto free_resources;963963+964964+ /* validate the sources with the destintation page */965965+ for (i = 0; i < IOAT_NUM_SRC_TEST; i++)966966+ xor_val_srcs[i] = xor_srcs[i];967967+ xor_val_srcs[i] = dest;968968+969969+ xor_val_result = 1;970970+971971+ for (i = 0; i < IOAT_NUM_SRC_TEST + 1; i++)972972+ dma_srcs[i] = dma_map_page(dev, xor_val_srcs[i], 0, PAGE_SIZE,973973+ DMA_TO_DEVICE);974974+ tx = dma->device_prep_dma_xor_val(dma_chan, dma_srcs,975975+ IOAT_NUM_SRC_TEST + 1, PAGE_SIZE,976976+ &xor_val_result, DMA_PREP_INTERRUPT);977977+ if (!tx) {978978+ dev_err(dev, "Self-test zero prep failed\n");979979+ err = -ENODEV;980980+ goto free_resources;981981+ }982982+983983+ async_tx_ack(tx);984984+ init_completion(&cmp);985985+ tx->callback = ioat3_dma_test_callback;986986+ tx->callback_param = &cmp;987987+ cookie = tx->tx_submit(tx);988988+ if (cookie < 0) {989989+ dev_err(dev, "Self-test zero setup failed\n");990990+ err = -ENODEV;991991+ goto free_resources;992992+ }993993+ dma->device_issue_pending(dma_chan);994994+995995+ tmo = wait_for_completion_timeout(&cmp, msecs_to_jiffies(3000));996996+997997+ if (dma->device_is_tx_complete(dma_chan, cookie, NULL, NULL) != DMA_SUCCESS) {998998+ dev_err(dev, "Self-test validate timed out\n");999999+ err = -ENODEV;10001000+ goto free_resources;10011001+ }10021002+10031003+ if (xor_val_result != 0) {10041004+ dev_err(dev, "Self-test validate failed compare\n");10051005+ err = -ENODEV;10061006+ goto free_resources;10071007+ }10081008+10091009+ /* skip memset if the capability is not present */10101010+ if (!dma_has_cap(DMA_MEMSET, dma_chan->device->cap_mask))10111011+ goto free_resources;10121012+10131013+ /* test memset */10141014+ dma_addr = dma_map_page(dev, dest, 0,10151015+ PAGE_SIZE, DMA_FROM_DEVICE);10161016+ tx = dma->device_prep_dma_memset(dma_chan, dma_addr, 0, PAGE_SIZE,10171017+ DMA_PREP_INTERRUPT);10181018+ if (!tx) {10191019+ dev_err(dev, "Self-test memset prep failed\n");10201020+ err = -ENODEV;10211021+ goto free_resources;10221022+ }10231023+10241024+ async_tx_ack(tx);10251025+ init_completion(&cmp);10261026+ tx->callback = ioat3_dma_test_callback;10271027+ tx->callback_param = &cmp;10281028+ cookie = tx->tx_submit(tx);10291029+ if (cookie < 0) {10301030+ dev_err(dev, "Self-test memset setup failed\n");10311031+ err = -ENODEV;10321032+ goto free_resources;10331033+ }10341034+ dma->device_issue_pending(dma_chan);10351035+10361036+ tmo = wait_for_completion_timeout(&cmp, msecs_to_jiffies(3000));10371037+10381038+ if (dma->device_is_tx_complete(dma_chan, cookie, NULL, NULL) != DMA_SUCCESS) {10391039+ dev_err(dev, "Self-test memset timed out\n");10401040+ err = -ENODEV;10411041+ goto free_resources;10421042+ }10431043+10441044+ for (i = 0; i < PAGE_SIZE/sizeof(u32); i++) {10451045+ u32 *ptr = page_address(dest);10461046+ if (ptr[i]) {10471047+ dev_err(dev, "Self-test memset failed compare\n");10481048+ err = -ENODEV;10491049+ goto free_resources;10501050+ }10511051+ }10521052+10531053+ /* test for non-zero parity sum */10541054+ xor_val_result = 0;10551055+ for (i = 0; i < IOAT_NUM_SRC_TEST + 1; i++)10561056+ dma_srcs[i] = dma_map_page(dev, xor_val_srcs[i], 0, PAGE_SIZE,10571057+ DMA_TO_DEVICE);10581058+ tx = dma->device_prep_dma_xor_val(dma_chan, dma_srcs,10591059+ IOAT_NUM_SRC_TEST + 1, PAGE_SIZE,10601060+ &xor_val_result, DMA_PREP_INTERRUPT);10611061+ if (!tx) {10621062+ dev_err(dev, "Self-test 2nd zero prep failed\n");10631063+ err = -ENODEV;10641064+ goto free_resources;10651065+ }10661066+10671067+ async_tx_ack(tx);10681068+ init_completion(&cmp);10691069+ tx->callback = ioat3_dma_test_callback;10701070+ tx->callback_param = &cmp;10711071+ cookie = tx->tx_submit(tx);10721072+ if (cookie < 0) {10731073+ dev_err(dev, "Self-test 2nd zero setup failed\n");10741074+ err = -ENODEV;10751075+ goto free_resources;10761076+ }10771077+ dma->device_issue_pending(dma_chan);10781078+10791079+ tmo = wait_for_completion_timeout(&cmp, msecs_to_jiffies(3000));10801080+10811081+ if (dma->device_is_tx_complete(dma_chan, cookie, NULL, NULL) != DMA_SUCCESS) {10821082+ dev_err(dev, "Self-test 2nd validate timed out\n");10831083+ err = -ENODEV;10841084+ goto free_resources;10851085+ }10861086+10871087+ if (xor_val_result != SUM_CHECK_P_RESULT) {10881088+ dev_err(dev, "Self-test validate failed compare\n");10891089+ err = -ENODEV;10901090+ goto free_resources;10911091+ }10921092+10931093+free_resources:10941094+ dma->device_free_chan_resources(dma_chan);10951095+out:10961096+ src_idx = IOAT_NUM_SRC_TEST;10971097+ while (src_idx--)10981098+ __free_page(xor_srcs[src_idx]);10991099+ __free_page(dest);11001100+ return err;11011101+}11021102+11031103+static int __devinit ioat3_dma_self_test(struct ioatdma_device *device)11041104+{11051105+ int rc = ioat_dma_self_test(device);11061106+11071107+ if (rc)11081108+ return rc;11091109+11101110+ rc = ioat_xor_val_self_test(device);11111111+ if (rc)11121112+ return rc;11131113+11141114+ return 0;11151115+}11161116+11171117+int __devinit ioat3_dma_probe(struct ioatdma_device *device, int dca)11181118+{11191119+ struct pci_dev *pdev = device->pdev;11201120+ struct dma_device *dma;11211121+ struct dma_chan *c;11221122+ struct ioat_chan_common *chan;11231123+ bool is_raid_device = false;11241124+ int err;11251125+ u16 dev_id;11261126+ u32 cap;11271127+11281128+ device->enumerate_channels = ioat2_enumerate_channels;11291129+ device->self_test = ioat3_dma_self_test;11301130+ dma = &device->common;11311131+ dma->device_prep_dma_memcpy = ioat2_dma_prep_memcpy_lock;11321132+ dma->device_issue_pending = ioat2_issue_pending;11331133+ dma->device_alloc_chan_resources = ioat2_alloc_chan_resources;11341134+ dma->device_free_chan_resources = ioat2_free_chan_resources;11351135+11361136+ dma_cap_set(DMA_INTERRUPT, dma->cap_mask);11371137+ dma->device_prep_dma_interrupt = ioat3_prep_interrupt_lock;11381138+11391139+ cap = readl(device->reg_base + IOAT_DMA_CAP_OFFSET);11401140+ if (cap & IOAT_CAP_XOR) {11411141+ is_raid_device = true;11421142+ dma->max_xor = 8;11431143+ dma->xor_align = 2;11441144+11451145+ dma_cap_set(DMA_XOR, dma->cap_mask);11461146+ dma->device_prep_dma_xor = ioat3_prep_xor;11471147+11481148+ dma_cap_set(DMA_XOR_VAL, dma->cap_mask);11491149+ dma->device_prep_dma_xor_val = ioat3_prep_xor_val;11501150+ }11511151+ if (cap & IOAT_CAP_PQ) {11521152+ is_raid_device = true;11531153+ dma_set_maxpq(dma, 8, 0);11541154+ dma->pq_align = 2;11551155+11561156+ dma_cap_set(DMA_PQ, dma->cap_mask);11571157+ dma->device_prep_dma_pq = ioat3_prep_pq;11581158+11591159+ dma_cap_set(DMA_PQ_VAL, dma->cap_mask);11601160+ dma->device_prep_dma_pq_val = ioat3_prep_pq_val;11611161+11621162+ if (!(cap & IOAT_CAP_XOR)) {11631163+ dma->max_xor = 8;11641164+ dma->xor_align = 2;11651165+11661166+ dma_cap_set(DMA_XOR, dma->cap_mask);11671167+ dma->device_prep_dma_xor = ioat3_prep_pqxor;11681168+11691169+ dma_cap_set(DMA_XOR_VAL, dma->cap_mask);11701170+ dma->device_prep_dma_xor_val = ioat3_prep_pqxor_val;11711171+ }11721172+ }11731173+ if (is_raid_device && (cap & IOAT_CAP_FILL_BLOCK)) {11741174+ dma_cap_set(DMA_MEMSET, dma->cap_mask);11751175+ dma->device_prep_dma_memset = ioat3_prep_memset_lock;11761176+ }11771177+11781178+11791179+ if (is_raid_device) {11801180+ dma->device_is_tx_complete = ioat3_is_complete;11811181+ device->cleanup_tasklet = ioat3_cleanup_tasklet;11821182+ device->timer_fn = ioat3_timer_event;11831183+ } else {11841184+ dma->device_is_tx_complete = ioat2_is_complete;11851185+ device->cleanup_tasklet = ioat2_cleanup_tasklet;11861186+ device->timer_fn = ioat2_timer_event;11871187+ }11881188+11891189+ /* -= IOAT ver.3 workarounds =- */11901190+ /* Write CHANERRMSK_INT with 3E07h to mask out the errors11911191+ * that can cause stability issues for IOAT ver.311921192+ */11931193+ pci_write_config_dword(pdev, IOAT_PCI_CHANERRMASK_INT_OFFSET, 0x3e07);11941194+11951195+ /* Clear DMAUNCERRSTS Cfg-Reg Parity Error status bit11961196+ * (workaround for spurious config parity error after restart)11971197+ */11981198+ pci_read_config_word(pdev, IOAT_PCI_DEVICE_ID_OFFSET, &dev_id);11991199+ if (dev_id == PCI_DEVICE_ID_INTEL_IOAT_TBG0)12001200+ pci_write_config_dword(pdev, IOAT_PCI_DMAUNCERRSTS_OFFSET, 0x10);12011201+12021202+ err = ioat_probe(device);12031203+ if (err)12041204+ return err;12051205+ ioat_set_tcp_copy_break(262144);12061206+12071207+ list_for_each_entry(c, &dma->channels, device_node) {12081208+ chan = to_chan_common(c);12091209+ writel(IOAT_DMA_DCA_ANY_CPU,12101210+ chan->reg_base + IOAT_DCACTRL_OFFSET);12111211+ }12121212+12131213+ err = ioat_register(device);12141214+ if (err)12151215+ return err;12161216+12171217+ ioat_kobject_add(device, &ioat2_ktype);12181218+12191219+ if (dca)12201220+ device->dca = ioat3_dca_init(pdev, device->reg_base);12211221+12221222+ return 0;12231223+}
+215
drivers/dma/ioat/hw.h
···11+/*22+ * Copyright(c) 2004 - 2009 Intel Corporation. All rights reserved.33+ *44+ * This program is free software; you can redistribute it and/or modify it55+ * under the terms of the GNU General Public License as published by the Free66+ * Software Foundation; either version 2 of the License, or (at your option)77+ * any later version.88+ *99+ * This program is distributed in the hope that it will be useful, but WITHOUT1010+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or1111+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for1212+ * more details.1313+ *1414+ * You should have received a copy of the GNU General Public License along with1515+ * this program; if not, write to the Free Software Foundation, Inc., 591616+ * Temple Place - Suite 330, Boston, MA 02111-1307, USA.1717+ *1818+ * The full GNU General Public License is included in this distribution in the1919+ * file called COPYING.2020+ */2121+#ifndef _IOAT_HW_H_2222+#define _IOAT_HW_H_2323+2424+/* PCI Configuration Space Values */2525+#define IOAT_PCI_VID 0x80862626+#define IOAT_MMIO_BAR 02727+2828+/* CB device ID's */2929+#define IOAT_PCI_DID_5000 0x1A383030+#define IOAT_PCI_DID_CNB 0x360B3131+#define IOAT_PCI_DID_SCNB 0x65FF3232+#define IOAT_PCI_DID_SNB 0x402F3333+3434+#define IOAT_PCI_RID 0x003535+#define IOAT_PCI_SVID 0x80863636+#define IOAT_PCI_SID 0x80863737+#define IOAT_VER_1_2 0x12 /* Version 1.2 */3838+#define IOAT_VER_2_0 0x20 /* Version 2.0 */3939+#define IOAT_VER_3_0 0x30 /* Version 3.0 */4040+#define IOAT_VER_3_2 0x32 /* Version 3.2 */4141+4242+struct ioat_dma_descriptor {4343+ uint32_t size;4444+ union {4545+ uint32_t ctl;4646+ struct {4747+ unsigned int int_en:1;4848+ unsigned int src_snoop_dis:1;4949+ unsigned int dest_snoop_dis:1;5050+ unsigned int compl_write:1;5151+ unsigned int fence:1;5252+ unsigned int null:1;5353+ unsigned int src_brk:1;5454+ unsigned int dest_brk:1;5555+ unsigned int bundle:1;5656+ unsigned int dest_dca:1;5757+ unsigned int hint:1;5858+ unsigned int rsvd2:13;5959+ #define IOAT_OP_COPY 0x006060+ unsigned int op:8;6161+ } ctl_f;6262+ };6363+ uint64_t src_addr;6464+ uint64_t dst_addr;6565+ uint64_t next;6666+ uint64_t rsv1;6767+ uint64_t rsv2;6868+ /* store some driver data in an unused portion of the descriptor */6969+ union {7070+ uint64_t user1;7171+ uint64_t tx_cnt;7272+ };7373+ uint64_t user2;7474+};7575+7676+struct ioat_fill_descriptor {7777+ uint32_t size;7878+ union {7979+ uint32_t ctl;8080+ struct {8181+ unsigned int int_en:1;8282+ unsigned int rsvd:1;8383+ unsigned int dest_snoop_dis:1;8484+ unsigned int compl_write:1;8585+ unsigned int fence:1;8686+ unsigned int rsvd2:2;8787+ unsigned int dest_brk:1;8888+ unsigned int bundle:1;8989+ unsigned int rsvd4:15;9090+ #define IOAT_OP_FILL 0x019191+ unsigned int op:8;9292+ } ctl_f;9393+ };9494+ uint64_t src_data;9595+ uint64_t dst_addr;9696+ uint64_t next;9797+ uint64_t rsv1;9898+ uint64_t next_dst_addr;9999+ uint64_t user1;100100+ uint64_t user2;101101+};102102+103103+struct ioat_xor_descriptor {104104+ uint32_t size;105105+ union {106106+ uint32_t ctl;107107+ struct {108108+ unsigned int int_en:1;109109+ unsigned int src_snoop_dis:1;110110+ unsigned int dest_snoop_dis:1;111111+ unsigned int compl_write:1;112112+ unsigned int fence:1;113113+ unsigned int src_cnt:3;114114+ unsigned int bundle:1;115115+ unsigned int dest_dca:1;116116+ unsigned int hint:1;117117+ unsigned int rsvd:13;118118+ #define IOAT_OP_XOR 0x87119119+ #define IOAT_OP_XOR_VAL 0x88120120+ unsigned int op:8;121121+ } ctl_f;122122+ };123123+ uint64_t src_addr;124124+ uint64_t dst_addr;125125+ uint64_t next;126126+ uint64_t src_addr2;127127+ uint64_t src_addr3;128128+ uint64_t src_addr4;129129+ uint64_t src_addr5;130130+};131131+132132+struct ioat_xor_ext_descriptor {133133+ uint64_t src_addr6;134134+ uint64_t src_addr7;135135+ uint64_t src_addr8;136136+ uint64_t next;137137+ uint64_t rsvd[4];138138+};139139+140140+struct ioat_pq_descriptor {141141+ uint32_t size;142142+ union {143143+ uint32_t ctl;144144+ struct {145145+ unsigned int int_en:1;146146+ unsigned int src_snoop_dis:1;147147+ unsigned int dest_snoop_dis:1;148148+ unsigned int compl_write:1;149149+ unsigned int fence:1;150150+ unsigned int src_cnt:3;151151+ unsigned int bundle:1;152152+ unsigned int dest_dca:1;153153+ unsigned int hint:1;154154+ unsigned int p_disable:1;155155+ unsigned int q_disable:1;156156+ unsigned int rsvd:11;157157+ #define IOAT_OP_PQ 0x89158158+ #define IOAT_OP_PQ_VAL 0x8a159159+ unsigned int op:8;160160+ } ctl_f;161161+ };162162+ uint64_t src_addr;163163+ uint64_t p_addr;164164+ uint64_t next;165165+ uint64_t src_addr2;166166+ uint64_t src_addr3;167167+ uint8_t coef[8];168168+ uint64_t q_addr;169169+};170170+171171+struct ioat_pq_ext_descriptor {172172+ uint64_t src_addr4;173173+ uint64_t src_addr5;174174+ uint64_t src_addr6;175175+ uint64_t next;176176+ uint64_t src_addr7;177177+ uint64_t src_addr8;178178+ uint64_t rsvd[2];179179+};180180+181181+struct ioat_pq_update_descriptor {182182+ uint32_t size;183183+ union {184184+ uint32_t ctl;185185+ struct {186186+ unsigned int int_en:1;187187+ unsigned int src_snoop_dis:1;188188+ unsigned int dest_snoop_dis:1;189189+ unsigned int compl_write:1;190190+ unsigned int fence:1;191191+ unsigned int src_cnt:3;192192+ unsigned int bundle:1;193193+ unsigned int dest_dca:1;194194+ unsigned int hint:1;195195+ unsigned int p_disable:1;196196+ unsigned int q_disable:1;197197+ unsigned int rsvd:3;198198+ unsigned int coef:8;199199+ #define IOAT_OP_PQ_UP 0x8b200200+ unsigned int op:8;201201+ } ctl_f;202202+ };203203+ uint64_t src_addr;204204+ uint64_t p_addr;205205+ uint64_t next;206206+ uint64_t src_addr2;207207+ uint64_t p_src;208208+ uint64_t q_src;209209+ uint64_t q_addr;210210+};211211+212212+struct ioat_raw_descriptor {213213+ uint64_t field[8];214214+};215215+#endif
+210
drivers/dma/ioat/pci.c
···11+/*22+ * Intel I/OAT DMA Linux driver33+ * Copyright(c) 2007 - 2009 Intel Corporation.44+ *55+ * This program is free software; you can redistribute it and/or modify it66+ * under the terms and conditions of the GNU General Public License,77+ * version 2, as published by the Free Software Foundation.88+ *99+ * This program is distributed in the hope that it will be useful, but WITHOUT1010+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or1111+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for1212+ * more details.1313+ *1414+ * You should have received a copy of the GNU General Public License along with1515+ * this program; if not, write to the Free Software Foundation, Inc.,1616+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.1717+ *1818+ * The full GNU General Public License is included in this distribution in1919+ * the file called "COPYING".2020+ *2121+ */2222+2323+/*2424+ * This driver supports an Intel I/OAT DMA engine, which does asynchronous2525+ * copy operations.2626+ */2727+2828+#include <linux/init.h>2929+#include <linux/module.h>3030+#include <linux/pci.h>3131+#include <linux/interrupt.h>3232+#include <linux/dca.h>3333+#include "dma.h"3434+#include "dma_v2.h"3535+#include "registers.h"3636+#include "hw.h"3737+3838+MODULE_VERSION(IOAT_DMA_VERSION);3939+MODULE_LICENSE("Dual BSD/GPL");4040+MODULE_AUTHOR("Intel Corporation");4141+4242+static struct pci_device_id ioat_pci_tbl[] = {4343+ /* I/OAT v1 platforms */4444+ { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_IOAT) },4545+ { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_IOAT_CNB) },4646+ { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_IOAT_SCNB) },4747+ { PCI_VDEVICE(UNISYS, PCI_DEVICE_ID_UNISYS_DMA_DIRECTOR) },4848+4949+ /* I/OAT v2 platforms */5050+ { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_IOAT_SNB) },5151+5252+ /* I/OAT v3 platforms */5353+ { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_IOAT_TBG0) },5454+ { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_IOAT_TBG1) },5555+ { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_IOAT_TBG2) },5656+ { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_IOAT_TBG3) },5757+ { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_IOAT_TBG4) },5858+ { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_IOAT_TBG5) },5959+ { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_IOAT_TBG6) },6060+ { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_IOAT_TBG7) },6161+6262+ /* I/OAT v3.2 platforms */6363+ { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_IOAT_JSF0) },6464+ { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_IOAT_JSF1) },6565+ { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_IOAT_JSF2) },6666+ { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_IOAT_JSF3) },6767+ { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_IOAT_JSF4) },6868+ { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_IOAT_JSF5) },6969+ { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_IOAT_JSF6) },7070+ { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_IOAT_JSF7) },7171+ { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_IOAT_JSF8) },7272+ { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_IOAT_JSF9) },7373+7474+ { 0, }7575+};7676+MODULE_DEVICE_TABLE(pci, ioat_pci_tbl);7777+7878+static int __devinit ioat_pci_probe(struct pci_dev *pdev,7979+ const struct pci_device_id *id);8080+static void __devexit ioat_remove(struct pci_dev *pdev);8181+8282+static int ioat_dca_enabled = 1;8383+module_param(ioat_dca_enabled, int, 0644);8484+MODULE_PARM_DESC(ioat_dca_enabled, "control support of dca service (default: 1)");8585+8686+struct kmem_cache *ioat2_cache;8787+8888+#define DRV_NAME "ioatdma"8989+9090+static struct pci_driver ioat_pci_driver = {9191+ .name = DRV_NAME,9292+ .id_table = ioat_pci_tbl,9393+ .probe = ioat_pci_probe,9494+ .remove = __devexit_p(ioat_remove),9595+};9696+9797+static struct ioatdma_device *9898+alloc_ioatdma(struct pci_dev *pdev, void __iomem *iobase)9999+{100100+ struct device *dev = &pdev->dev;101101+ struct ioatdma_device *d = devm_kzalloc(dev, sizeof(*d), GFP_KERNEL);102102+103103+ if (!d)104104+ return NULL;105105+ d->pdev = pdev;106106+ d->reg_base = iobase;107107+ return d;108108+}109109+110110+static int __devinit ioat_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)111111+{112112+ void __iomem * const *iomap;113113+ struct device *dev = &pdev->dev;114114+ struct ioatdma_device *device;115115+ int err;116116+117117+ err = pcim_enable_device(pdev);118118+ if (err)119119+ return err;120120+121121+ err = pcim_iomap_regions(pdev, 1 << IOAT_MMIO_BAR, DRV_NAME);122122+ if (err)123123+ return err;124124+ iomap = pcim_iomap_table(pdev);125125+ if (!iomap)126126+ return -ENOMEM;127127+128128+ err = pci_set_dma_mask(pdev, DMA_BIT_MASK(64));129129+ if (err)130130+ err = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));131131+ if (err)132132+ return err;133133+134134+ err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64));135135+ if (err)136136+ err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32));137137+ if (err)138138+ return err;139139+140140+ device = devm_kzalloc(dev, sizeof(*device), GFP_KERNEL);141141+ if (!device)142142+ return -ENOMEM;143143+144144+ pci_set_master(pdev);145145+146146+ device = alloc_ioatdma(pdev, iomap[IOAT_MMIO_BAR]);147147+ if (!device)148148+ return -ENOMEM;149149+ pci_set_drvdata(pdev, device);150150+151151+ device->version = readb(device->reg_base + IOAT_VER_OFFSET);152152+ if (device->version == IOAT_VER_1_2)153153+ err = ioat1_dma_probe(device, ioat_dca_enabled);154154+ else if (device->version == IOAT_VER_2_0)155155+ err = ioat2_dma_probe(device, ioat_dca_enabled);156156+ else if (device->version >= IOAT_VER_3_0)157157+ err = ioat3_dma_probe(device, ioat_dca_enabled);158158+ else159159+ return -ENODEV;160160+161161+ if (err) {162162+ dev_err(dev, "Intel(R) I/OAT DMA Engine init failed\n");163163+ return -ENODEV;164164+ }165165+166166+ return 0;167167+}168168+169169+static void __devexit ioat_remove(struct pci_dev *pdev)170170+{171171+ struct ioatdma_device *device = pci_get_drvdata(pdev);172172+173173+ if (!device)174174+ return;175175+176176+ dev_err(&pdev->dev, "Removing dma and dca services\n");177177+ if (device->dca) {178178+ unregister_dca_provider(device->dca, &pdev->dev);179179+ free_dca_provider(device->dca);180180+ device->dca = NULL;181181+ }182182+ ioat_dma_remove(device);183183+}184184+185185+static int __init ioat_init_module(void)186186+{187187+ int err;188188+189189+ pr_info("%s: Intel(R) QuickData Technology Driver %s\n",190190+ DRV_NAME, IOAT_DMA_VERSION);191191+192192+ ioat2_cache = kmem_cache_create("ioat2", sizeof(struct ioat_ring_ent),193193+ 0, SLAB_HWCACHE_ALIGN, NULL);194194+ if (!ioat2_cache)195195+ return -ENOMEM;196196+197197+ err = pci_register_driver(&ioat_pci_driver);198198+ if (err)199199+ kmem_cache_destroy(ioat2_cache);200200+201201+ return err;202202+}203203+module_init(ioat_init_module);204204+205205+static void __exit ioat_exit_module(void)206206+{207207+ pci_unregister_driver(&ioat_pci_driver);208208+ kmem_cache_destroy(ioat2_cache);209209+}210210+module_exit(ioat_exit_module);
+8-5
drivers/dma/ioat_dca.c
drivers/dma/ioat/dca.c
···3333#define cpu_physical_id(cpu) (cpuid_ebx(1) >> 24)3434#endif35353636-#include "ioatdma.h"3737-#include "ioatdma_registers.h"3636+#include "dma.h"3737+#include "registers.h"38383939/*4040 * Bit 7 of a tag map entry is the "valid" bit, if it is set then bits 0:6···242242};243243244244245245-struct dca_provider *ioat_dca_init(struct pci_dev *pdev, void __iomem *iobase)245245+struct dca_provider * __devinit246246+ioat_dca_init(struct pci_dev *pdev, void __iomem *iobase)246247{247248 struct dca_provider *dca;248249 struct ioat_dca_priv *ioatdca;···408407 return slots;409408}410409411411-struct dca_provider *ioat2_dca_init(struct pci_dev *pdev, void __iomem *iobase)410410+struct dca_provider * __devinit411411+ioat2_dca_init(struct pci_dev *pdev, void __iomem *iobase)412412{413413 struct dca_provider *dca;414414 struct ioat_dca_priv *ioatdca;···604602 return slots;605603}606604607607-struct dca_provider *ioat3_dca_init(struct pci_dev *pdev, void __iomem *iobase)605605+struct dca_provider * __devinit606606+ioat3_dca_init(struct pci_dev *pdev, void __iomem *iobase)608607{609608 struct dca_provider *dca;610609 struct ioat_dca_priv *ioatdca;
-1741
drivers/dma/ioat_dma.c
···11-/*22- * Intel I/OAT DMA Linux driver33- * Copyright(c) 2004 - 2009 Intel Corporation.44- *55- * This program is free software; you can redistribute it and/or modify it66- * under the terms and conditions of the GNU General Public License,77- * version 2, as published by the Free Software Foundation.88- *99- * This program is distributed in the hope that it will be useful, but WITHOUT1010- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or1111- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for1212- * more details.1313- *1414- * You should have received a copy of the GNU General Public License along with1515- * this program; if not, write to the Free Software Foundation, Inc.,1616- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.1717- *1818- * The full GNU General Public License is included in this distribution in1919- * the file called "COPYING".2020- *2121- */2222-2323-/*2424- * This driver supports an Intel I/OAT DMA engine, which does asynchronous2525- * copy operations.2626- */2727-2828-#include <linux/init.h>2929-#include <linux/module.h>3030-#include <linux/pci.h>3131-#include <linux/interrupt.h>3232-#include <linux/dmaengine.h>3333-#include <linux/delay.h>3434-#include <linux/dma-mapping.h>3535-#include <linux/workqueue.h>3636-#include <linux/i7300_idle.h>3737-#include "ioatdma.h"3838-#include "ioatdma_registers.h"3939-#include "ioatdma_hw.h"4040-4141-#define to_ioat_chan(chan) container_of(chan, struct ioat_dma_chan, common)4242-#define to_ioatdma_device(dev) container_of(dev, struct ioatdma_device, common)4343-#define to_ioat_desc(lh) container_of(lh, struct ioat_desc_sw, node)4444-#define tx_to_ioat_desc(tx) container_of(tx, struct ioat_desc_sw, async_tx)4545-4646-#define chan_num(ch) ((int)((ch)->reg_base - (ch)->device->reg_base) / 0x80)4747-static int ioat_pending_level = 4;4848-module_param(ioat_pending_level, int, 0644);4949-MODULE_PARM_DESC(ioat_pending_level,5050- "high-water mark for pushing ioat descriptors (default: 4)");5151-5252-#define RESET_DELAY msecs_to_jiffies(100)5353-#define WATCHDOG_DELAY round_jiffies(msecs_to_jiffies(2000))5454-static void ioat_dma_chan_reset_part2(struct work_struct *work);5555-static void ioat_dma_chan_watchdog(struct work_struct *work);5656-5757-/*5858- * workaround for IOAT ver.3.0 null descriptor issue5959- * (channel returns error when size is 0)6060- */6161-#define NULL_DESC_BUFFER_SIZE 16262-6363-/* internal functions */6464-static void ioat_dma_start_null_desc(struct ioat_dma_chan *ioat_chan);6565-static void ioat_dma_memcpy_cleanup(struct ioat_dma_chan *ioat_chan);6666-6767-static struct ioat_desc_sw *6868-ioat1_dma_get_next_descriptor(struct ioat_dma_chan *ioat_chan);6969-static struct ioat_desc_sw *7070-ioat2_dma_get_next_descriptor(struct ioat_dma_chan *ioat_chan);7171-7272-static inline struct ioat_dma_chan *ioat_lookup_chan_by_index(7373- struct ioatdma_device *device,7474- int index)7575-{7676- return device->idx[index];7777-}7878-7979-/**8080- * ioat_dma_do_interrupt - handler used for single vector interrupt mode8181- * @irq: interrupt id8282- * @data: interrupt data8383- */8484-static irqreturn_t ioat_dma_do_interrupt(int irq, void *data)8585-{8686- struct ioatdma_device *instance = data;8787- struct ioat_dma_chan *ioat_chan;8888- unsigned long attnstatus;8989- int bit;9090- u8 intrctrl;9191-9292- intrctrl = readb(instance->reg_base + IOAT_INTRCTRL_OFFSET);9393-9494- if (!(intrctrl & IOAT_INTRCTRL_MASTER_INT_EN))9595- return IRQ_NONE;9696-9797- if (!(intrctrl & IOAT_INTRCTRL_INT_STATUS)) {9898- writeb(intrctrl, instance->reg_base + IOAT_INTRCTRL_OFFSET);9999- return IRQ_NONE;100100- }101101-102102- attnstatus = readl(instance->reg_base + IOAT_ATTNSTATUS_OFFSET);103103- for_each_bit(bit, &attnstatus, BITS_PER_LONG) {104104- ioat_chan = ioat_lookup_chan_by_index(instance, bit);105105- tasklet_schedule(&ioat_chan->cleanup_task);106106- }107107-108108- writeb(intrctrl, instance->reg_base + IOAT_INTRCTRL_OFFSET);109109- return IRQ_HANDLED;110110-}111111-112112-/**113113- * ioat_dma_do_interrupt_msix - handler used for vector-per-channel interrupt mode114114- * @irq: interrupt id115115- * @data: interrupt data116116- */117117-static irqreturn_t ioat_dma_do_interrupt_msix(int irq, void *data)118118-{119119- struct ioat_dma_chan *ioat_chan = data;120120-121121- tasklet_schedule(&ioat_chan->cleanup_task);122122-123123- return IRQ_HANDLED;124124-}125125-126126-static void ioat_dma_cleanup_tasklet(unsigned long data);127127-128128-/**129129- * ioat_dma_enumerate_channels - find and initialize the device's channels130130- * @device: the device to be enumerated131131- */132132-static int ioat_dma_enumerate_channels(struct ioatdma_device *device)133133-{134134- u8 xfercap_scale;135135- u32 xfercap;136136- int i;137137- struct ioat_dma_chan *ioat_chan;138138-139139- /*140140- * IOAT ver.3 workarounds141141- */142142- if (device->version == IOAT_VER_3_0) {143143- u32 chan_err_mask;144144- u16 dev_id;145145- u32 dmauncerrsts;146146-147147- /*148148- * Write CHANERRMSK_INT with 3E07h to mask out the errors149149- * that can cause stability issues for IOAT ver.3150150- */151151- chan_err_mask = 0x3E07;152152- pci_write_config_dword(device->pdev,153153- IOAT_PCI_CHANERRMASK_INT_OFFSET,154154- chan_err_mask);155155-156156- /*157157- * Clear DMAUNCERRSTS Cfg-Reg Parity Error status bit158158- * (workaround for spurious config parity error after restart)159159- */160160- pci_read_config_word(device->pdev,161161- IOAT_PCI_DEVICE_ID_OFFSET,162162- &dev_id);163163- if (dev_id == PCI_DEVICE_ID_INTEL_IOAT_TBG0) {164164- dmauncerrsts = 0x10;165165- pci_write_config_dword(device->pdev,166166- IOAT_PCI_DMAUNCERRSTS_OFFSET,167167- dmauncerrsts);168168- }169169- }170170-171171- device->common.chancnt = readb(device->reg_base + IOAT_CHANCNT_OFFSET);172172- xfercap_scale = readb(device->reg_base + IOAT_XFERCAP_OFFSET);173173- xfercap = (xfercap_scale == 0 ? -1 : (1UL << xfercap_scale));174174-175175-#ifdef CONFIG_I7300_IDLE_IOAT_CHANNEL176176- if (i7300_idle_platform_probe(NULL, NULL, 1) == 0) {177177- device->common.chancnt--;178178- }179179-#endif180180- for (i = 0; i < device->common.chancnt; i++) {181181- ioat_chan = kzalloc(sizeof(*ioat_chan), GFP_KERNEL);182182- if (!ioat_chan) {183183- device->common.chancnt = i;184184- break;185185- }186186-187187- ioat_chan->device = device;188188- ioat_chan->reg_base = device->reg_base + (0x80 * (i + 1));189189- ioat_chan->xfercap = xfercap;190190- ioat_chan->desccount = 0;191191- INIT_DELAYED_WORK(&ioat_chan->work, ioat_dma_chan_reset_part2);192192- if (ioat_chan->device->version == IOAT_VER_2_0)193193- writel(IOAT_DCACTRL_CMPL_WRITE_ENABLE |194194- IOAT_DMA_DCA_ANY_CPU,195195- ioat_chan->reg_base + IOAT_DCACTRL_OFFSET);196196- else if (ioat_chan->device->version == IOAT_VER_3_0)197197- writel(IOAT_DMA_DCA_ANY_CPU,198198- ioat_chan->reg_base + IOAT_DCACTRL_OFFSET);199199- spin_lock_init(&ioat_chan->cleanup_lock);200200- spin_lock_init(&ioat_chan->desc_lock);201201- INIT_LIST_HEAD(&ioat_chan->free_desc);202202- INIT_LIST_HEAD(&ioat_chan->used_desc);203203- /* This should be made common somewhere in dmaengine.c */204204- ioat_chan->common.device = &device->common;205205- list_add_tail(&ioat_chan->common.device_node,206206- &device->common.channels);207207- device->idx[i] = ioat_chan;208208- tasklet_init(&ioat_chan->cleanup_task,209209- ioat_dma_cleanup_tasklet,210210- (unsigned long) ioat_chan);211211- tasklet_disable(&ioat_chan->cleanup_task);212212- }213213- return device->common.chancnt;214214-}215215-216216-/**217217- * ioat_dma_memcpy_issue_pending - push potentially unrecognized appended218218- * descriptors to hw219219- * @chan: DMA channel handle220220- */221221-static inline void __ioat1_dma_memcpy_issue_pending(222222- struct ioat_dma_chan *ioat_chan)223223-{224224- ioat_chan->pending = 0;225225- writeb(IOAT_CHANCMD_APPEND, ioat_chan->reg_base + IOAT1_CHANCMD_OFFSET);226226-}227227-228228-static void ioat1_dma_memcpy_issue_pending(struct dma_chan *chan)229229-{230230- struct ioat_dma_chan *ioat_chan = to_ioat_chan(chan);231231-232232- if (ioat_chan->pending > 0) {233233- spin_lock_bh(&ioat_chan->desc_lock);234234- __ioat1_dma_memcpy_issue_pending(ioat_chan);235235- spin_unlock_bh(&ioat_chan->desc_lock);236236- }237237-}238238-239239-static inline void __ioat2_dma_memcpy_issue_pending(240240- struct ioat_dma_chan *ioat_chan)241241-{242242- ioat_chan->pending = 0;243243- writew(ioat_chan->dmacount,244244- ioat_chan->reg_base + IOAT_CHAN_DMACOUNT_OFFSET);245245-}246246-247247-static void ioat2_dma_memcpy_issue_pending(struct dma_chan *chan)248248-{249249- struct ioat_dma_chan *ioat_chan = to_ioat_chan(chan);250250-251251- if (ioat_chan->pending > 0) {252252- spin_lock_bh(&ioat_chan->desc_lock);253253- __ioat2_dma_memcpy_issue_pending(ioat_chan);254254- spin_unlock_bh(&ioat_chan->desc_lock);255255- }256256-}257257-258258-259259-/**260260- * ioat_dma_chan_reset_part2 - reinit the channel after a reset261261- */262262-static void ioat_dma_chan_reset_part2(struct work_struct *work)263263-{264264- struct ioat_dma_chan *ioat_chan =265265- container_of(work, struct ioat_dma_chan, work.work);266266- struct ioat_desc_sw *desc;267267-268268- spin_lock_bh(&ioat_chan->cleanup_lock);269269- spin_lock_bh(&ioat_chan->desc_lock);270270-271271- ioat_chan->completion_virt->low = 0;272272- ioat_chan->completion_virt->high = 0;273273- ioat_chan->pending = 0;274274-275275- /*276276- * count the descriptors waiting, and be sure to do it277277- * right for both the CB1 line and the CB2 ring278278- */279279- ioat_chan->dmacount = 0;280280- if (ioat_chan->used_desc.prev) {281281- desc = to_ioat_desc(ioat_chan->used_desc.prev);282282- do {283283- ioat_chan->dmacount++;284284- desc = to_ioat_desc(desc->node.next);285285- } while (&desc->node != ioat_chan->used_desc.next);286286- }287287-288288- /*289289- * write the new starting descriptor address290290- * this puts channel engine into ARMED state291291- */292292- desc = to_ioat_desc(ioat_chan->used_desc.prev);293293- switch (ioat_chan->device->version) {294294- case IOAT_VER_1_2:295295- writel(((u64) desc->async_tx.phys) & 0x00000000FFFFFFFF,296296- ioat_chan->reg_base + IOAT1_CHAINADDR_OFFSET_LOW);297297- writel(((u64) desc->async_tx.phys) >> 32,298298- ioat_chan->reg_base + IOAT1_CHAINADDR_OFFSET_HIGH);299299-300300- writeb(IOAT_CHANCMD_START, ioat_chan->reg_base301301- + IOAT_CHANCMD_OFFSET(ioat_chan->device->version));302302- break;303303- case IOAT_VER_2_0:304304- writel(((u64) desc->async_tx.phys) & 0x00000000FFFFFFFF,305305- ioat_chan->reg_base + IOAT2_CHAINADDR_OFFSET_LOW);306306- writel(((u64) desc->async_tx.phys) >> 32,307307- ioat_chan->reg_base + IOAT2_CHAINADDR_OFFSET_HIGH);308308-309309- /* tell the engine to go with what's left to be done */310310- writew(ioat_chan->dmacount,311311- ioat_chan->reg_base + IOAT_CHAN_DMACOUNT_OFFSET);312312-313313- break;314314- }315315- dev_err(&ioat_chan->device->pdev->dev,316316- "chan%d reset - %d descs waiting, %d total desc\n",317317- chan_num(ioat_chan), ioat_chan->dmacount, ioat_chan->desccount);318318-319319- spin_unlock_bh(&ioat_chan->desc_lock);320320- spin_unlock_bh(&ioat_chan->cleanup_lock);321321-}322322-323323-/**324324- * ioat_dma_reset_channel - restart a channel325325- * @ioat_chan: IOAT DMA channel handle326326- */327327-static void ioat_dma_reset_channel(struct ioat_dma_chan *ioat_chan)328328-{329329- u32 chansts, chanerr;330330-331331- if (!ioat_chan->used_desc.prev)332332- return;333333-334334- chanerr = readl(ioat_chan->reg_base + IOAT_CHANERR_OFFSET);335335- chansts = (ioat_chan->completion_virt->low336336- & IOAT_CHANSTS_DMA_TRANSFER_STATUS);337337- if (chanerr) {338338- dev_err(&ioat_chan->device->pdev->dev,339339- "chan%d, CHANSTS = 0x%08x CHANERR = 0x%04x, clearing\n",340340- chan_num(ioat_chan), chansts, chanerr);341341- writel(chanerr, ioat_chan->reg_base + IOAT_CHANERR_OFFSET);342342- }343343-344344- /*345345- * whack it upside the head with a reset346346- * and wait for things to settle out.347347- * force the pending count to a really big negative348348- * to make sure no one forces an issue_pending349349- * while we're waiting.350350- */351351-352352- spin_lock_bh(&ioat_chan->desc_lock);353353- ioat_chan->pending = INT_MIN;354354- writeb(IOAT_CHANCMD_RESET,355355- ioat_chan->reg_base356356- + IOAT_CHANCMD_OFFSET(ioat_chan->device->version));357357- spin_unlock_bh(&ioat_chan->desc_lock);358358-359359- /* schedule the 2nd half instead of sleeping a long time */360360- schedule_delayed_work(&ioat_chan->work, RESET_DELAY);361361-}362362-363363-/**364364- * ioat_dma_chan_watchdog - watch for stuck channels365365- */366366-static void ioat_dma_chan_watchdog(struct work_struct *work)367367-{368368- struct ioatdma_device *device =369369- container_of(work, struct ioatdma_device, work.work);370370- struct ioat_dma_chan *ioat_chan;371371- int i;372372-373373- union {374374- u64 full;375375- struct {376376- u32 low;377377- u32 high;378378- };379379- } completion_hw;380380- unsigned long compl_desc_addr_hw;381381-382382- for (i = 0; i < device->common.chancnt; i++) {383383- ioat_chan = ioat_lookup_chan_by_index(device, i);384384-385385- if (ioat_chan->device->version == IOAT_VER_1_2386386- /* have we started processing anything yet */387387- && ioat_chan->last_completion388388- /* have we completed any since last watchdog cycle? */389389- && (ioat_chan->last_completion ==390390- ioat_chan->watchdog_completion)391391- /* has TCP stuck on one cookie since last watchdog? */392392- && (ioat_chan->watchdog_tcp_cookie ==393393- ioat_chan->watchdog_last_tcp_cookie)394394- && (ioat_chan->watchdog_tcp_cookie !=395395- ioat_chan->completed_cookie)396396- /* is there something in the chain to be processed? */397397- /* CB1 chain always has at least the last one processed */398398- && (ioat_chan->used_desc.prev != ioat_chan->used_desc.next)399399- && ioat_chan->pending == 0) {400400-401401- /*402402- * check CHANSTS register for completed403403- * descriptor address.404404- * if it is different than completion writeback,405405- * it is not zero406406- * and it has changed since the last watchdog407407- * we can assume that channel408408- * is still working correctly409409- * and the problem is in completion writeback.410410- * update completion writeback411411- * with actual CHANSTS value412412- * else413413- * try resetting the channel414414- */415415-416416- completion_hw.low = readl(ioat_chan->reg_base +417417- IOAT_CHANSTS_OFFSET_LOW(ioat_chan->device->version));418418- completion_hw.high = readl(ioat_chan->reg_base +419419- IOAT_CHANSTS_OFFSET_HIGH(ioat_chan->device->version));420420-#if (BITS_PER_LONG == 64)421421- compl_desc_addr_hw =422422- completion_hw.full423423- & IOAT_CHANSTS_COMPLETED_DESCRIPTOR_ADDR;424424-#else425425- compl_desc_addr_hw =426426- completion_hw.low & IOAT_LOW_COMPLETION_MASK;427427-#endif428428-429429- if ((compl_desc_addr_hw != 0)430430- && (compl_desc_addr_hw != ioat_chan->watchdog_completion)431431- && (compl_desc_addr_hw != ioat_chan->last_compl_desc_addr_hw)) {432432- ioat_chan->last_compl_desc_addr_hw = compl_desc_addr_hw;433433- ioat_chan->completion_virt->low = completion_hw.low;434434- ioat_chan->completion_virt->high = completion_hw.high;435435- } else {436436- ioat_dma_reset_channel(ioat_chan);437437- ioat_chan->watchdog_completion = 0;438438- ioat_chan->last_compl_desc_addr_hw = 0;439439- }440440-441441- /*442442- * for version 2.0 if there are descriptors yet to be processed443443- * and the last completed hasn't changed since the last watchdog444444- * if they haven't hit the pending level445445- * issue the pending to push them through446446- * else447447- * try resetting the channel448448- */449449- } else if (ioat_chan->device->version == IOAT_VER_2_0450450- && ioat_chan->used_desc.prev451451- && ioat_chan->last_completion452452- && ioat_chan->last_completion == ioat_chan->watchdog_completion) {453453-454454- if (ioat_chan->pending < ioat_pending_level)455455- ioat2_dma_memcpy_issue_pending(&ioat_chan->common);456456- else {457457- ioat_dma_reset_channel(ioat_chan);458458- ioat_chan->watchdog_completion = 0;459459- }460460- } else {461461- ioat_chan->last_compl_desc_addr_hw = 0;462462- ioat_chan->watchdog_completion463463- = ioat_chan->last_completion;464464- }465465-466466- ioat_chan->watchdog_last_tcp_cookie =467467- ioat_chan->watchdog_tcp_cookie;468468- }469469-470470- schedule_delayed_work(&device->work, WATCHDOG_DELAY);471471-}472472-473473-static dma_cookie_t ioat1_tx_submit(struct dma_async_tx_descriptor *tx)474474-{475475- struct ioat_dma_chan *ioat_chan = to_ioat_chan(tx->chan);476476- struct ioat_desc_sw *first = tx_to_ioat_desc(tx);477477- struct ioat_desc_sw *prev, *new;478478- struct ioat_dma_descriptor *hw;479479- dma_cookie_t cookie;480480- LIST_HEAD(new_chain);481481- u32 copy;482482- size_t len;483483- dma_addr_t src, dst;484484- unsigned long orig_flags;485485- unsigned int desc_count = 0;486486-487487- /* src and dest and len are stored in the initial descriptor */488488- len = first->len;489489- src = first->src;490490- dst = first->dst;491491- orig_flags = first->async_tx.flags;492492- new = first;493493-494494- spin_lock_bh(&ioat_chan->desc_lock);495495- prev = to_ioat_desc(ioat_chan->used_desc.prev);496496- prefetch(prev->hw);497497- do {498498- copy = min_t(size_t, len, ioat_chan->xfercap);499499-500500- async_tx_ack(&new->async_tx);501501-502502- hw = new->hw;503503- hw->size = copy;504504- hw->ctl = 0;505505- hw->src_addr = src;506506- hw->dst_addr = dst;507507- hw->next = 0;508508-509509- /* chain together the physical address list for the HW */510510- wmb();511511- prev->hw->next = (u64) new->async_tx.phys;512512-513513- len -= copy;514514- dst += copy;515515- src += copy;516516-517517- list_add_tail(&new->node, &new_chain);518518- desc_count++;519519- prev = new;520520- } while (len && (new = ioat1_dma_get_next_descriptor(ioat_chan)));521521-522522- if (!new) {523523- dev_err(&ioat_chan->device->pdev->dev,524524- "tx submit failed\n");525525- spin_unlock_bh(&ioat_chan->desc_lock);526526- return -ENOMEM;527527- }528528-529529- hw->ctl = IOAT_DMA_DESCRIPTOR_CTL_CP_STS;530530- if (first->async_tx.callback) {531531- hw->ctl |= IOAT_DMA_DESCRIPTOR_CTL_INT_GN;532532- if (first != new) {533533- /* move callback into to last desc */534534- new->async_tx.callback = first->async_tx.callback;535535- new->async_tx.callback_param536536- = first->async_tx.callback_param;537537- first->async_tx.callback = NULL;538538- first->async_tx.callback_param = NULL;539539- }540540- }541541-542542- new->tx_cnt = desc_count;543543- new->async_tx.flags = orig_flags; /* client is in control of this ack */544544-545545- /* store the original values for use in later cleanup */546546- if (new != first) {547547- new->src = first->src;548548- new->dst = first->dst;549549- new->len = first->len;550550- }551551-552552- /* cookie incr and addition to used_list must be atomic */553553- cookie = ioat_chan->common.cookie;554554- cookie++;555555- if (cookie < 0)556556- cookie = 1;557557- ioat_chan->common.cookie = new->async_tx.cookie = cookie;558558-559559- /* write address into NextDescriptor field of last desc in chain */560560- to_ioat_desc(ioat_chan->used_desc.prev)->hw->next =561561- first->async_tx.phys;562562- list_splice_tail(&new_chain, &ioat_chan->used_desc);563563-564564- ioat_chan->dmacount += desc_count;565565- ioat_chan->pending += desc_count;566566- if (ioat_chan->pending >= ioat_pending_level)567567- __ioat1_dma_memcpy_issue_pending(ioat_chan);568568- spin_unlock_bh(&ioat_chan->desc_lock);569569-570570- return cookie;571571-}572572-573573-static dma_cookie_t ioat2_tx_submit(struct dma_async_tx_descriptor *tx)574574-{575575- struct ioat_dma_chan *ioat_chan = to_ioat_chan(tx->chan);576576- struct ioat_desc_sw *first = tx_to_ioat_desc(tx);577577- struct ioat_desc_sw *new;578578- struct ioat_dma_descriptor *hw;579579- dma_cookie_t cookie;580580- u32 copy;581581- size_t len;582582- dma_addr_t src, dst;583583- unsigned long orig_flags;584584- unsigned int desc_count = 0;585585-586586- /* src and dest and len are stored in the initial descriptor */587587- len = first->len;588588- src = first->src;589589- dst = first->dst;590590- orig_flags = first->async_tx.flags;591591- new = first;592592-593593- /*594594- * ioat_chan->desc_lock is still in force in version 2 path595595- * it gets unlocked at end of this function596596- */597597- do {598598- copy = min_t(size_t, len, ioat_chan->xfercap);599599-600600- async_tx_ack(&new->async_tx);601601-602602- hw = new->hw;603603- hw->size = copy;604604- hw->ctl = 0;605605- hw->src_addr = src;606606- hw->dst_addr = dst;607607-608608- len -= copy;609609- dst += copy;610610- src += copy;611611- desc_count++;612612- } while (len && (new = ioat2_dma_get_next_descriptor(ioat_chan)));613613-614614- if (!new) {615615- dev_err(&ioat_chan->device->pdev->dev,616616- "tx submit failed\n");617617- spin_unlock_bh(&ioat_chan->desc_lock);618618- return -ENOMEM;619619- }620620-621621- hw->ctl |= IOAT_DMA_DESCRIPTOR_CTL_CP_STS;622622- if (first->async_tx.callback) {623623- hw->ctl |= IOAT_DMA_DESCRIPTOR_CTL_INT_GN;624624- if (first != new) {625625- /* move callback into to last desc */626626- new->async_tx.callback = first->async_tx.callback;627627- new->async_tx.callback_param628628- = first->async_tx.callback_param;629629- first->async_tx.callback = NULL;630630- first->async_tx.callback_param = NULL;631631- }632632- }633633-634634- new->tx_cnt = desc_count;635635- new->async_tx.flags = orig_flags; /* client is in control of this ack */636636-637637- /* store the original values for use in later cleanup */638638- if (new != first) {639639- new->src = first->src;640640- new->dst = first->dst;641641- new->len = first->len;642642- }643643-644644- /* cookie incr and addition to used_list must be atomic */645645- cookie = ioat_chan->common.cookie;646646- cookie++;647647- if (cookie < 0)648648- cookie = 1;649649- ioat_chan->common.cookie = new->async_tx.cookie = cookie;650650-651651- ioat_chan->dmacount += desc_count;652652- ioat_chan->pending += desc_count;653653- if (ioat_chan->pending >= ioat_pending_level)654654- __ioat2_dma_memcpy_issue_pending(ioat_chan);655655- spin_unlock_bh(&ioat_chan->desc_lock);656656-657657- return cookie;658658-}659659-660660-/**661661- * ioat_dma_alloc_descriptor - allocate and return a sw and hw descriptor pair662662- * @ioat_chan: the channel supplying the memory pool for the descriptors663663- * @flags: allocation flags664664- */665665-static struct ioat_desc_sw *ioat_dma_alloc_descriptor(666666- struct ioat_dma_chan *ioat_chan,667667- gfp_t flags)668668-{669669- struct ioat_dma_descriptor *desc;670670- struct ioat_desc_sw *desc_sw;671671- struct ioatdma_device *ioatdma_device;672672- dma_addr_t phys;673673-674674- ioatdma_device = to_ioatdma_device(ioat_chan->common.device);675675- desc = pci_pool_alloc(ioatdma_device->dma_pool, flags, &phys);676676- if (unlikely(!desc))677677- return NULL;678678-679679- desc_sw = kzalloc(sizeof(*desc_sw), flags);680680- if (unlikely(!desc_sw)) {681681- pci_pool_free(ioatdma_device->dma_pool, desc, phys);682682- return NULL;683683- }684684-685685- memset(desc, 0, sizeof(*desc));686686- dma_async_tx_descriptor_init(&desc_sw->async_tx, &ioat_chan->common);687687- switch (ioat_chan->device->version) {688688- case IOAT_VER_1_2:689689- desc_sw->async_tx.tx_submit = ioat1_tx_submit;690690- break;691691- case IOAT_VER_2_0:692692- case IOAT_VER_3_0:693693- desc_sw->async_tx.tx_submit = ioat2_tx_submit;694694- break;695695- }696696-697697- desc_sw->hw = desc;698698- desc_sw->async_tx.phys = phys;699699-700700- return desc_sw;701701-}702702-703703-static int ioat_initial_desc_count = 256;704704-module_param(ioat_initial_desc_count, int, 0644);705705-MODULE_PARM_DESC(ioat_initial_desc_count,706706- "initial descriptors per channel (default: 256)");707707-708708-/**709709- * ioat2_dma_massage_chan_desc - link the descriptors into a circle710710- * @ioat_chan: the channel to be massaged711711- */712712-static void ioat2_dma_massage_chan_desc(struct ioat_dma_chan *ioat_chan)713713-{714714- struct ioat_desc_sw *desc, *_desc;715715-716716- /* setup used_desc */717717- ioat_chan->used_desc.next = ioat_chan->free_desc.next;718718- ioat_chan->used_desc.prev = NULL;719719-720720- /* pull free_desc out of the circle so that every node is a hw721721- * descriptor, but leave it pointing to the list722722- */723723- ioat_chan->free_desc.prev->next = ioat_chan->free_desc.next;724724- ioat_chan->free_desc.next->prev = ioat_chan->free_desc.prev;725725-726726- /* circle link the hw descriptors */727727- desc = to_ioat_desc(ioat_chan->free_desc.next);728728- desc->hw->next = to_ioat_desc(desc->node.next)->async_tx.phys;729729- list_for_each_entry_safe(desc, _desc, ioat_chan->free_desc.next, node) {730730- desc->hw->next = to_ioat_desc(desc->node.next)->async_tx.phys;731731- }732732-}733733-734734-/**735735- * ioat_dma_alloc_chan_resources - returns the number of allocated descriptors736736- * @chan: the channel to be filled out737737- */738738-static int ioat_dma_alloc_chan_resources(struct dma_chan *chan)739739-{740740- struct ioat_dma_chan *ioat_chan = to_ioat_chan(chan);741741- struct ioat_desc_sw *desc;742742- u16 chanctrl;743743- u32 chanerr;744744- int i;745745- LIST_HEAD(tmp_list);746746-747747- /* have we already been set up? */748748- if (!list_empty(&ioat_chan->free_desc))749749- return ioat_chan->desccount;750750-751751- /* Setup register to interrupt and write completion status on error */752752- chanctrl = IOAT_CHANCTRL_ERR_INT_EN |753753- IOAT_CHANCTRL_ANY_ERR_ABORT_EN |754754- IOAT_CHANCTRL_ERR_COMPLETION_EN;755755- writew(chanctrl, ioat_chan->reg_base + IOAT_CHANCTRL_OFFSET);756756-757757- chanerr = readl(ioat_chan->reg_base + IOAT_CHANERR_OFFSET);758758- if (chanerr) {759759- dev_err(&ioat_chan->device->pdev->dev,760760- "CHANERR = %x, clearing\n", chanerr);761761- writel(chanerr, ioat_chan->reg_base + IOAT_CHANERR_OFFSET);762762- }763763-764764- /* Allocate descriptors */765765- for (i = 0; i < ioat_initial_desc_count; i++) {766766- desc = ioat_dma_alloc_descriptor(ioat_chan, GFP_KERNEL);767767- if (!desc) {768768- dev_err(&ioat_chan->device->pdev->dev,769769- "Only %d initial descriptors\n", i);770770- break;771771- }772772- list_add_tail(&desc->node, &tmp_list);773773- }774774- spin_lock_bh(&ioat_chan->desc_lock);775775- ioat_chan->desccount = i;776776- list_splice(&tmp_list, &ioat_chan->free_desc);777777- if (ioat_chan->device->version != IOAT_VER_1_2)778778- ioat2_dma_massage_chan_desc(ioat_chan);779779- spin_unlock_bh(&ioat_chan->desc_lock);780780-781781- /* allocate a completion writeback area */782782- /* doing 2 32bit writes to mmio since 1 64b write doesn't work */783783- ioat_chan->completion_virt =784784- pci_pool_alloc(ioat_chan->device->completion_pool,785785- GFP_KERNEL,786786- &ioat_chan->completion_addr);787787- memset(ioat_chan->completion_virt, 0,788788- sizeof(*ioat_chan->completion_virt));789789- writel(((u64) ioat_chan->completion_addr) & 0x00000000FFFFFFFF,790790- ioat_chan->reg_base + IOAT_CHANCMP_OFFSET_LOW);791791- writel(((u64) ioat_chan->completion_addr) >> 32,792792- ioat_chan->reg_base + IOAT_CHANCMP_OFFSET_HIGH);793793-794794- tasklet_enable(&ioat_chan->cleanup_task);795795- ioat_dma_start_null_desc(ioat_chan); /* give chain to dma device */796796- return ioat_chan->desccount;797797-}798798-799799-/**800800- * ioat_dma_free_chan_resources - release all the descriptors801801- * @chan: the channel to be cleaned802802- */803803-static void ioat_dma_free_chan_resources(struct dma_chan *chan)804804-{805805- struct ioat_dma_chan *ioat_chan = to_ioat_chan(chan);806806- struct ioatdma_device *ioatdma_device = to_ioatdma_device(chan->device);807807- struct ioat_desc_sw *desc, *_desc;808808- int in_use_descs = 0;809809-810810- /* Before freeing channel resources first check811811- * if they have been previously allocated for this channel.812812- */813813- if (ioat_chan->desccount == 0)814814- return;815815-816816- tasklet_disable(&ioat_chan->cleanup_task);817817- ioat_dma_memcpy_cleanup(ioat_chan);818818-819819- /* Delay 100ms after reset to allow internal DMA logic to quiesce820820- * before removing DMA descriptor resources.821821- */822822- writeb(IOAT_CHANCMD_RESET,823823- ioat_chan->reg_base824824- + IOAT_CHANCMD_OFFSET(ioat_chan->device->version));825825- mdelay(100);826826-827827- spin_lock_bh(&ioat_chan->desc_lock);828828- switch (ioat_chan->device->version) {829829- case IOAT_VER_1_2:830830- list_for_each_entry_safe(desc, _desc,831831- &ioat_chan->used_desc, node) {832832- in_use_descs++;833833- list_del(&desc->node);834834- pci_pool_free(ioatdma_device->dma_pool, desc->hw,835835- desc->async_tx.phys);836836- kfree(desc);837837- }838838- list_for_each_entry_safe(desc, _desc,839839- &ioat_chan->free_desc, node) {840840- list_del(&desc->node);841841- pci_pool_free(ioatdma_device->dma_pool, desc->hw,842842- desc->async_tx.phys);843843- kfree(desc);844844- }845845- break;846846- case IOAT_VER_2_0:847847- case IOAT_VER_3_0:848848- list_for_each_entry_safe(desc, _desc,849849- ioat_chan->free_desc.next, node) {850850- list_del(&desc->node);851851- pci_pool_free(ioatdma_device->dma_pool, desc->hw,852852- desc->async_tx.phys);853853- kfree(desc);854854- }855855- desc = to_ioat_desc(ioat_chan->free_desc.next);856856- pci_pool_free(ioatdma_device->dma_pool, desc->hw,857857- desc->async_tx.phys);858858- kfree(desc);859859- INIT_LIST_HEAD(&ioat_chan->free_desc);860860- INIT_LIST_HEAD(&ioat_chan->used_desc);861861- break;862862- }863863- spin_unlock_bh(&ioat_chan->desc_lock);864864-865865- pci_pool_free(ioatdma_device->completion_pool,866866- ioat_chan->completion_virt,867867- ioat_chan->completion_addr);868868-869869- /* one is ok since we left it on there on purpose */870870- if (in_use_descs > 1)871871- dev_err(&ioat_chan->device->pdev->dev,872872- "Freeing %d in use descriptors!\n",873873- in_use_descs - 1);874874-875875- ioat_chan->last_completion = ioat_chan->completion_addr = 0;876876- ioat_chan->pending = 0;877877- ioat_chan->dmacount = 0;878878- ioat_chan->desccount = 0;879879- ioat_chan->watchdog_completion = 0;880880- ioat_chan->last_compl_desc_addr_hw = 0;881881- ioat_chan->watchdog_tcp_cookie =882882- ioat_chan->watchdog_last_tcp_cookie = 0;883883-}884884-885885-/**886886- * ioat_dma_get_next_descriptor - return the next available descriptor887887- * @ioat_chan: IOAT DMA channel handle888888- *889889- * Gets the next descriptor from the chain, and must be called with the890890- * channel's desc_lock held. Allocates more descriptors if the channel891891- * has run out.892892- */893893-static struct ioat_desc_sw *894894-ioat1_dma_get_next_descriptor(struct ioat_dma_chan *ioat_chan)895895-{896896- struct ioat_desc_sw *new;897897-898898- if (!list_empty(&ioat_chan->free_desc)) {899899- new = to_ioat_desc(ioat_chan->free_desc.next);900900- list_del(&new->node);901901- } else {902902- /* try to get another desc */903903- new = ioat_dma_alloc_descriptor(ioat_chan, GFP_ATOMIC);904904- if (!new) {905905- dev_err(&ioat_chan->device->pdev->dev,906906- "alloc failed\n");907907- return NULL;908908- }909909- }910910-911911- prefetch(new->hw);912912- return new;913913-}914914-915915-static struct ioat_desc_sw *916916-ioat2_dma_get_next_descriptor(struct ioat_dma_chan *ioat_chan)917917-{918918- struct ioat_desc_sw *new;919919-920920- /*921921- * used.prev points to where to start processing922922- * used.next points to next free descriptor923923- * if used.prev == NULL, there are none waiting to be processed924924- * if used.next == used.prev.prev, there is only one free descriptor,925925- * and we need to use it to as a noop descriptor before926926- * linking in a new set of descriptors, since the device927927- * has probably already read the pointer to it928928- */929929- if (ioat_chan->used_desc.prev &&930930- ioat_chan->used_desc.next == ioat_chan->used_desc.prev->prev) {931931-932932- struct ioat_desc_sw *desc;933933- struct ioat_desc_sw *noop_desc;934934- int i;935935-936936- /* set up the noop descriptor */937937- noop_desc = to_ioat_desc(ioat_chan->used_desc.next);938938- /* set size to non-zero value (channel returns error when size is 0) */939939- noop_desc->hw->size = NULL_DESC_BUFFER_SIZE;940940- noop_desc->hw->ctl = IOAT_DMA_DESCRIPTOR_NUL;941941- noop_desc->hw->src_addr = 0;942942- noop_desc->hw->dst_addr = 0;943943-944944- ioat_chan->used_desc.next = ioat_chan->used_desc.next->next;945945- ioat_chan->pending++;946946- ioat_chan->dmacount++;947947-948948- /* try to get a few more descriptors */949949- for (i = 16; i; i--) {950950- desc = ioat_dma_alloc_descriptor(ioat_chan, GFP_ATOMIC);951951- if (!desc) {952952- dev_err(&ioat_chan->device->pdev->dev,953953- "alloc failed\n");954954- break;955955- }956956- list_add_tail(&desc->node, ioat_chan->used_desc.next);957957-958958- desc->hw->next959959- = to_ioat_desc(desc->node.next)->async_tx.phys;960960- to_ioat_desc(desc->node.prev)->hw->next961961- = desc->async_tx.phys;962962- ioat_chan->desccount++;963963- }964964-965965- ioat_chan->used_desc.next = noop_desc->node.next;966966- }967967- new = to_ioat_desc(ioat_chan->used_desc.next);968968- prefetch(new);969969- ioat_chan->used_desc.next = new->node.next;970970-971971- if (ioat_chan->used_desc.prev == NULL)972972- ioat_chan->used_desc.prev = &new->node;973973-974974- prefetch(new->hw);975975- return new;976976-}977977-978978-static struct ioat_desc_sw *ioat_dma_get_next_descriptor(979979- struct ioat_dma_chan *ioat_chan)980980-{981981- if (!ioat_chan)982982- return NULL;983983-984984- switch (ioat_chan->device->version) {985985- case IOAT_VER_1_2:986986- return ioat1_dma_get_next_descriptor(ioat_chan);987987- case IOAT_VER_2_0:988988- case IOAT_VER_3_0:989989- return ioat2_dma_get_next_descriptor(ioat_chan);990990- }991991- return NULL;992992-}993993-994994-static struct dma_async_tx_descriptor *ioat1_dma_prep_memcpy(995995- struct dma_chan *chan,996996- dma_addr_t dma_dest,997997- dma_addr_t dma_src,998998- size_t len,999999- unsigned long flags)10001000-{10011001- struct ioat_dma_chan *ioat_chan = to_ioat_chan(chan);10021002- struct ioat_desc_sw *new;10031003-10041004- spin_lock_bh(&ioat_chan->desc_lock);10051005- new = ioat_dma_get_next_descriptor(ioat_chan);10061006- spin_unlock_bh(&ioat_chan->desc_lock);10071007-10081008- if (new) {10091009- new->len = len;10101010- new->dst = dma_dest;10111011- new->src = dma_src;10121012- new->async_tx.flags = flags;10131013- return &new->async_tx;10141014- } else {10151015- dev_err(&ioat_chan->device->pdev->dev,10161016- "chan%d - get_next_desc failed: %d descs waiting, %d total desc\n",10171017- chan_num(ioat_chan), ioat_chan->dmacount, ioat_chan->desccount);10181018- return NULL;10191019- }10201020-}10211021-10221022-static struct dma_async_tx_descriptor *ioat2_dma_prep_memcpy(10231023- struct dma_chan *chan,10241024- dma_addr_t dma_dest,10251025- dma_addr_t dma_src,10261026- size_t len,10271027- unsigned long flags)10281028-{10291029- struct ioat_dma_chan *ioat_chan = to_ioat_chan(chan);10301030- struct ioat_desc_sw *new;10311031-10321032- spin_lock_bh(&ioat_chan->desc_lock);10331033- new = ioat2_dma_get_next_descriptor(ioat_chan);10341034-10351035- /*10361036- * leave ioat_chan->desc_lock set in ioat 2 path10371037- * it will get unlocked at end of tx_submit10381038- */10391039-10401040- if (new) {10411041- new->len = len;10421042- new->dst = dma_dest;10431043- new->src = dma_src;10441044- new->async_tx.flags = flags;10451045- return &new->async_tx;10461046- } else {10471047- spin_unlock_bh(&ioat_chan->desc_lock);10481048- dev_err(&ioat_chan->device->pdev->dev,10491049- "chan%d - get_next_desc failed: %d descs waiting, %d total desc\n",10501050- chan_num(ioat_chan), ioat_chan->dmacount, ioat_chan->desccount);10511051- return NULL;10521052- }10531053-}10541054-10551055-static void ioat_dma_cleanup_tasklet(unsigned long data)10561056-{10571057- struct ioat_dma_chan *chan = (void *)data;10581058- ioat_dma_memcpy_cleanup(chan);10591059- writew(IOAT_CHANCTRL_INT_DISABLE,10601060- chan->reg_base + IOAT_CHANCTRL_OFFSET);10611061-}10621062-10631063-static void10641064-ioat_dma_unmap(struct ioat_dma_chan *ioat_chan, struct ioat_desc_sw *desc)10651065-{10661066- if (!(desc->async_tx.flags & DMA_COMPL_SKIP_DEST_UNMAP)) {10671067- if (desc->async_tx.flags & DMA_COMPL_DEST_UNMAP_SINGLE)10681068- pci_unmap_single(ioat_chan->device->pdev,10691069- pci_unmap_addr(desc, dst),10701070- pci_unmap_len(desc, len),10711071- PCI_DMA_FROMDEVICE);10721072- else10731073- pci_unmap_page(ioat_chan->device->pdev,10741074- pci_unmap_addr(desc, dst),10751075- pci_unmap_len(desc, len),10761076- PCI_DMA_FROMDEVICE);10771077- }10781078-10791079- if (!(desc->async_tx.flags & DMA_COMPL_SKIP_SRC_UNMAP)) {10801080- if (desc->async_tx.flags & DMA_COMPL_SRC_UNMAP_SINGLE)10811081- pci_unmap_single(ioat_chan->device->pdev,10821082- pci_unmap_addr(desc, src),10831083- pci_unmap_len(desc, len),10841084- PCI_DMA_TODEVICE);10851085- else10861086- pci_unmap_page(ioat_chan->device->pdev,10871087- pci_unmap_addr(desc, src),10881088- pci_unmap_len(desc, len),10891089- PCI_DMA_TODEVICE);10901090- }10911091-}10921092-10931093-/**10941094- * ioat_dma_memcpy_cleanup - cleanup up finished descriptors10951095- * @chan: ioat channel to be cleaned up10961096- */10971097-static void ioat_dma_memcpy_cleanup(struct ioat_dma_chan *ioat_chan)10981098-{10991099- unsigned long phys_complete;11001100- struct ioat_desc_sw *desc, *_desc;11011101- dma_cookie_t cookie = 0;11021102- unsigned long desc_phys;11031103- struct ioat_desc_sw *latest_desc;11041104-11051105- prefetch(ioat_chan->completion_virt);11061106-11071107- if (!spin_trylock_bh(&ioat_chan->cleanup_lock))11081108- return;11091109-11101110- /* The completion writeback can happen at any time,11111111- so reads by the driver need to be atomic operations11121112- The descriptor physical addresses are limited to 32-bits11131113- when the CPU can only do a 32-bit mov */11141114-11151115-#if (BITS_PER_LONG == 64)11161116- phys_complete =11171117- ioat_chan->completion_virt->full11181118- & IOAT_CHANSTS_COMPLETED_DESCRIPTOR_ADDR;11191119-#else11201120- phys_complete =11211121- ioat_chan->completion_virt->low & IOAT_LOW_COMPLETION_MASK;11221122-#endif11231123-11241124- if ((ioat_chan->completion_virt->full11251125- & IOAT_CHANSTS_DMA_TRANSFER_STATUS) ==11261126- IOAT_CHANSTS_DMA_TRANSFER_STATUS_HALTED) {11271127- dev_err(&ioat_chan->device->pdev->dev,11281128- "Channel halted, chanerr = %x\n",11291129- readl(ioat_chan->reg_base + IOAT_CHANERR_OFFSET));11301130-11311131- /* TODO do something to salvage the situation */11321132- }11331133-11341134- if (phys_complete == ioat_chan->last_completion) {11351135- spin_unlock_bh(&ioat_chan->cleanup_lock);11361136- /*11371137- * perhaps we're stuck so hard that the watchdog can't go off?11381138- * try to catch it after 2 seconds11391139- */11401140- if (ioat_chan->device->version != IOAT_VER_3_0) {11411141- if (time_after(jiffies,11421142- ioat_chan->last_completion_time + HZ*WATCHDOG_DELAY)) {11431143- ioat_dma_chan_watchdog(&(ioat_chan->device->work.work));11441144- ioat_chan->last_completion_time = jiffies;11451145- }11461146- }11471147- return;11481148- }11491149- ioat_chan->last_completion_time = jiffies;11501150-11511151- cookie = 0;11521152- if (!spin_trylock_bh(&ioat_chan->desc_lock)) {11531153- spin_unlock_bh(&ioat_chan->cleanup_lock);11541154- return;11551155- }11561156-11571157- switch (ioat_chan->device->version) {11581158- case IOAT_VER_1_2:11591159- list_for_each_entry_safe(desc, _desc,11601160- &ioat_chan->used_desc, node) {11611161-11621162- /*11631163- * Incoming DMA requests may use multiple descriptors,11641164- * due to exceeding xfercap, perhaps. If so, only the11651165- * last one will have a cookie, and require unmapping.11661166- */11671167- if (desc->async_tx.cookie) {11681168- cookie = desc->async_tx.cookie;11691169- ioat_dma_unmap(ioat_chan, desc);11701170- if (desc->async_tx.callback) {11711171- desc->async_tx.callback(desc->async_tx.callback_param);11721172- desc->async_tx.callback = NULL;11731173- }11741174- }11751175-11761176- if (desc->async_tx.phys != phys_complete) {11771177- /*11781178- * a completed entry, but not the last, so clean11791179- * up if the client is done with the descriptor11801180- */11811181- if (async_tx_test_ack(&desc->async_tx)) {11821182- list_move_tail(&desc->node,11831183- &ioat_chan->free_desc);11841184- } else11851185- desc->async_tx.cookie = 0;11861186- } else {11871187- /*11881188- * last used desc. Do not remove, so we can11891189- * append from it, but don't look at it next11901190- * time, either11911191- */11921192- desc->async_tx.cookie = 0;11931193-11941194- /* TODO check status bits? */11951195- break;11961196- }11971197- }11981198- break;11991199- case IOAT_VER_2_0:12001200- case IOAT_VER_3_0:12011201- /* has some other thread has already cleaned up? */12021202- if (ioat_chan->used_desc.prev == NULL)12031203- break;12041204-12051205- /* work backwards to find latest finished desc */12061206- desc = to_ioat_desc(ioat_chan->used_desc.next);12071207- latest_desc = NULL;12081208- do {12091209- desc = to_ioat_desc(desc->node.prev);12101210- desc_phys = (unsigned long)desc->async_tx.phys12111211- & IOAT_CHANSTS_COMPLETED_DESCRIPTOR_ADDR;12121212- if (desc_phys == phys_complete) {12131213- latest_desc = desc;12141214- break;12151215- }12161216- } while (&desc->node != ioat_chan->used_desc.prev);12171217-12181218- if (latest_desc != NULL) {12191219-12201220- /* work forwards to clear finished descriptors */12211221- for (desc = to_ioat_desc(ioat_chan->used_desc.prev);12221222- &desc->node != latest_desc->node.next &&12231223- &desc->node != ioat_chan->used_desc.next;12241224- desc = to_ioat_desc(desc->node.next)) {12251225- if (desc->async_tx.cookie) {12261226- cookie = desc->async_tx.cookie;12271227- desc->async_tx.cookie = 0;12281228- ioat_dma_unmap(ioat_chan, desc);12291229- if (desc->async_tx.callback) {12301230- desc->async_tx.callback(desc->async_tx.callback_param);12311231- desc->async_tx.callback = NULL;12321232- }12331233- }12341234- }12351235-12361236- /* move used.prev up beyond those that are finished */12371237- if (&desc->node == ioat_chan->used_desc.next)12381238- ioat_chan->used_desc.prev = NULL;12391239- else12401240- ioat_chan->used_desc.prev = &desc->node;12411241- }12421242- break;12431243- }12441244-12451245- spin_unlock_bh(&ioat_chan->desc_lock);12461246-12471247- ioat_chan->last_completion = phys_complete;12481248- if (cookie != 0)12491249- ioat_chan->completed_cookie = cookie;12501250-12511251- spin_unlock_bh(&ioat_chan->cleanup_lock);12521252-}12531253-12541254-/**12551255- * ioat_dma_is_complete - poll the status of a IOAT DMA transaction12561256- * @chan: IOAT DMA channel handle12571257- * @cookie: DMA transaction identifier12581258- * @done: if not %NULL, updated with last completed transaction12591259- * @used: if not %NULL, updated with last used transaction12601260- */12611261-static enum dma_status ioat_dma_is_complete(struct dma_chan *chan,12621262- dma_cookie_t cookie,12631263- dma_cookie_t *done,12641264- dma_cookie_t *used)12651265-{12661266- struct ioat_dma_chan *ioat_chan = to_ioat_chan(chan);12671267- dma_cookie_t last_used;12681268- dma_cookie_t last_complete;12691269- enum dma_status ret;12701270-12711271- last_used = chan->cookie;12721272- last_complete = ioat_chan->completed_cookie;12731273- ioat_chan->watchdog_tcp_cookie = cookie;12741274-12751275- if (done)12761276- *done = last_complete;12771277- if (used)12781278- *used = last_used;12791279-12801280- ret = dma_async_is_complete(cookie, last_complete, last_used);12811281- if (ret == DMA_SUCCESS)12821282- return ret;12831283-12841284- ioat_dma_memcpy_cleanup(ioat_chan);12851285-12861286- last_used = chan->cookie;12871287- last_complete = ioat_chan->completed_cookie;12881288-12891289- if (done)12901290- *done = last_complete;12911291- if (used)12921292- *used = last_used;12931293-12941294- return dma_async_is_complete(cookie, last_complete, last_used);12951295-}12961296-12971297-static void ioat_dma_start_null_desc(struct ioat_dma_chan *ioat_chan)12981298-{12991299- struct ioat_desc_sw *desc;13001300-13011301- spin_lock_bh(&ioat_chan->desc_lock);13021302-13031303- desc = ioat_dma_get_next_descriptor(ioat_chan);13041304-13051305- if (!desc) {13061306- dev_err(&ioat_chan->device->pdev->dev,13071307- "Unable to start null desc - get next desc failed\n");13081308- spin_unlock_bh(&ioat_chan->desc_lock);13091309- return;13101310- }13111311-13121312- desc->hw->ctl = IOAT_DMA_DESCRIPTOR_NUL13131313- | IOAT_DMA_DESCRIPTOR_CTL_INT_GN13141314- | IOAT_DMA_DESCRIPTOR_CTL_CP_STS;13151315- /* set size to non-zero value (channel returns error when size is 0) */13161316- desc->hw->size = NULL_DESC_BUFFER_SIZE;13171317- desc->hw->src_addr = 0;13181318- desc->hw->dst_addr = 0;13191319- async_tx_ack(&desc->async_tx);13201320- switch (ioat_chan->device->version) {13211321- case IOAT_VER_1_2:13221322- desc->hw->next = 0;13231323- list_add_tail(&desc->node, &ioat_chan->used_desc);13241324-13251325- writel(((u64) desc->async_tx.phys) & 0x00000000FFFFFFFF,13261326- ioat_chan->reg_base + IOAT1_CHAINADDR_OFFSET_LOW);13271327- writel(((u64) desc->async_tx.phys) >> 32,13281328- ioat_chan->reg_base + IOAT1_CHAINADDR_OFFSET_HIGH);13291329-13301330- writeb(IOAT_CHANCMD_START, ioat_chan->reg_base13311331- + IOAT_CHANCMD_OFFSET(ioat_chan->device->version));13321332- break;13331333- case IOAT_VER_2_0:13341334- case IOAT_VER_3_0:13351335- writel(((u64) desc->async_tx.phys) & 0x00000000FFFFFFFF,13361336- ioat_chan->reg_base + IOAT2_CHAINADDR_OFFSET_LOW);13371337- writel(((u64) desc->async_tx.phys) >> 32,13381338- ioat_chan->reg_base + IOAT2_CHAINADDR_OFFSET_HIGH);13391339-13401340- ioat_chan->dmacount++;13411341- __ioat2_dma_memcpy_issue_pending(ioat_chan);13421342- break;13431343- }13441344- spin_unlock_bh(&ioat_chan->desc_lock);13451345-}13461346-13471347-/*13481348- * Perform a IOAT transaction to verify the HW works.13491349- */13501350-#define IOAT_TEST_SIZE 200013511351-13521352-static void ioat_dma_test_callback(void *dma_async_param)13531353-{13541354- struct completion *cmp = dma_async_param;13551355-13561356- complete(cmp);13571357-}13581358-13591359-/**13601360- * ioat_dma_self_test - Perform a IOAT transaction to verify the HW works.13611361- * @device: device to be tested13621362- */13631363-static int ioat_dma_self_test(struct ioatdma_device *device)13641364-{13651365- int i;13661366- u8 *src;13671367- u8 *dest;13681368- struct dma_chan *dma_chan;13691369- struct dma_async_tx_descriptor *tx;13701370- dma_addr_t dma_dest, dma_src;13711371- dma_cookie_t cookie;13721372- int err = 0;13731373- struct completion cmp;13741374- unsigned long tmo;13751375- unsigned long flags;13761376-13771377- src = kzalloc(sizeof(u8) * IOAT_TEST_SIZE, GFP_KERNEL);13781378- if (!src)13791379- return -ENOMEM;13801380- dest = kzalloc(sizeof(u8) * IOAT_TEST_SIZE, GFP_KERNEL);13811381- if (!dest) {13821382- kfree(src);13831383- return -ENOMEM;13841384- }13851385-13861386- /* Fill in src buffer */13871387- for (i = 0; i < IOAT_TEST_SIZE; i++)13881388- src[i] = (u8)i;13891389-13901390- /* Start copy, using first DMA channel */13911391- dma_chan = container_of(device->common.channels.next,13921392- struct dma_chan,13931393- device_node);13941394- if (device->common.device_alloc_chan_resources(dma_chan) < 1) {13951395- dev_err(&device->pdev->dev,13961396- "selftest cannot allocate chan resource\n");13971397- err = -ENODEV;13981398- goto out;13991399- }14001400-14011401- dma_src = dma_map_single(dma_chan->device->dev, src, IOAT_TEST_SIZE,14021402- DMA_TO_DEVICE);14031403- dma_dest = dma_map_single(dma_chan->device->dev, dest, IOAT_TEST_SIZE,14041404- DMA_FROM_DEVICE);14051405- flags = DMA_COMPL_SRC_UNMAP_SINGLE | DMA_COMPL_DEST_UNMAP_SINGLE;14061406- tx = device->common.device_prep_dma_memcpy(dma_chan, dma_dest, dma_src,14071407- IOAT_TEST_SIZE, flags);14081408- if (!tx) {14091409- dev_err(&device->pdev->dev,14101410- "Self-test prep failed, disabling\n");14111411- err = -ENODEV;14121412- goto free_resources;14131413- }14141414-14151415- async_tx_ack(tx);14161416- init_completion(&cmp);14171417- tx->callback = ioat_dma_test_callback;14181418- tx->callback_param = &cmp;14191419- cookie = tx->tx_submit(tx);14201420- if (cookie < 0) {14211421- dev_err(&device->pdev->dev,14221422- "Self-test setup failed, disabling\n");14231423- err = -ENODEV;14241424- goto free_resources;14251425- }14261426- device->common.device_issue_pending(dma_chan);14271427-14281428- tmo = wait_for_completion_timeout(&cmp, msecs_to_jiffies(3000));14291429-14301430- if (tmo == 0 ||14311431- device->common.device_is_tx_complete(dma_chan, cookie, NULL, NULL)14321432- != DMA_SUCCESS) {14331433- dev_err(&device->pdev->dev,14341434- "Self-test copy timed out, disabling\n");14351435- err = -ENODEV;14361436- goto free_resources;14371437- }14381438- if (memcmp(src, dest, IOAT_TEST_SIZE)) {14391439- dev_err(&device->pdev->dev,14401440- "Self-test copy failed compare, disabling\n");14411441- err = -ENODEV;14421442- goto free_resources;14431443- }14441444-14451445-free_resources:14461446- device->common.device_free_chan_resources(dma_chan);14471447-out:14481448- kfree(src);14491449- kfree(dest);14501450- return err;14511451-}14521452-14531453-static char ioat_interrupt_style[32] = "msix";14541454-module_param_string(ioat_interrupt_style, ioat_interrupt_style,14551455- sizeof(ioat_interrupt_style), 0644);14561456-MODULE_PARM_DESC(ioat_interrupt_style,14571457- "set ioat interrupt style: msix (default), "14581458- "msix-single-vector, msi, intx)");14591459-14601460-/**14611461- * ioat_dma_setup_interrupts - setup interrupt handler14621462- * @device: ioat device14631463- */14641464-static int ioat_dma_setup_interrupts(struct ioatdma_device *device)14651465-{14661466- struct ioat_dma_chan *ioat_chan;14671467- int err, i, j, msixcnt;14681468- u8 intrctrl = 0;14691469-14701470- if (!strcmp(ioat_interrupt_style, "msix"))14711471- goto msix;14721472- if (!strcmp(ioat_interrupt_style, "msix-single-vector"))14731473- goto msix_single_vector;14741474- if (!strcmp(ioat_interrupt_style, "msi"))14751475- goto msi;14761476- if (!strcmp(ioat_interrupt_style, "intx"))14771477- goto intx;14781478- dev_err(&device->pdev->dev, "invalid ioat_interrupt_style %s\n",14791479- ioat_interrupt_style);14801480- goto err_no_irq;14811481-14821482-msix:14831483- /* The number of MSI-X vectors should equal the number of channels */14841484- msixcnt = device->common.chancnt;14851485- for (i = 0; i < msixcnt; i++)14861486- device->msix_entries[i].entry = i;14871487-14881488- err = pci_enable_msix(device->pdev, device->msix_entries, msixcnt);14891489- if (err < 0)14901490- goto msi;14911491- if (err > 0)14921492- goto msix_single_vector;14931493-14941494- for (i = 0; i < msixcnt; i++) {14951495- ioat_chan = ioat_lookup_chan_by_index(device, i);14961496- err = request_irq(device->msix_entries[i].vector,14971497- ioat_dma_do_interrupt_msix,14981498- 0, "ioat-msix", ioat_chan);14991499- if (err) {15001500- for (j = 0; j < i; j++) {15011501- ioat_chan =15021502- ioat_lookup_chan_by_index(device, j);15031503- free_irq(device->msix_entries[j].vector,15041504- ioat_chan);15051505- }15061506- goto msix_single_vector;15071507- }15081508- }15091509- intrctrl |= IOAT_INTRCTRL_MSIX_VECTOR_CONTROL;15101510- device->irq_mode = msix_multi_vector;15111511- goto done;15121512-15131513-msix_single_vector:15141514- device->msix_entries[0].entry = 0;15151515- err = pci_enable_msix(device->pdev, device->msix_entries, 1);15161516- if (err)15171517- goto msi;15181518-15191519- err = request_irq(device->msix_entries[0].vector, ioat_dma_do_interrupt,15201520- 0, "ioat-msix", device);15211521- if (err) {15221522- pci_disable_msix(device->pdev);15231523- goto msi;15241524- }15251525- device->irq_mode = msix_single_vector;15261526- goto done;15271527-15281528-msi:15291529- err = pci_enable_msi(device->pdev);15301530- if (err)15311531- goto intx;15321532-15331533- err = request_irq(device->pdev->irq, ioat_dma_do_interrupt,15341534- 0, "ioat-msi", device);15351535- if (err) {15361536- pci_disable_msi(device->pdev);15371537- goto intx;15381538- }15391539- /*15401540- * CB 1.2 devices need a bit set in configuration space to enable MSI15411541- */15421542- if (device->version == IOAT_VER_1_2) {15431543- u32 dmactrl;15441544- pci_read_config_dword(device->pdev,15451545- IOAT_PCI_DMACTRL_OFFSET, &dmactrl);15461546- dmactrl |= IOAT_PCI_DMACTRL_MSI_EN;15471547- pci_write_config_dword(device->pdev,15481548- IOAT_PCI_DMACTRL_OFFSET, dmactrl);15491549- }15501550- device->irq_mode = msi;15511551- goto done;15521552-15531553-intx:15541554- err = request_irq(device->pdev->irq, ioat_dma_do_interrupt,15551555- IRQF_SHARED, "ioat-intx", device);15561556- if (err)15571557- goto err_no_irq;15581558- device->irq_mode = intx;15591559-15601560-done:15611561- intrctrl |= IOAT_INTRCTRL_MASTER_INT_EN;15621562- writeb(intrctrl, device->reg_base + IOAT_INTRCTRL_OFFSET);15631563- return 0;15641564-15651565-err_no_irq:15661566- /* Disable all interrupt generation */15671567- writeb(0, device->reg_base + IOAT_INTRCTRL_OFFSET);15681568- dev_err(&device->pdev->dev, "no usable interrupts\n");15691569- device->irq_mode = none;15701570- return -1;15711571-}15721572-15731573-/**15741574- * ioat_dma_remove_interrupts - remove whatever interrupts were set15751575- * @device: ioat device15761576- */15771577-static void ioat_dma_remove_interrupts(struct ioatdma_device *device)15781578-{15791579- struct ioat_dma_chan *ioat_chan;15801580- int i;15811581-15821582- /* Disable all interrupt generation */15831583- writeb(0, device->reg_base + IOAT_INTRCTRL_OFFSET);15841584-15851585- switch (device->irq_mode) {15861586- case msix_multi_vector:15871587- for (i = 0; i < device->common.chancnt; i++) {15881588- ioat_chan = ioat_lookup_chan_by_index(device, i);15891589- free_irq(device->msix_entries[i].vector, ioat_chan);15901590- }15911591- pci_disable_msix(device->pdev);15921592- break;15931593- case msix_single_vector:15941594- free_irq(device->msix_entries[0].vector, device);15951595- pci_disable_msix(device->pdev);15961596- break;15971597- case msi:15981598- free_irq(device->pdev->irq, device);15991599- pci_disable_msi(device->pdev);16001600- break;16011601- case intx:16021602- free_irq(device->pdev->irq, device);16031603- break;16041604- case none:16051605- dev_warn(&device->pdev->dev,16061606- "call to %s without interrupts setup\n", __func__);16071607- }16081608- device->irq_mode = none;16091609-}16101610-16111611-struct ioatdma_device *ioat_dma_probe(struct pci_dev *pdev,16121612- void __iomem *iobase)16131613-{16141614- int err;16151615- struct ioatdma_device *device;16161616-16171617- device = kzalloc(sizeof(*device), GFP_KERNEL);16181618- if (!device) {16191619- err = -ENOMEM;16201620- goto err_kzalloc;16211621- }16221622- device->pdev = pdev;16231623- device->reg_base = iobase;16241624- device->version = readb(device->reg_base + IOAT_VER_OFFSET);16251625-16261626- /* DMA coherent memory pool for DMA descriptor allocations */16271627- device->dma_pool = pci_pool_create("dma_desc_pool", pdev,16281628- sizeof(struct ioat_dma_descriptor),16291629- 64, 0);16301630- if (!device->dma_pool) {16311631- err = -ENOMEM;16321632- goto err_dma_pool;16331633- }16341634-16351635- device->completion_pool = pci_pool_create("completion_pool", pdev,16361636- sizeof(u64), SMP_CACHE_BYTES,16371637- SMP_CACHE_BYTES);16381638- if (!device->completion_pool) {16391639- err = -ENOMEM;16401640- goto err_completion_pool;16411641- }16421642-16431643- INIT_LIST_HEAD(&device->common.channels);16441644- ioat_dma_enumerate_channels(device);16451645-16461646- device->common.device_alloc_chan_resources =16471647- ioat_dma_alloc_chan_resources;16481648- device->common.device_free_chan_resources =16491649- ioat_dma_free_chan_resources;16501650- device->common.dev = &pdev->dev;16511651-16521652- dma_cap_set(DMA_MEMCPY, device->common.cap_mask);16531653- device->common.device_is_tx_complete = ioat_dma_is_complete;16541654- switch (device->version) {16551655- case IOAT_VER_1_2:16561656- device->common.device_prep_dma_memcpy = ioat1_dma_prep_memcpy;16571657- device->common.device_issue_pending =16581658- ioat1_dma_memcpy_issue_pending;16591659- break;16601660- case IOAT_VER_2_0:16611661- case IOAT_VER_3_0:16621662- device->common.device_prep_dma_memcpy = ioat2_dma_prep_memcpy;16631663- device->common.device_issue_pending =16641664- ioat2_dma_memcpy_issue_pending;16651665- break;16661666- }16671667-16681668- dev_err(&device->pdev->dev,16691669- "Intel(R) I/OAT DMA Engine found,"16701670- " %d channels, device version 0x%02x, driver version %s\n",16711671- device->common.chancnt, device->version, IOAT_DMA_VERSION);16721672-16731673- if (!device->common.chancnt) {16741674- dev_err(&device->pdev->dev,16751675- "Intel(R) I/OAT DMA Engine problem found: "16761676- "zero channels detected\n");16771677- goto err_setup_interrupts;16781678- }16791679-16801680- err = ioat_dma_setup_interrupts(device);16811681- if (err)16821682- goto err_setup_interrupts;16831683-16841684- err = ioat_dma_self_test(device);16851685- if (err)16861686- goto err_self_test;16871687-16881688- ioat_set_tcp_copy_break(device);16891689-16901690- dma_async_device_register(&device->common);16911691-16921692- if (device->version != IOAT_VER_3_0) {16931693- INIT_DELAYED_WORK(&device->work, ioat_dma_chan_watchdog);16941694- schedule_delayed_work(&device->work,16951695- WATCHDOG_DELAY);16961696- }16971697-16981698- return device;16991699-17001700-err_self_test:17011701- ioat_dma_remove_interrupts(device);17021702-err_setup_interrupts:17031703- pci_pool_destroy(device->completion_pool);17041704-err_completion_pool:17051705- pci_pool_destroy(device->dma_pool);17061706-err_dma_pool:17071707- kfree(device);17081708-err_kzalloc:17091709- dev_err(&pdev->dev,17101710- "Intel(R) I/OAT DMA Engine initialization failed\n");17111711- return NULL;17121712-}17131713-17141714-void ioat_dma_remove(struct ioatdma_device *device)17151715-{17161716- struct dma_chan *chan, *_chan;17171717- struct ioat_dma_chan *ioat_chan;17181718-17191719- if (device->version != IOAT_VER_3_0)17201720- cancel_delayed_work(&device->work);17211721-17221722- ioat_dma_remove_interrupts(device);17231723-17241724- dma_async_device_unregister(&device->common);17251725-17261726- pci_pool_destroy(device->dma_pool);17271727- pci_pool_destroy(device->completion_pool);17281728-17291729- iounmap(device->reg_base);17301730- pci_release_regions(device->pdev);17311731- pci_disable_device(device->pdev);17321732-17331733- list_for_each_entry_safe(chan, _chan,17341734- &device->common.channels, device_node) {17351735- ioat_chan = to_ioat_chan(chan);17361736- list_del(&chan->device_node);17371737- kfree(ioat_chan);17381738- }17391739- kfree(device);17401740-}17411741-
-165
drivers/dma/ioatdma.h
···11-/*22- * Copyright(c) 2004 - 2009 Intel Corporation. All rights reserved.33- *44- * This program is free software; you can redistribute it and/or modify it55- * under the terms of the GNU General Public License as published by the Free66- * Software Foundation; either version 2 of the License, or (at your option)77- * any later version.88- *99- * This program is distributed in the hope that it will be useful, but WITHOUT1010- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or1111- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for1212- * more details.1313- *1414- * You should have received a copy of the GNU General Public License along with1515- * this program; if not, write to the Free Software Foundation, Inc., 591616- * Temple Place - Suite 330, Boston, MA 02111-1307, USA.1717- *1818- * The full GNU General Public License is included in this distribution in the1919- * file called COPYING.2020- */2121-#ifndef IOATDMA_H2222-#define IOATDMA_H2323-2424-#include <linux/dmaengine.h>2525-#include "ioatdma_hw.h"2626-#include <linux/init.h>2727-#include <linux/dmapool.h>2828-#include <linux/cache.h>2929-#include <linux/pci_ids.h>3030-#include <net/tcp.h>3131-3232-#define IOAT_DMA_VERSION "3.64"3333-3434-enum ioat_interrupt {3535- none = 0,3636- msix_multi_vector = 1,3737- msix_single_vector = 2,3838- msi = 3,3939- intx = 4,4040-};4141-4242-#define IOAT_LOW_COMPLETION_MASK 0xffffffc04343-#define IOAT_DMA_DCA_ANY_CPU ~04444-#define IOAT_WATCHDOG_PERIOD (2 * HZ)4545-4646-4747-/**4848- * struct ioatdma_device - internal representation of a IOAT device4949- * @pdev: PCI-Express device5050- * @reg_base: MMIO register space base address5151- * @dma_pool: for allocating DMA descriptors5252- * @common: embedded struct dma_device5353- * @version: version of ioatdma device5454- * @irq_mode: which style irq to use5555- * @msix_entries: irq handlers5656- * @idx: per channel data5757- */5858-5959-struct ioatdma_device {6060- struct pci_dev *pdev;6161- void __iomem *reg_base;6262- struct pci_pool *dma_pool;6363- struct pci_pool *completion_pool;6464- struct dma_device common;6565- u8 version;6666- enum ioat_interrupt irq_mode;6767- struct delayed_work work;6868- struct msix_entry msix_entries[4];6969- struct ioat_dma_chan *idx[4];7070-};7171-7272-/**7373- * struct ioat_dma_chan - internal representation of a DMA channel7474- */7575-struct ioat_dma_chan {7676-7777- void __iomem *reg_base;7878-7979- dma_cookie_t completed_cookie;8080- unsigned long last_completion;8181- unsigned long last_completion_time;8282-8383- size_t xfercap; /* XFERCAP register value expanded out */8484-8585- spinlock_t cleanup_lock;8686- spinlock_t desc_lock;8787- struct list_head free_desc;8888- struct list_head used_desc;8989- unsigned long watchdog_completion;9090- int watchdog_tcp_cookie;9191- u32 watchdog_last_tcp_cookie;9292- struct delayed_work work;9393-9494- int pending;9595- int dmacount;9696- int desccount;9797-9898- struct ioatdma_device *device;9999- struct dma_chan common;100100-101101- dma_addr_t completion_addr;102102- union {103103- u64 full; /* HW completion writeback */104104- struct {105105- u32 low;106106- u32 high;107107- };108108- } *completion_virt;109109- unsigned long last_compl_desc_addr_hw;110110- struct tasklet_struct cleanup_task;111111-};112112-113113-/* wrapper around hardware descriptor format + additional software fields */114114-115115-/**116116- * struct ioat_desc_sw - wrapper around hardware descriptor117117- * @hw: hardware DMA descriptor118118- * @node: this descriptor will either be on the free list,119119- * or attached to a transaction list (async_tx.tx_list)120120- * @tx_cnt: number of descriptors required to complete the transaction121121- * @async_tx: the generic software descriptor for all engines122122- */123123-struct ioat_desc_sw {124124- struct ioat_dma_descriptor *hw;125125- struct list_head node;126126- int tx_cnt;127127- size_t len;128128- dma_addr_t src;129129- dma_addr_t dst;130130- struct dma_async_tx_descriptor async_tx;131131-};132132-133133-static inline void ioat_set_tcp_copy_break(struct ioatdma_device *dev)134134-{135135- #ifdef CONFIG_NET_DMA136136- switch (dev->version) {137137- case IOAT_VER_1_2:138138- sysctl_tcp_dma_copybreak = 4096;139139- break;140140- case IOAT_VER_2_0:141141- sysctl_tcp_dma_copybreak = 2048;142142- break;143143- case IOAT_VER_3_0:144144- sysctl_tcp_dma_copybreak = 262144;145145- break;146146- }147147- #endif148148-}149149-150150-#if defined(CONFIG_INTEL_IOATDMA) || defined(CONFIG_INTEL_IOATDMA_MODULE)151151-struct ioatdma_device *ioat_dma_probe(struct pci_dev *pdev,152152- void __iomem *iobase);153153-void ioat_dma_remove(struct ioatdma_device *device);154154-struct dca_provider *ioat_dca_init(struct pci_dev *pdev, void __iomem *iobase);155155-struct dca_provider *ioat2_dca_init(struct pci_dev *pdev, void __iomem *iobase);156156-struct dca_provider *ioat3_dca_init(struct pci_dev *pdev, void __iomem *iobase);157157-#else158158-#define ioat_dma_probe(pdev, iobase) NULL159159-#define ioat_dma_remove(device) do { } while (0)160160-#define ioat_dca_init(pdev, iobase) NULL161161-#define ioat2_dca_init(pdev, iobase) NULL162162-#define ioat3_dca_init(pdev, iobase) NULL163163-#endif164164-165165-#endif /* IOATDMA_H */
-70
drivers/dma/ioatdma_hw.h
···11-/*22- * Copyright(c) 2004 - 2009 Intel Corporation. All rights reserved.33- *44- * This program is free software; you can redistribute it and/or modify it55- * under the terms of the GNU General Public License as published by the Free66- * Software Foundation; either version 2 of the License, or (at your option)77- * any later version.88- *99- * This program is distributed in the hope that it will be useful, but WITHOUT1010- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or1111- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for1212- * more details.1313- *1414- * You should have received a copy of the GNU General Public License along with1515- * this program; if not, write to the Free Software Foundation, Inc., 591616- * Temple Place - Suite 330, Boston, MA 02111-1307, USA.1717- *1818- * The full GNU General Public License is included in this distribution in the1919- * file called COPYING.2020- */2121-#ifndef _IOAT_HW_H_2222-#define _IOAT_HW_H_2323-2424-/* PCI Configuration Space Values */2525-#define IOAT_PCI_VID 0x80862626-2727-/* CB device ID's */2828-#define IOAT_PCI_DID_5000 0x1A382929-#define IOAT_PCI_DID_CNB 0x360B3030-#define IOAT_PCI_DID_SCNB 0x65FF3131-#define IOAT_PCI_DID_SNB 0x402F3232-3333-#define IOAT_PCI_RID 0x003434-#define IOAT_PCI_SVID 0x80863535-#define IOAT_PCI_SID 0x80863636-#define IOAT_VER_1_2 0x12 /* Version 1.2 */3737-#define IOAT_VER_2_0 0x20 /* Version 2.0 */3838-#define IOAT_VER_3_0 0x30 /* Version 3.0 */3939-4040-struct ioat_dma_descriptor {4141- uint32_t size;4242- uint32_t ctl;4343- uint64_t src_addr;4444- uint64_t dst_addr;4545- uint64_t next;4646- uint64_t rsv1;4747- uint64_t rsv2;4848- uint64_t user1;4949- uint64_t user2;5050-};5151-5252-#define IOAT_DMA_DESCRIPTOR_CTL_INT_GN 0x000000015353-#define IOAT_DMA_DESCRIPTOR_CTL_SRC_SN 0x000000025454-#define IOAT_DMA_DESCRIPTOR_CTL_DST_SN 0x000000045555-#define IOAT_DMA_DESCRIPTOR_CTL_CP_STS 0x000000085656-#define IOAT_DMA_DESCRIPTOR_CTL_FRAME 0x000000105757-#define IOAT_DMA_DESCRIPTOR_NUL 0x000000205858-#define IOAT_DMA_DESCRIPTOR_CTL_SP_BRK 0x000000405959-#define IOAT_DMA_DESCRIPTOR_CTL_DP_BRK 0x000000806060-#define IOAT_DMA_DESCRIPTOR_CTL_BNDL 0x000001006161-#define IOAT_DMA_DESCRIPTOR_CTL_DCA 0x000002006262-#define IOAT_DMA_DESCRIPTOR_CTL_BUFHINT 0x000004006363-6464-#define IOAT_DMA_DESCRIPTOR_CTL_OPCODE_CONTEXT 0xFF0000006565-#define IOAT_DMA_DESCRIPTOR_CTL_OPCODE_DMA 0x000000006666-6767-#define IOAT_DMA_DESCRIPTOR_CTL_CONTEXT_DCA 0x000000016868-#define IOAT_DMA_DESCRIPTOR_CTL_OPCODE_MASK 0xFF0000006969-7070-#endif
···126126 * @idx: pool index127127 * @unmap_src_cnt: number of xor sources128128 * @unmap_len: transaction bytecount129129+ * @tx_list: list of slots that make up a multi-descriptor transaction129130 * @async_tx: support for the async_tx api130130- * @group_list: list of slots that make up a multi-descriptor transaction131131- * for example transfer lengths larger than the supported hw max132131 * @xor_check_result: result of zero sum133132 * @crc32_result: result crc calculation134133 */···144145 u16 unmap_src_cnt;145146 u32 value;146147 size_t unmap_len;148148+ struct list_head tx_list;147149 struct dma_async_tx_descriptor async_tx;148150 union {149151 u32 *xor_check_result;
+786
drivers/dma/shdma.c
···11+/*22+ * Renesas SuperH DMA Engine support33+ *44+ * base is drivers/dma/flsdma.c55+ *66+ * Copyright (C) 2009 Nobuhiro Iwamatsu <iwamatsu.nobuhiro@renesas.com>77+ * Copyright (C) 2009 Renesas Solutions, Inc. All rights reserved.88+ * Copyright (C) 2007 Freescale Semiconductor, Inc. All rights reserved.99+ *1010+ * This is free software; you can redistribute it and/or modify1111+ * it under the terms of the GNU General Public License as published by1212+ * the Free Software Foundation; either version 2 of the License, or1313+ * (at your option) any later version.1414+ *1515+ * - DMA of SuperH does not have Hardware DMA chain mode.1616+ * - MAX DMA size is 16MB.1717+ *1818+ */1919+2020+#include <linux/init.h>2121+#include <linux/module.h>2222+#include <linux/interrupt.h>2323+#include <linux/dmaengine.h>2424+#include <linux/delay.h>2525+#include <linux/dma-mapping.h>2626+#include <linux/dmapool.h>2727+#include <linux/platform_device.h>2828+#include <cpu/dma.h>2929+#include <asm/dma-sh.h>3030+#include "shdma.h"3131+3232+/* DMA descriptor control */3333+#define DESC_LAST (-1)3434+#define DESC_COMP (1)3535+#define DESC_NCOMP (0)3636+3737+#define NR_DESCS_PER_CHANNEL 323838+/*3939+ * Define the default configuration for dual address memory-memory transfer.4040+ * The 0x400 value represents auto-request, external->external.4141+ *4242+ * And this driver set 4byte burst mode.4343+ * If you want to change mode, you need to change RS_DEFAULT of value.4444+ * (ex 1byte burst mode -> (RS_DUAL & ~TS_32)4545+ */4646+#define RS_DEFAULT (RS_DUAL)4747+4848+#define SH_DMAC_CHAN_BASE(id) (dma_base_addr[id])4949+static void sh_dmae_writel(struct sh_dmae_chan *sh_dc, u32 data, u32 reg)5050+{5151+ ctrl_outl(data, (SH_DMAC_CHAN_BASE(sh_dc->id) + reg));5252+}5353+5454+static u32 sh_dmae_readl(struct sh_dmae_chan *sh_dc, u32 reg)5555+{5656+ return ctrl_inl((SH_DMAC_CHAN_BASE(sh_dc->id) + reg));5757+}5858+5959+static void dmae_init(struct sh_dmae_chan *sh_chan)6060+{6161+ u32 chcr = RS_DEFAULT; /* default is DUAL mode */6262+ sh_dmae_writel(sh_chan, chcr, CHCR);6363+}6464+6565+/*6666+ * Reset DMA controller6767+ *6868+ * SH7780 has two DMAOR register6969+ */7070+static void sh_dmae_ctl_stop(int id)7171+{7272+ unsigned short dmaor = dmaor_read_reg(id);7373+7474+ dmaor &= ~(DMAOR_NMIF | DMAOR_AE);7575+ dmaor_write_reg(id, dmaor);7676+}7777+7878+static int sh_dmae_rst(int id)7979+{8080+ unsigned short dmaor;8181+8282+ sh_dmae_ctl_stop(id);8383+ dmaor = (dmaor_read_reg(id)|DMAOR_INIT);8484+8585+ dmaor_write_reg(id, dmaor);8686+ if ((dmaor_read_reg(id) & (DMAOR_AE | DMAOR_NMIF))) {8787+ pr_warning(KERN_ERR "dma-sh: Can't initialize DMAOR.\n");8888+ return -EINVAL;8989+ }9090+ return 0;9191+}9292+9393+static int dmae_is_idle(struct sh_dmae_chan *sh_chan)9494+{9595+ u32 chcr = sh_dmae_readl(sh_chan, CHCR);9696+ if (chcr & CHCR_DE) {9797+ if (!(chcr & CHCR_TE))9898+ return -EBUSY; /* working */9999+ }100100+ return 0; /* waiting */101101+}102102+103103+static inline unsigned int calc_xmit_shift(struct sh_dmae_chan *sh_chan)104104+{105105+ u32 chcr = sh_dmae_readl(sh_chan, CHCR);106106+ return ts_shift[(chcr & CHCR_TS_MASK) >> CHCR_TS_SHIFT];107107+}108108+109109+static void dmae_set_reg(struct sh_dmae_chan *sh_chan, struct sh_dmae_regs hw)110110+{111111+ sh_dmae_writel(sh_chan, hw.sar, SAR);112112+ sh_dmae_writel(sh_chan, hw.dar, DAR);113113+ sh_dmae_writel(sh_chan,114114+ (hw.tcr >> calc_xmit_shift(sh_chan)), TCR);115115+}116116+117117+static void dmae_start(struct sh_dmae_chan *sh_chan)118118+{119119+ u32 chcr = sh_dmae_readl(sh_chan, CHCR);120120+121121+ chcr |= (CHCR_DE|CHCR_IE);122122+ sh_dmae_writel(sh_chan, chcr, CHCR);123123+}124124+125125+static void dmae_halt(struct sh_dmae_chan *sh_chan)126126+{127127+ u32 chcr = sh_dmae_readl(sh_chan, CHCR);128128+129129+ chcr &= ~(CHCR_DE | CHCR_TE | CHCR_IE);130130+ sh_dmae_writel(sh_chan, chcr, CHCR);131131+}132132+133133+static int dmae_set_chcr(struct sh_dmae_chan *sh_chan, u32 val)134134+{135135+ int ret = dmae_is_idle(sh_chan);136136+ /* When DMA was working, can not set data to CHCR */137137+ if (ret)138138+ return ret;139139+140140+ sh_dmae_writel(sh_chan, val, CHCR);141141+ return 0;142142+}143143+144144+#define DMARS1_ADDR 0x04145145+#define DMARS2_ADDR 0x08146146+#define DMARS_SHIFT 8147147+#define DMARS_CHAN_MSK 0x01148148+static int dmae_set_dmars(struct sh_dmae_chan *sh_chan, u16 val)149149+{150150+ u32 addr;151151+ int shift = 0;152152+ int ret = dmae_is_idle(sh_chan);153153+ if (ret)154154+ return ret;155155+156156+ if (sh_chan->id & DMARS_CHAN_MSK)157157+ shift = DMARS_SHIFT;158158+159159+ switch (sh_chan->id) {160160+ /* DMARS0 */161161+ case 0:162162+ case 1:163163+ addr = SH_DMARS_BASE;164164+ break;165165+ /* DMARS1 */166166+ case 2:167167+ case 3:168168+ addr = (SH_DMARS_BASE + DMARS1_ADDR);169169+ break;170170+ /* DMARS2 */171171+ case 4:172172+ case 5:173173+ addr = (SH_DMARS_BASE + DMARS2_ADDR);174174+ break;175175+ default:176176+ return -EINVAL;177177+ }178178+179179+ ctrl_outw((val << shift) |180180+ (ctrl_inw(addr) & (shift ? 0xFF00 : 0x00FF)),181181+ addr);182182+183183+ return 0;184184+}185185+186186+static dma_cookie_t sh_dmae_tx_submit(struct dma_async_tx_descriptor *tx)187187+{188188+ struct sh_desc *desc = tx_to_sh_desc(tx);189189+ struct sh_dmae_chan *sh_chan = to_sh_chan(tx->chan);190190+ dma_cookie_t cookie;191191+192192+ spin_lock_bh(&sh_chan->desc_lock);193193+194194+ cookie = sh_chan->common.cookie;195195+ cookie++;196196+ if (cookie < 0)197197+ cookie = 1;198198+199199+ /* If desc only in the case of 1 */200200+ if (desc->async_tx.cookie != -EBUSY)201201+ desc->async_tx.cookie = cookie;202202+ sh_chan->common.cookie = desc->async_tx.cookie;203203+204204+ list_splice_init(&desc->tx_list, sh_chan->ld_queue.prev);205205+206206+ spin_unlock_bh(&sh_chan->desc_lock);207207+208208+ return cookie;209209+}210210+211211+static struct sh_desc *sh_dmae_get_desc(struct sh_dmae_chan *sh_chan)212212+{213213+ struct sh_desc *desc, *_desc, *ret = NULL;214214+215215+ spin_lock_bh(&sh_chan->desc_lock);216216+ list_for_each_entry_safe(desc, _desc, &sh_chan->ld_free, node) {217217+ if (async_tx_test_ack(&desc->async_tx)) {218218+ list_del(&desc->node);219219+ ret = desc;220220+ break;221221+ }222222+ }223223+ spin_unlock_bh(&sh_chan->desc_lock);224224+225225+ return ret;226226+}227227+228228+static void sh_dmae_put_desc(struct sh_dmae_chan *sh_chan, struct sh_desc *desc)229229+{230230+ if (desc) {231231+ spin_lock_bh(&sh_chan->desc_lock);232232+233233+ list_splice_init(&desc->tx_list, &sh_chan->ld_free);234234+ list_add(&desc->node, &sh_chan->ld_free);235235+236236+ spin_unlock_bh(&sh_chan->desc_lock);237237+ }238238+}239239+240240+static int sh_dmae_alloc_chan_resources(struct dma_chan *chan)241241+{242242+ struct sh_dmae_chan *sh_chan = to_sh_chan(chan);243243+ struct sh_desc *desc;244244+245245+ spin_lock_bh(&sh_chan->desc_lock);246246+ while (sh_chan->descs_allocated < NR_DESCS_PER_CHANNEL) {247247+ spin_unlock_bh(&sh_chan->desc_lock);248248+ desc = kzalloc(sizeof(struct sh_desc), GFP_KERNEL);249249+ if (!desc) {250250+ spin_lock_bh(&sh_chan->desc_lock);251251+ break;252252+ }253253+ dma_async_tx_descriptor_init(&desc->async_tx,254254+ &sh_chan->common);255255+ desc->async_tx.tx_submit = sh_dmae_tx_submit;256256+ desc->async_tx.flags = DMA_CTRL_ACK;257257+ INIT_LIST_HEAD(&desc->tx_list);258258+ sh_dmae_put_desc(sh_chan, desc);259259+260260+ spin_lock_bh(&sh_chan->desc_lock);261261+ sh_chan->descs_allocated++;262262+ }263263+ spin_unlock_bh(&sh_chan->desc_lock);264264+265265+ return sh_chan->descs_allocated;266266+}267267+268268+/*269269+ * sh_dma_free_chan_resources - Free all resources of the channel.270270+ */271271+static void sh_dmae_free_chan_resources(struct dma_chan *chan)272272+{273273+ struct sh_dmae_chan *sh_chan = to_sh_chan(chan);274274+ struct sh_desc *desc, *_desc;275275+ LIST_HEAD(list);276276+277277+ BUG_ON(!list_empty(&sh_chan->ld_queue));278278+ spin_lock_bh(&sh_chan->desc_lock);279279+280280+ list_splice_init(&sh_chan->ld_free, &list);281281+ sh_chan->descs_allocated = 0;282282+283283+ spin_unlock_bh(&sh_chan->desc_lock);284284+285285+ list_for_each_entry_safe(desc, _desc, &list, node)286286+ kfree(desc);287287+}288288+289289+static struct dma_async_tx_descriptor *sh_dmae_prep_memcpy(290290+ struct dma_chan *chan, dma_addr_t dma_dest, dma_addr_t dma_src,291291+ size_t len, unsigned long flags)292292+{293293+ struct sh_dmae_chan *sh_chan;294294+ struct sh_desc *first = NULL, *prev = NULL, *new;295295+ size_t copy_size;296296+297297+ if (!chan)298298+ return NULL;299299+300300+ if (!len)301301+ return NULL;302302+303303+ sh_chan = to_sh_chan(chan);304304+305305+ do {306306+ /* Allocate the link descriptor from DMA pool */307307+ new = sh_dmae_get_desc(sh_chan);308308+ if (!new) {309309+ dev_err(sh_chan->dev,310310+ "No free memory for link descriptor\n");311311+ goto err_get_desc;312312+ }313313+314314+ copy_size = min(len, (size_t)SH_DMA_TCR_MAX);315315+316316+ new->hw.sar = dma_src;317317+ new->hw.dar = dma_dest;318318+ new->hw.tcr = copy_size;319319+ if (!first)320320+ first = new;321321+322322+ new->mark = DESC_NCOMP;323323+ async_tx_ack(&new->async_tx);324324+325325+ prev = new;326326+ len -= copy_size;327327+ dma_src += copy_size;328328+ dma_dest += copy_size;329329+ /* Insert the link descriptor to the LD ring */330330+ list_add_tail(&new->node, &first->tx_list);331331+ } while (len);332332+333333+ new->async_tx.flags = flags; /* client is in control of this ack */334334+ new->async_tx.cookie = -EBUSY; /* Last desc */335335+336336+ return &first->async_tx;337337+338338+err_get_desc:339339+ sh_dmae_put_desc(sh_chan, first);340340+ return NULL;341341+342342+}343343+344344+/*345345+ * sh_chan_ld_cleanup - Clean up link descriptors346346+ *347347+ * This function clean up the ld_queue of DMA channel.348348+ */349349+static void sh_dmae_chan_ld_cleanup(struct sh_dmae_chan *sh_chan)350350+{351351+ struct sh_desc *desc, *_desc;352352+353353+ spin_lock_bh(&sh_chan->desc_lock);354354+ list_for_each_entry_safe(desc, _desc, &sh_chan->ld_queue, node) {355355+ dma_async_tx_callback callback;356356+ void *callback_param;357357+358358+ /* non send data */359359+ if (desc->mark == DESC_NCOMP)360360+ break;361361+362362+ /* send data sesc */363363+ callback = desc->async_tx.callback;364364+ callback_param = desc->async_tx.callback_param;365365+366366+ /* Remove from ld_queue list */367367+ list_splice_init(&desc->tx_list, &sh_chan->ld_free);368368+369369+ dev_dbg(sh_chan->dev, "link descriptor %p will be recycle.\n",370370+ desc);371371+372372+ list_move(&desc->node, &sh_chan->ld_free);373373+ /* Run the link descriptor callback function */374374+ if (callback) {375375+ spin_unlock_bh(&sh_chan->desc_lock);376376+ dev_dbg(sh_chan->dev, "link descriptor %p callback\n",377377+ desc);378378+ callback(callback_param);379379+ spin_lock_bh(&sh_chan->desc_lock);380380+ }381381+ }382382+ spin_unlock_bh(&sh_chan->desc_lock);383383+}384384+385385+static void sh_chan_xfer_ld_queue(struct sh_dmae_chan *sh_chan)386386+{387387+ struct list_head *ld_node;388388+ struct sh_dmae_regs hw;389389+390390+ /* DMA work check */391391+ if (dmae_is_idle(sh_chan))392392+ return;393393+394394+ /* Find the first un-transfer desciptor */395395+ for (ld_node = sh_chan->ld_queue.next;396396+ (ld_node != &sh_chan->ld_queue)397397+ && (to_sh_desc(ld_node)->mark == DESC_COMP);398398+ ld_node = ld_node->next)399399+ cpu_relax();400400+401401+ if (ld_node != &sh_chan->ld_queue) {402402+ /* Get the ld start address from ld_queue */403403+ hw = to_sh_desc(ld_node)->hw;404404+ dmae_set_reg(sh_chan, hw);405405+ dmae_start(sh_chan);406406+ }407407+}408408+409409+static void sh_dmae_memcpy_issue_pending(struct dma_chan *chan)410410+{411411+ struct sh_dmae_chan *sh_chan = to_sh_chan(chan);412412+ sh_chan_xfer_ld_queue(sh_chan);413413+}414414+415415+static enum dma_status sh_dmae_is_complete(struct dma_chan *chan,416416+ dma_cookie_t cookie,417417+ dma_cookie_t *done,418418+ dma_cookie_t *used)419419+{420420+ struct sh_dmae_chan *sh_chan = to_sh_chan(chan);421421+ dma_cookie_t last_used;422422+ dma_cookie_t last_complete;423423+424424+ sh_dmae_chan_ld_cleanup(sh_chan);425425+426426+ last_used = chan->cookie;427427+ last_complete = sh_chan->completed_cookie;428428+ if (last_complete == -EBUSY)429429+ last_complete = last_used;430430+431431+ if (done)432432+ *done = last_complete;433433+434434+ if (used)435435+ *used = last_used;436436+437437+ return dma_async_is_complete(cookie, last_complete, last_used);438438+}439439+440440+static irqreturn_t sh_dmae_interrupt(int irq, void *data)441441+{442442+ irqreturn_t ret = IRQ_NONE;443443+ struct sh_dmae_chan *sh_chan = (struct sh_dmae_chan *)data;444444+ u32 chcr = sh_dmae_readl(sh_chan, CHCR);445445+446446+ if (chcr & CHCR_TE) {447447+ /* DMA stop */448448+ dmae_halt(sh_chan);449449+450450+ ret = IRQ_HANDLED;451451+ tasklet_schedule(&sh_chan->tasklet);452452+ }453453+454454+ return ret;455455+}456456+457457+#if defined(CONFIG_CPU_SH4)458458+static irqreturn_t sh_dmae_err(int irq, void *data)459459+{460460+ int err = 0;461461+ struct sh_dmae_device *shdev = (struct sh_dmae_device *)data;462462+463463+ /* IRQ Multi */464464+ if (shdev->pdata.mode & SHDMA_MIX_IRQ) {465465+ int cnt = 0;466466+ switch (irq) {467467+#if defined(DMTE6_IRQ) && defined(DMAE1_IRQ)468468+ case DMTE6_IRQ:469469+ cnt++;470470+#endif471471+ case DMTE0_IRQ:472472+ if (dmaor_read_reg(cnt) & (DMAOR_NMIF | DMAOR_AE)) {473473+ disable_irq(irq);474474+ return IRQ_HANDLED;475475+ }476476+ default:477477+ return IRQ_NONE;478478+ }479479+ } else {480480+ /* reset dma controller */481481+ err = sh_dmae_rst(0);482482+ if (err)483483+ return err;484484+ if (shdev->pdata.mode & SHDMA_DMAOR1) {485485+ err = sh_dmae_rst(1);486486+ if (err)487487+ return err;488488+ }489489+ disable_irq(irq);490490+ return IRQ_HANDLED;491491+ }492492+}493493+#endif494494+495495+static void dmae_do_tasklet(unsigned long data)496496+{497497+ struct sh_dmae_chan *sh_chan = (struct sh_dmae_chan *)data;498498+ struct sh_desc *desc, *_desc, *cur_desc = NULL;499499+ u32 sar_buf = sh_dmae_readl(sh_chan, SAR);500500+ list_for_each_entry_safe(desc, _desc,501501+ &sh_chan->ld_queue, node) {502502+ if ((desc->hw.sar + desc->hw.tcr) == sar_buf) {503503+ cur_desc = desc;504504+ break;505505+ }506506+ }507507+508508+ if (cur_desc) {509509+ switch (cur_desc->async_tx.cookie) {510510+ case 0: /* other desc data */511511+ break;512512+ case -EBUSY: /* last desc */513513+ sh_chan->completed_cookie =514514+ cur_desc->async_tx.cookie;515515+ break;516516+ default: /* first desc ( 0 < )*/517517+ sh_chan->completed_cookie =518518+ cur_desc->async_tx.cookie - 1;519519+ break;520520+ }521521+ cur_desc->mark = DESC_COMP;522522+ }523523+ /* Next desc */524524+ sh_chan_xfer_ld_queue(sh_chan);525525+ sh_dmae_chan_ld_cleanup(sh_chan);526526+}527527+528528+static unsigned int get_dmae_irq(unsigned int id)529529+{530530+ unsigned int irq = 0;531531+ if (id < ARRAY_SIZE(dmte_irq_map))532532+ irq = dmte_irq_map[id];533533+ return irq;534534+}535535+536536+static int __devinit sh_dmae_chan_probe(struct sh_dmae_device *shdev, int id)537537+{538538+ int err;539539+ unsigned int irq = get_dmae_irq(id);540540+ unsigned long irqflags = IRQF_DISABLED;541541+ struct sh_dmae_chan *new_sh_chan;542542+543543+ /* alloc channel */544544+ new_sh_chan = kzalloc(sizeof(struct sh_dmae_chan), GFP_KERNEL);545545+ if (!new_sh_chan) {546546+ dev_err(shdev->common.dev, "No free memory for allocating "547547+ "dma channels!\n");548548+ return -ENOMEM;549549+ }550550+551551+ new_sh_chan->dev = shdev->common.dev;552552+ new_sh_chan->id = id;553553+554554+ /* Init DMA tasklet */555555+ tasklet_init(&new_sh_chan->tasklet, dmae_do_tasklet,556556+ (unsigned long)new_sh_chan);557557+558558+ /* Init the channel */559559+ dmae_init(new_sh_chan);560560+561561+ spin_lock_init(&new_sh_chan->desc_lock);562562+563563+ /* Init descripter manage list */564564+ INIT_LIST_HEAD(&new_sh_chan->ld_queue);565565+ INIT_LIST_HEAD(&new_sh_chan->ld_free);566566+567567+ /* copy struct dma_device */568568+ new_sh_chan->common.device = &shdev->common;569569+570570+ /* Add the channel to DMA device channel list */571571+ list_add_tail(&new_sh_chan->common.device_node,572572+ &shdev->common.channels);573573+ shdev->common.chancnt++;574574+575575+ if (shdev->pdata.mode & SHDMA_MIX_IRQ) {576576+ irqflags = IRQF_SHARED;577577+#if defined(DMTE6_IRQ)578578+ if (irq >= DMTE6_IRQ)579579+ irq = DMTE6_IRQ;580580+ else581581+#endif582582+ irq = DMTE0_IRQ;583583+ }584584+585585+ snprintf(new_sh_chan->dev_id, sizeof(new_sh_chan->dev_id),586586+ "sh-dmae%d", new_sh_chan->id);587587+588588+ /* set up channel irq */589589+ err = request_irq(irq, &sh_dmae_interrupt,590590+ irqflags, new_sh_chan->dev_id, new_sh_chan);591591+ if (err) {592592+ dev_err(shdev->common.dev, "DMA channel %d request_irq error "593593+ "with return %d\n", id, err);594594+ goto err_no_irq;595595+ }596596+597597+ /* CHCR register control function */598598+ new_sh_chan->set_chcr = dmae_set_chcr;599599+ /* DMARS register control function */600600+ new_sh_chan->set_dmars = dmae_set_dmars;601601+602602+ shdev->chan[id] = new_sh_chan;603603+ return 0;604604+605605+err_no_irq:606606+ /* remove from dmaengine device node */607607+ list_del(&new_sh_chan->common.device_node);608608+ kfree(new_sh_chan);609609+ return err;610610+}611611+612612+static void sh_dmae_chan_remove(struct sh_dmae_device *shdev)613613+{614614+ int i;615615+616616+ for (i = shdev->common.chancnt - 1 ; i >= 0 ; i--) {617617+ if (shdev->chan[i]) {618618+ struct sh_dmae_chan *shchan = shdev->chan[i];619619+ if (!(shdev->pdata.mode & SHDMA_MIX_IRQ))620620+ free_irq(dmte_irq_map[i], shchan);621621+622622+ list_del(&shchan->common.device_node);623623+ kfree(shchan);624624+ shdev->chan[i] = NULL;625625+ }626626+ }627627+ shdev->common.chancnt = 0;628628+}629629+630630+static int __init sh_dmae_probe(struct platform_device *pdev)631631+{632632+ int err = 0, cnt, ecnt;633633+ unsigned long irqflags = IRQF_DISABLED;634634+#if defined(CONFIG_CPU_SH4)635635+ int eirq[] = { DMAE0_IRQ,636636+#if defined(DMAE1_IRQ)637637+ DMAE1_IRQ638638+#endif639639+ };640640+#endif641641+ struct sh_dmae_device *shdev;642642+643643+ shdev = kzalloc(sizeof(struct sh_dmae_device), GFP_KERNEL);644644+ if (!shdev) {645645+ dev_err(&pdev->dev, "No enough memory\n");646646+ err = -ENOMEM;647647+ goto shdev_err;648648+ }649649+650650+ /* get platform data */651651+ if (!pdev->dev.platform_data)652652+ goto shdev_err;653653+654654+ /* platform data */655655+ memcpy(&shdev->pdata, pdev->dev.platform_data,656656+ sizeof(struct sh_dmae_pdata));657657+658658+ /* reset dma controller */659659+ err = sh_dmae_rst(0);660660+ if (err)661661+ goto rst_err;662662+663663+ /* SH7780/85/23 has DMAOR1 */664664+ if (shdev->pdata.mode & SHDMA_DMAOR1) {665665+ err = sh_dmae_rst(1);666666+ if (err)667667+ goto rst_err;668668+ }669669+670670+ INIT_LIST_HEAD(&shdev->common.channels);671671+672672+ dma_cap_set(DMA_MEMCPY, shdev->common.cap_mask);673673+ shdev->common.device_alloc_chan_resources674674+ = sh_dmae_alloc_chan_resources;675675+ shdev->common.device_free_chan_resources = sh_dmae_free_chan_resources;676676+ shdev->common.device_prep_dma_memcpy = sh_dmae_prep_memcpy;677677+ shdev->common.device_is_tx_complete = sh_dmae_is_complete;678678+ shdev->common.device_issue_pending = sh_dmae_memcpy_issue_pending;679679+ shdev->common.dev = &pdev->dev;680680+681681+#if defined(CONFIG_CPU_SH4)682682+ /* Non Mix IRQ mode SH7722/SH7730 etc... */683683+ if (shdev->pdata.mode & SHDMA_MIX_IRQ) {684684+ irqflags = IRQF_SHARED;685685+ eirq[0] = DMTE0_IRQ;686686+#if defined(DMTE6_IRQ) && defined(DMAE1_IRQ)687687+ eirq[1] = DMTE6_IRQ;688688+#endif689689+ }690690+691691+ for (ecnt = 0 ; ecnt < ARRAY_SIZE(eirq); ecnt++) {692692+ err = request_irq(eirq[ecnt], sh_dmae_err,693693+ irqflags, "DMAC Address Error", shdev);694694+ if (err) {695695+ dev_err(&pdev->dev, "DMA device request_irq"696696+ "error (irq %d) with return %d\n",697697+ eirq[ecnt], err);698698+ goto eirq_err;699699+ }700700+ }701701+#endif /* CONFIG_CPU_SH4 */702702+703703+ /* Create DMA Channel */704704+ for (cnt = 0 ; cnt < MAX_DMA_CHANNELS ; cnt++) {705705+ err = sh_dmae_chan_probe(shdev, cnt);706706+ if (err)707707+ goto chan_probe_err;708708+ }709709+710710+ platform_set_drvdata(pdev, shdev);711711+ dma_async_device_register(&shdev->common);712712+713713+ return err;714714+715715+chan_probe_err:716716+ sh_dmae_chan_remove(shdev);717717+718718+eirq_err:719719+ for (ecnt-- ; ecnt >= 0; ecnt--)720720+ free_irq(eirq[ecnt], shdev);721721+722722+rst_err:723723+ kfree(shdev);724724+725725+shdev_err:726726+ return err;727727+}728728+729729+static int __exit sh_dmae_remove(struct platform_device *pdev)730730+{731731+ struct sh_dmae_device *shdev = platform_get_drvdata(pdev);732732+733733+ dma_async_device_unregister(&shdev->common);734734+735735+ if (shdev->pdata.mode & SHDMA_MIX_IRQ) {736736+ free_irq(DMTE0_IRQ, shdev);737737+#if defined(DMTE6_IRQ)738738+ free_irq(DMTE6_IRQ, shdev);739739+#endif740740+ }741741+742742+ /* channel data remove */743743+ sh_dmae_chan_remove(shdev);744744+745745+ if (!(shdev->pdata.mode & SHDMA_MIX_IRQ)) {746746+ free_irq(DMAE0_IRQ, shdev);747747+#if defined(DMAE1_IRQ)748748+ free_irq(DMAE1_IRQ, shdev);749749+#endif750750+ }751751+ kfree(shdev);752752+753753+ return 0;754754+}755755+756756+static void sh_dmae_shutdown(struct platform_device *pdev)757757+{758758+ struct sh_dmae_device *shdev = platform_get_drvdata(pdev);759759+ sh_dmae_ctl_stop(0);760760+ if (shdev->pdata.mode & SHDMA_DMAOR1)761761+ sh_dmae_ctl_stop(1);762762+}763763+764764+static struct platform_driver sh_dmae_driver = {765765+ .remove = __exit_p(sh_dmae_remove),766766+ .shutdown = sh_dmae_shutdown,767767+ .driver = {768768+ .name = "sh-dma-engine",769769+ },770770+};771771+772772+static int __init sh_dmae_init(void)773773+{774774+ return platform_driver_probe(&sh_dmae_driver, sh_dmae_probe);775775+}776776+module_init(sh_dmae_init);777777+778778+static void __exit sh_dmae_exit(void)779779+{780780+ platform_driver_unregister(&sh_dmae_driver);781781+}782782+module_exit(sh_dmae_exit);783783+784784+MODULE_AUTHOR("Nobuhiro Iwamatsu <iwamatsu.nobuhiro@renesas.com>");785785+MODULE_DESCRIPTION("Renesas SH DMA Engine driver");786786+MODULE_LICENSE("GPL");
+64
drivers/dma/shdma.h
···11+/*22+ * Renesas SuperH DMA Engine support33+ *44+ * Copyright (C) 2009 Nobuhiro Iwamatsu <iwamatsu.nobuhiro@renesas.com>55+ * Copyright (C) 2009 Renesas Solutions, Inc. All rights reserved.66+ *77+ * This is free software; you can redistribute it and/or modify88+ * it under the terms of the GNU General Public License as published by99+ * the Free Software Foundation; either version 2 of the License, or1010+ * (at your option) any later version.1111+ *1212+ */1313+#ifndef __DMA_SHDMA_H1414+#define __DMA_SHDMA_H1515+1616+#include <linux/device.h>1717+#include <linux/dmapool.h>1818+#include <linux/dmaengine.h>1919+2020+#define SH_DMA_TCR_MAX 0x00FFFFFF /* 16MB */2121+2222+struct sh_dmae_regs {2323+ u32 sar; /* SAR / source address */2424+ u32 dar; /* DAR / destination address */2525+ u32 tcr; /* TCR / transfer count */2626+};2727+2828+struct sh_desc {2929+ struct list_head tx_list;3030+ struct sh_dmae_regs hw;3131+ struct list_head node;3232+ struct dma_async_tx_descriptor async_tx;3333+ int mark;3434+};3535+3636+struct sh_dmae_chan {3737+ dma_cookie_t completed_cookie; /* The maximum cookie completed */3838+ spinlock_t desc_lock; /* Descriptor operation lock */3939+ struct list_head ld_queue; /* Link descriptors queue */4040+ struct list_head ld_free; /* Link descriptors free */4141+ struct dma_chan common; /* DMA common channel */4242+ struct device *dev; /* Channel device */4343+ struct tasklet_struct tasklet; /* Tasklet */4444+ int descs_allocated; /* desc count */4545+ int id; /* Raw id of this channel */4646+ char dev_id[16]; /* unique name per DMAC of channel */4747+4848+ /* Set chcr */4949+ int (*set_chcr)(struct sh_dmae_chan *sh_chan, u32 regs);5050+ /* Set DMA resource */5151+ int (*set_dmars)(struct sh_dmae_chan *sh_chan, u16 res);5252+};5353+5454+struct sh_dmae_device {5555+ struct dma_device common;5656+ struct sh_dmae_chan *chan[MAX_DMA_CHANNELS];5757+ struct sh_dmae_pdata pdata;5858+};5959+6060+#define to_sh_chan(chan) container_of(chan, struct sh_dmae_chan, common)6161+#define to_sh_desc(lh) container_of(lh, struct sh_desc, node)6262+#define tx_to_sh_desc(tx) container_of(tx, struct sh_desc, async_tx)6363+6464+#endif /* __DMA_SHDMA_H */
···231231232232 /* THEN values for driver housekeeping */233233 struct list_head desc_node ____cacheline_aligned;234234+ struct list_head tx_list;234235 struct dma_async_tx_descriptor txd;235236 size_t len;236237};
+10-10
drivers/idle/i7300_idle.c
···29293030#include <asm/idle.h>31313232-#include "../dma/ioatdma_hw.h"3333-#include "../dma/ioatdma_registers.h"3232+#include "../dma/ioat/hw.h"3333+#include "../dma/ioat/registers.h"34343535#define I7300_IDLE_DRIVER_VERSION "1.55"3636#define I7300_PRINT "i7300_idle:"···126126 udelay(10);127127128128 sts = readq(ioat_chanbase + IOAT1_CHANSTS_OFFSET) &129129- IOAT_CHANSTS_DMA_TRANSFER_STATUS;129129+ IOAT_CHANSTS_STATUS;130130131131- if (sts != IOAT_CHANSTS_DMA_TRANSFER_STATUS_ACTIVE)131131+ if (sts != IOAT_CHANSTS_ACTIVE)132132 break;133133134134 }···160160 udelay(1000);161161162162 chan_sts = readq(ioat_chanbase + IOAT1_CHANSTS_OFFSET) &163163- IOAT_CHANSTS_DMA_TRANSFER_STATUS;163163+ IOAT_CHANSTS_STATUS;164164165165- if (chan_sts != IOAT_CHANSTS_DMA_TRANSFER_STATUS_DONE) {165165+ if (chan_sts != IOAT_CHANSTS_DONE) {166166 /* Not complete, reset the channel */167167 writeb(IOAT_CHANCMD_RESET,168168 ioat_chanbase + IOAT1_CHANCMD_OFFSET);···288288 ioat_chanbase + IOAT1_CHANCMD_OFFSET);289289290290 chan_sts = readq(ioat_chanbase + IOAT1_CHANSTS_OFFSET) &291291- IOAT_CHANSTS_DMA_TRANSFER_STATUS;291291+ IOAT_CHANSTS_STATUS;292292293293- if (chan_sts != IOAT_CHANSTS_DMA_TRANSFER_STATUS_ACTIVE) {293293+ if (chan_sts != IOAT_CHANSTS_ACTIVE) {294294 writew(0, ioat_chanbase + IOAT_CHANCTRL_OFFSET);295295 break;296296 }···298298 }299299300300 chan_sts = readq(ioat_chanbase + IOAT1_CHANSTS_OFFSET) &301301- IOAT_CHANSTS_DMA_TRANSFER_STATUS;301301+ IOAT_CHANSTS_STATUS;302302303303 /*304304 * We tried to reset multiple times. If IO A/T channel is still active305305 * flag an error and return without cleanup. Memory leak is better306306 * than random corruption in that extreme error situation.307307 */308308- if (chan_sts == IOAT_CHANSTS_DMA_TRANSFER_STATUS_ACTIVE) {308308+ if (chan_sts == IOAT_CHANSTS_ACTIVE) {309309 printk(KERN_ERR I7300_PRINT "Unable to stop IO A/T channels."310310 " Not freeing resources\n");311311 return;
+26
drivers/md/Kconfig
···124124 select MD_RAID6_PQ125125 select ASYNC_MEMCPY126126 select ASYNC_XOR127127+ select ASYNC_PQ128128+ select ASYNC_RAID6_RECOV127129 ---help---128130 A RAID-5 set of N drives with a capacity of C MB per drive provides129131 the capacity of C * (N - 1) MB, and protects against a failure···154152155153 If unsure, say Y.156154155155+config MULTICORE_RAID456156156+ bool "RAID-4/RAID-5/RAID-6 Multicore processing (EXPERIMENTAL)"157157+ depends on MD_RAID456158158+ depends on SMP159159+ depends on EXPERIMENTAL160160+ ---help---161161+ Enable the raid456 module to dispatch per-stripe raid operations to a162162+ thread pool.163163+164164+ If unsure, say N.165165+157166config MD_RAID6_PQ158167 tristate168168+169169+config ASYNC_RAID6_TEST170170+ tristate "Self test for hardware accelerated raid6 recovery"171171+ depends on MD_RAID6_PQ172172+ select ASYNC_RAID6_RECOV173173+ ---help---174174+ This is a one-shot self test that permutes through the175175+ recovery of all the possible two disk failure scenarios for a176176+ N-disk array. Recovery is performed with the asynchronous177177+ raid6 recovery routines, and will optionally use an offload178178+ engine if one is available.179179+180180+ If unsure, say N.159181160182config MD_MULTIPATH161183 tristate "Multipath I/O support"
+913-562
drivers/md/raid5.c
···4747#include <linux/kthread.h>4848#include <linux/raid/pq.h>4949#include <linux/async_tx.h>5050+#include <linux/async.h>5051#include <linux/seq_file.h>5252+#include <linux/cpu.h>5153#include "md.h"5254#include "raid5.h"5355#include "bitmap.h"···501499 struct page *bio_page;502500 int i;503501 int page_offset;502502+ struct async_submit_ctl submit;503503+ enum async_tx_flags flags = 0;504504505505 if (bio->bi_sector >= sector)506506 page_offset = (signed)(bio->bi_sector - sector) * 512;507507 else508508 page_offset = (signed)(sector - bio->bi_sector) * -512;509509+510510+ if (frombio)511511+ flags |= ASYNC_TX_FENCE;512512+ init_async_submit(&submit, flags, tx, NULL, NULL, NULL);513513+509514 bio_for_each_segment(bvl, bio, i) {510515 int len = bio_iovec_idx(bio, i)->bv_len;511516 int clen;···534525 bio_page = bio_iovec_idx(bio, i)->bv_page;535526 if (frombio)536527 tx = async_memcpy(page, bio_page, page_offset,537537- b_offset, clen,538538- ASYNC_TX_DEP_ACK,539539- tx, NULL, NULL);528528+ b_offset, clen, &submit);540529 else541530 tx = async_memcpy(bio_page, page, b_offset,542542- page_offset, clen,543543- ASYNC_TX_DEP_ACK,544544- tx, NULL, NULL);531531+ page_offset, clen, &submit);545532 }533533+ /* chain the operations */534534+ submit.depend_tx = tx;535535+546536 if (clen < len) /* hit end of page */547537 break;548538 page_offset += len;···600592{601593 struct dma_async_tx_descriptor *tx = NULL;602594 raid5_conf_t *conf = sh->raid_conf;595595+ struct async_submit_ctl submit;603596 int i;604597605598 pr_debug("%s: stripe %llu\n", __func__,···624615 }625616626617 atomic_inc(&sh->count);627627- async_trigger_callback(ASYNC_TX_DEP_ACK | ASYNC_TX_ACK, tx,628628- ops_complete_biofill, sh);618618+ init_async_submit(&submit, ASYNC_TX_ACK, tx, ops_complete_biofill, sh, NULL);619619+ async_trigger_callback(&submit);629620}630621631631-static void ops_complete_compute5(void *stripe_head_ref)622622+static void mark_target_uptodate(struct stripe_head *sh, int target)623623+{624624+ struct r5dev *tgt;625625+626626+ if (target < 0)627627+ return;628628+629629+ tgt = &sh->dev[target];630630+ set_bit(R5_UPTODATE, &tgt->flags);631631+ BUG_ON(!test_bit(R5_Wantcompute, &tgt->flags));632632+ clear_bit(R5_Wantcompute, &tgt->flags);633633+}634634+635635+static void ops_complete_compute(void *stripe_head_ref)632636{633637 struct stripe_head *sh = stripe_head_ref;634634- int target = sh->ops.target;635635- struct r5dev *tgt = &sh->dev[target];636638637639 pr_debug("%s: stripe %llu\n", __func__,638640 (unsigned long long)sh->sector);639641640640- set_bit(R5_UPTODATE, &tgt->flags);641641- BUG_ON(!test_bit(R5_Wantcompute, &tgt->flags));642642- clear_bit(R5_Wantcompute, &tgt->flags);642642+ /* mark the computed target(s) as uptodate */643643+ mark_target_uptodate(sh, sh->ops.target);644644+ mark_target_uptodate(sh, sh->ops.target2);645645+643646 clear_bit(STRIPE_COMPUTE_RUN, &sh->state);644647 if (sh->check_state == check_state_compute_run)645648 sh->check_state = check_state_compute_result;···659638 release_stripe(sh);660639}661640662662-static struct dma_async_tx_descriptor *ops_run_compute5(struct stripe_head *sh)641641+/* return a pointer to the address conversion region of the scribble buffer */642642+static addr_conv_t *to_addr_conv(struct stripe_head *sh,643643+ struct raid5_percpu *percpu)663644{664664- /* kernel stack size limits the total number of disks */645645+ return percpu->scribble + sizeof(struct page *) * (sh->disks + 2);646646+}647647+648648+static struct dma_async_tx_descriptor *649649+ops_run_compute5(struct stripe_head *sh, struct raid5_percpu *percpu)650650+{665651 int disks = sh->disks;666666- struct page *xor_srcs[disks];652652+ struct page **xor_srcs = percpu->scribble;667653 int target = sh->ops.target;668654 struct r5dev *tgt = &sh->dev[target];669655 struct page *xor_dest = tgt->page;670656 int count = 0;671657 struct dma_async_tx_descriptor *tx;658658+ struct async_submit_ctl submit;672659 int i;673660674661 pr_debug("%s: stripe %llu block: %d\n",···689660690661 atomic_inc(&sh->count);691662663663+ init_async_submit(&submit, ASYNC_TX_FENCE|ASYNC_TX_XOR_ZERO_DST, NULL,664664+ ops_complete_compute, sh, to_addr_conv(sh, percpu));692665 if (unlikely(count == 1))693693- tx = async_memcpy(xor_dest, xor_srcs[0], 0, 0, STRIPE_SIZE,694694- 0, NULL, ops_complete_compute5, sh);666666+ tx = async_memcpy(xor_dest, xor_srcs[0], 0, 0, STRIPE_SIZE, &submit);695667 else696696- tx = async_xor(xor_dest, xor_srcs, 0, count, STRIPE_SIZE,697697- ASYNC_TX_XOR_ZERO_DST, NULL,698698- ops_complete_compute5, sh);668668+ tx = async_xor(xor_dest, xor_srcs, 0, count, STRIPE_SIZE, &submit);699669700670 return tx;701671}672672+673673+/* set_syndrome_sources - populate source buffers for gen_syndrome674674+ * @srcs - (struct page *) array of size sh->disks675675+ * @sh - stripe_head to parse676676+ *677677+ * Populates srcs in proper layout order for the stripe and returns the678678+ * 'count' of sources to be used in a call to async_gen_syndrome. The P679679+ * destination buffer is recorded in srcs[count] and the Q destination680680+ * is recorded in srcs[count+1]].681681+ */682682+static int set_syndrome_sources(struct page **srcs, struct stripe_head *sh)683683+{684684+ int disks = sh->disks;685685+ int syndrome_disks = sh->ddf_layout ? disks : (disks - 2);686686+ int d0_idx = raid6_d0(sh);687687+ int count;688688+ int i;689689+690690+ for (i = 0; i < disks; i++)691691+ srcs[i] = (void *)raid6_empty_zero_page;692692+693693+ count = 0;694694+ i = d0_idx;695695+ do {696696+ int slot = raid6_idx_to_slot(i, sh, &count, syndrome_disks);697697+698698+ srcs[slot] = sh->dev[i].page;699699+ i = raid6_next_disk(i, disks);700700+ } while (i != d0_idx);701701+ BUG_ON(count != syndrome_disks);702702+703703+ return count;704704+}705705+706706+static struct dma_async_tx_descriptor *707707+ops_run_compute6_1(struct stripe_head *sh, struct raid5_percpu *percpu)708708+{709709+ int disks = sh->disks;710710+ struct page **blocks = percpu->scribble;711711+ int target;712712+ int qd_idx = sh->qd_idx;713713+ struct dma_async_tx_descriptor *tx;714714+ struct async_submit_ctl submit;715715+ struct r5dev *tgt;716716+ struct page *dest;717717+ int i;718718+ int count;719719+720720+ if (sh->ops.target < 0)721721+ target = sh->ops.target2;722722+ else if (sh->ops.target2 < 0)723723+ target = sh->ops.target;724724+ else725725+ /* we should only have one valid target */726726+ BUG();727727+ BUG_ON(target < 0);728728+ pr_debug("%s: stripe %llu block: %d\n",729729+ __func__, (unsigned long long)sh->sector, target);730730+731731+ tgt = &sh->dev[target];732732+ BUG_ON(!test_bit(R5_Wantcompute, &tgt->flags));733733+ dest = tgt->page;734734+735735+ atomic_inc(&sh->count);736736+737737+ if (target == qd_idx) {738738+ count = set_syndrome_sources(blocks, sh);739739+ blocks[count] = NULL; /* regenerating p is not necessary */740740+ BUG_ON(blocks[count+1] != dest); /* q should already be set */741741+ init_async_submit(&submit, ASYNC_TX_FENCE, NULL,742742+ ops_complete_compute, sh,743743+ to_addr_conv(sh, percpu));744744+ tx = async_gen_syndrome(blocks, 0, count+2, STRIPE_SIZE, &submit);745745+ } else {746746+ /* Compute any data- or p-drive using XOR */747747+ count = 0;748748+ for (i = disks; i-- ; ) {749749+ if (i == target || i == qd_idx)750750+ continue;751751+ blocks[count++] = sh->dev[i].page;752752+ }753753+754754+ init_async_submit(&submit, ASYNC_TX_FENCE|ASYNC_TX_XOR_ZERO_DST,755755+ NULL, ops_complete_compute, sh,756756+ to_addr_conv(sh, percpu));757757+ tx = async_xor(dest, blocks, 0, count, STRIPE_SIZE, &submit);758758+ }759759+760760+ return tx;761761+}762762+763763+static struct dma_async_tx_descriptor *764764+ops_run_compute6_2(struct stripe_head *sh, struct raid5_percpu *percpu)765765+{766766+ int i, count, disks = sh->disks;767767+ int syndrome_disks = sh->ddf_layout ? disks : disks-2;768768+ int d0_idx = raid6_d0(sh);769769+ int faila = -1, failb = -1;770770+ int target = sh->ops.target;771771+ int target2 = sh->ops.target2;772772+ struct r5dev *tgt = &sh->dev[target];773773+ struct r5dev *tgt2 = &sh->dev[target2];774774+ struct dma_async_tx_descriptor *tx;775775+ struct page **blocks = percpu->scribble;776776+ struct async_submit_ctl submit;777777+778778+ pr_debug("%s: stripe %llu block1: %d block2: %d\n",779779+ __func__, (unsigned long long)sh->sector, target, target2);780780+ BUG_ON(target < 0 || target2 < 0);781781+ BUG_ON(!test_bit(R5_Wantcompute, &tgt->flags));782782+ BUG_ON(!test_bit(R5_Wantcompute, &tgt2->flags));783783+784784+ /* we need to open-code set_syndrome_sources to handle the785785+ * slot number conversion for 'faila' and 'failb'786786+ */787787+ for (i = 0; i < disks ; i++)788788+ blocks[i] = (void *)raid6_empty_zero_page;789789+ count = 0;790790+ i = d0_idx;791791+ do {792792+ int slot = raid6_idx_to_slot(i, sh, &count, syndrome_disks);793793+794794+ blocks[slot] = sh->dev[i].page;795795+796796+ if (i == target)797797+ faila = slot;798798+ if (i == target2)799799+ failb = slot;800800+ i = raid6_next_disk(i, disks);801801+ } while (i != d0_idx);802802+ BUG_ON(count != syndrome_disks);803803+804804+ BUG_ON(faila == failb);805805+ if (failb < faila)806806+ swap(faila, failb);807807+ pr_debug("%s: stripe: %llu faila: %d failb: %d\n",808808+ __func__, (unsigned long long)sh->sector, faila, failb);809809+810810+ atomic_inc(&sh->count);811811+812812+ if (failb == syndrome_disks+1) {813813+ /* Q disk is one of the missing disks */814814+ if (faila == syndrome_disks) {815815+ /* Missing P+Q, just recompute */816816+ init_async_submit(&submit, ASYNC_TX_FENCE, NULL,817817+ ops_complete_compute, sh,818818+ to_addr_conv(sh, percpu));819819+ return async_gen_syndrome(blocks, 0, count+2,820820+ STRIPE_SIZE, &submit);821821+ } else {822822+ struct page *dest;823823+ int data_target;824824+ int qd_idx = sh->qd_idx;825825+826826+ /* Missing D+Q: recompute D from P, then recompute Q */827827+ if (target == qd_idx)828828+ data_target = target2;829829+ else830830+ data_target = target;831831+832832+ count = 0;833833+ for (i = disks; i-- ; ) {834834+ if (i == data_target || i == qd_idx)835835+ continue;836836+ blocks[count++] = sh->dev[i].page;837837+ }838838+ dest = sh->dev[data_target].page;839839+ init_async_submit(&submit,840840+ ASYNC_TX_FENCE|ASYNC_TX_XOR_ZERO_DST,841841+ NULL, NULL, NULL,842842+ to_addr_conv(sh, percpu));843843+ tx = async_xor(dest, blocks, 0, count, STRIPE_SIZE,844844+ &submit);845845+846846+ count = set_syndrome_sources(blocks, sh);847847+ init_async_submit(&submit, ASYNC_TX_FENCE, tx,848848+ ops_complete_compute, sh,849849+ to_addr_conv(sh, percpu));850850+ return async_gen_syndrome(blocks, 0, count+2,851851+ STRIPE_SIZE, &submit);852852+ }853853+ } else {854854+ init_async_submit(&submit, ASYNC_TX_FENCE, NULL,855855+ ops_complete_compute, sh,856856+ to_addr_conv(sh, percpu));857857+ if (failb == syndrome_disks) {858858+ /* We're missing D+P. */859859+ return async_raid6_datap_recov(syndrome_disks+2,860860+ STRIPE_SIZE, faila,861861+ blocks, &submit);862862+ } else {863863+ /* We're missing D+D. */864864+ return async_raid6_2data_recov(syndrome_disks+2,865865+ STRIPE_SIZE, faila, failb,866866+ blocks, &submit);867867+ }868868+ }869869+}870870+702871703872static void ops_complete_prexor(void *stripe_head_ref)704873{···907680}908681909682static struct dma_async_tx_descriptor *910910-ops_run_prexor(struct stripe_head *sh, struct dma_async_tx_descriptor *tx)683683+ops_run_prexor(struct stripe_head *sh, struct raid5_percpu *percpu,684684+ struct dma_async_tx_descriptor *tx)911685{912912- /* kernel stack size limits the total number of disks */913686 int disks = sh->disks;914914- struct page *xor_srcs[disks];687687+ struct page **xor_srcs = percpu->scribble;915688 int count = 0, pd_idx = sh->pd_idx, i;689689+ struct async_submit_ctl submit;916690917691 /* existing parity data subtracted */918692 struct page *xor_dest = xor_srcs[count++] = sh->dev[pd_idx].page;···928700 xor_srcs[count++] = dev->page;929701 }930702931931- tx = async_xor(xor_dest, xor_srcs, 0, count, STRIPE_SIZE,932932- ASYNC_TX_DEP_ACK | ASYNC_TX_XOR_DROP_DST, tx,933933- ops_complete_prexor, sh);703703+ init_async_submit(&submit, ASYNC_TX_FENCE|ASYNC_TX_XOR_DROP_DST, tx,704704+ ops_complete_prexor, sh, to_addr_conv(sh, percpu));705705+ tx = async_xor(xor_dest, xor_srcs, 0, count, STRIPE_SIZE, &submit);934706935707 return tx;936708}···970742 return tx;971743}972744973973-static void ops_complete_postxor(void *stripe_head_ref)745745+static void ops_complete_reconstruct(void *stripe_head_ref)974746{975747 struct stripe_head *sh = stripe_head_ref;976976- int disks = sh->disks, i, pd_idx = sh->pd_idx;748748+ int disks = sh->disks;749749+ int pd_idx = sh->pd_idx;750750+ int qd_idx = sh->qd_idx;751751+ int i;977752978753 pr_debug("%s: stripe %llu\n", __func__,979754 (unsigned long long)sh->sector);980755981756 for (i = disks; i--; ) {982757 struct r5dev *dev = &sh->dev[i];983983- if (dev->written || i == pd_idx)758758+759759+ if (dev->written || i == pd_idx || i == qd_idx)984760 set_bit(R5_UPTODATE, &dev->flags);985761 }986762···1002770}10037711004772static void10051005-ops_run_postxor(struct stripe_head *sh, struct dma_async_tx_descriptor *tx)773773+ops_run_reconstruct5(struct stripe_head *sh, struct raid5_percpu *percpu,774774+ struct dma_async_tx_descriptor *tx)1006775{10071007- /* kernel stack size limits the total number of disks */1008776 int disks = sh->disks;10091009- struct page *xor_srcs[disks];10101010-777777+ struct page **xor_srcs = percpu->scribble;778778+ struct async_submit_ctl submit;1011779 int count = 0, pd_idx = sh->pd_idx, i;1012780 struct page *xor_dest;1013781 int prexor = 0;···1041809 * set ASYNC_TX_XOR_DROP_DST and ASYNC_TX_XOR_ZERO_DST1042810 * for the synchronous xor case1043811 */10441044- flags = ASYNC_TX_DEP_ACK | ASYNC_TX_ACK |812812+ flags = ASYNC_TX_ACK |1045813 (prexor ? ASYNC_TX_XOR_DROP_DST : ASYNC_TX_XOR_ZERO_DST);10468141047815 atomic_inc(&sh->count);104881610491049- if (unlikely(count == 1)) {10501050- flags &= ~(ASYNC_TX_XOR_DROP_DST | ASYNC_TX_XOR_ZERO_DST);10511051- tx = async_memcpy(xor_dest, xor_srcs[0], 0, 0, STRIPE_SIZE,10521052- flags, tx, ops_complete_postxor, sh);10531053- } else10541054- tx = async_xor(xor_dest, xor_srcs, 0, count, STRIPE_SIZE,10551055- flags, tx, ops_complete_postxor, sh);817817+ init_async_submit(&submit, flags, tx, ops_complete_reconstruct, sh,818818+ to_addr_conv(sh, percpu));819819+ if (unlikely(count == 1))820820+ tx = async_memcpy(xor_dest, xor_srcs[0], 0, 0, STRIPE_SIZE, &submit);821821+ else822822+ tx = async_xor(xor_dest, xor_srcs, 0, count, STRIPE_SIZE, &submit);823823+}824824+825825+static void826826+ops_run_reconstruct6(struct stripe_head *sh, struct raid5_percpu *percpu,827827+ struct dma_async_tx_descriptor *tx)828828+{829829+ struct async_submit_ctl submit;830830+ struct page **blocks = percpu->scribble;831831+ int count;832832+833833+ pr_debug("%s: stripe %llu\n", __func__, (unsigned long long)sh->sector);834834+835835+ count = set_syndrome_sources(blocks, sh);836836+837837+ atomic_inc(&sh->count);838838+839839+ init_async_submit(&submit, ASYNC_TX_ACK, tx, ops_complete_reconstruct,840840+ sh, to_addr_conv(sh, percpu));841841+ async_gen_syndrome(blocks, 0, count+2, STRIPE_SIZE, &submit);1056842}10578431058844static void ops_complete_check(void *stripe_head_ref)···1085835 release_stripe(sh);1086836}108783710881088-static void ops_run_check(struct stripe_head *sh)838838+static void ops_run_check_p(struct stripe_head *sh, struct raid5_percpu *percpu)1089839{10901090- /* kernel stack size limits the total number of disks */1091840 int disks = sh->disks;10921092- struct page *xor_srcs[disks];841841+ int pd_idx = sh->pd_idx;842842+ int qd_idx = sh->qd_idx;843843+ struct page *xor_dest;844844+ struct page **xor_srcs = percpu->scribble;1093845 struct dma_async_tx_descriptor *tx;10941094-10951095- int count = 0, pd_idx = sh->pd_idx, i;10961096- struct page *xor_dest = xor_srcs[count++] = sh->dev[pd_idx].page;846846+ struct async_submit_ctl submit;847847+ int count;848848+ int i;10978491098850 pr_debug("%s: stripe %llu\n", __func__,1099851 (unsigned long long)sh->sector);1100852853853+ count = 0;854854+ xor_dest = sh->dev[pd_idx].page;855855+ xor_srcs[count++] = xor_dest;1101856 for (i = disks; i--; ) {11021102- struct r5dev *dev = &sh->dev[i];11031103- if (i != pd_idx)11041104- xor_srcs[count++] = dev->page;857857+ if (i == pd_idx || i == qd_idx)858858+ continue;859859+ xor_srcs[count++] = sh->dev[i].page;1105860 }110686111071107- tx = async_xor_zero_sum(xor_dest, xor_srcs, 0, count, STRIPE_SIZE,11081108- &sh->ops.zero_sum_result, 0, NULL, NULL, NULL);862862+ init_async_submit(&submit, 0, NULL, NULL, NULL,863863+ to_addr_conv(sh, percpu));864864+ tx = async_xor_val(xor_dest, xor_srcs, 0, count, STRIPE_SIZE,865865+ &sh->ops.zero_sum_result, &submit);11098661110867 atomic_inc(&sh->count);11111111- tx = async_trigger_callback(ASYNC_TX_DEP_ACK | ASYNC_TX_ACK, tx,11121112- ops_complete_check, sh);868868+ init_async_submit(&submit, ASYNC_TX_ACK, tx, ops_complete_check, sh, NULL);869869+ tx = async_trigger_callback(&submit);1113870}111487111151115-static void raid5_run_ops(struct stripe_head *sh, unsigned long ops_request)872872+static void ops_run_check_pq(struct stripe_head *sh, struct raid5_percpu *percpu, int checkp)873873+{874874+ struct page **srcs = percpu->scribble;875875+ struct async_submit_ctl submit;876876+ int count;877877+878878+ pr_debug("%s: stripe %llu checkp: %d\n", __func__,879879+ (unsigned long long)sh->sector, checkp);880880+881881+ count = set_syndrome_sources(srcs, sh);882882+ if (!checkp)883883+ srcs[count] = NULL;884884+885885+ atomic_inc(&sh->count);886886+ init_async_submit(&submit, ASYNC_TX_ACK, NULL, ops_complete_check,887887+ sh, to_addr_conv(sh, percpu));888888+ async_syndrome_val(srcs, 0, count+2, STRIPE_SIZE,889889+ &sh->ops.zero_sum_result, percpu->spare_page, &submit);890890+}891891+892892+static void raid_run_ops(struct stripe_head *sh, unsigned long ops_request)1116893{1117894 int overlap_clear = 0, i, disks = sh->disks;1118895 struct dma_async_tx_descriptor *tx = NULL;896896+ raid5_conf_t *conf = sh->raid_conf;897897+ int level = conf->level;898898+ struct raid5_percpu *percpu;899899+ unsigned long cpu;1119900901901+ cpu = get_cpu();902902+ percpu = per_cpu_ptr(conf->percpu, cpu);1120903 if (test_bit(STRIPE_OP_BIOFILL, &ops_request)) {1121904 ops_run_biofill(sh);1122905 overlap_clear++;1123906 }11249071125908 if (test_bit(STRIPE_OP_COMPUTE_BLK, &ops_request)) {11261126- tx = ops_run_compute5(sh);11271127- /* terminate the chain if postxor is not set to be run */11281128- if (tx && !test_bit(STRIPE_OP_POSTXOR, &ops_request))909909+ if (level < 6)910910+ tx = ops_run_compute5(sh, percpu);911911+ else {912912+ if (sh->ops.target2 < 0 || sh->ops.target < 0)913913+ tx = ops_run_compute6_1(sh, percpu);914914+ else915915+ tx = ops_run_compute6_2(sh, percpu);916916+ }917917+ /* terminate the chain if reconstruct is not set to be run */918918+ if (tx && !test_bit(STRIPE_OP_RECONSTRUCT, &ops_request))1129919 async_tx_ack(tx);1130920 }11319211132922 if (test_bit(STRIPE_OP_PREXOR, &ops_request))11331133- tx = ops_run_prexor(sh, tx);923923+ tx = ops_run_prexor(sh, percpu, tx);11349241135925 if (test_bit(STRIPE_OP_BIODRAIN, &ops_request)) {1136926 tx = ops_run_biodrain(sh, tx);1137927 overlap_clear++;1138928 }113992911401140- if (test_bit(STRIPE_OP_POSTXOR, &ops_request))11411141- ops_run_postxor(sh, tx);930930+ if (test_bit(STRIPE_OP_RECONSTRUCT, &ops_request)) {931931+ if (level < 6)932932+ ops_run_reconstruct5(sh, percpu, tx);933933+ else934934+ ops_run_reconstruct6(sh, percpu, tx);935935+ }114293611431143- if (test_bit(STRIPE_OP_CHECK, &ops_request))11441144- ops_run_check(sh);937937+ if (test_bit(STRIPE_OP_CHECK, &ops_request)) {938938+ if (sh->check_state == check_state_run)939939+ ops_run_check_p(sh, percpu);940940+ else if (sh->check_state == check_state_run_q)941941+ ops_run_check_pq(sh, percpu, 0);942942+ else if (sh->check_state == check_state_run_pq)943943+ ops_run_check_pq(sh, percpu, 1);944944+ else945945+ BUG();946946+ }11459471146948 if (overlap_clear)1147949 for (i = disks; i--; ) {···1201899 if (test_and_clear_bit(R5_Overlap, &dev->flags))1202900 wake_up(&sh->raid_conf->wait_for_overlap);1203901 }902902+ put_cpu();1204903}12059041206905static int grow_one_stripe(raid5_conf_t *conf)···1251948 return 0;1252949}1253950951951+/**952952+ * scribble_len - return the required size of the scribble region953953+ * @num - total number of disks in the array954954+ *955955+ * The size must be enough to contain:956956+ * 1/ a struct page pointer for each device in the array +2957957+ * 2/ room to convert each entry in (1) to its corresponding dma958958+ * (dma_map_page()) or page (page_address()) address.959959+ *960960+ * Note: the +2 is for the destination buffers of the ddf/raid6 case where we961961+ * calculate over all devices (not just the data blocks), using zeros in place962962+ * of the P and Q blocks.963963+ */964964+static size_t scribble_len(int num)965965+{966966+ size_t len;967967+968968+ len = sizeof(struct page *) * (num+2) + sizeof(addr_conv_t) * (num+2);969969+970970+ return len;971971+}972972+1254973static int resize_stripes(raid5_conf_t *conf, int newsize)1255974{1256975 /* Make all the stripes able to hold 'newsize' devices.···1301976 struct stripe_head *osh, *nsh;1302977 LIST_HEAD(newstripes);1303978 struct disk_info *ndisks;979979+ unsigned long cpu;1304980 int err;1305981 struct kmem_cache *sc;1306982 int i;···13671041 /* Step 3.13681042 * At this point, we are holding all the stripes so the array13691043 * is completely stalled, so now is a good time to resize13701370- * conf->disks.10441044+ * conf->disks and the scribble region13711045 */13721046 ndisks = kzalloc(newsize * sizeof(struct disk_info), GFP_NOIO);13731047 if (ndisks) {···13781052 } else13791053 err = -ENOMEM;1380105410551055+ get_online_cpus();10561056+ conf->scribble_len = scribble_len(newsize);10571057+ for_each_present_cpu(cpu) {10581058+ struct raid5_percpu *percpu;10591059+ void *scribble;10601060+10611061+ percpu = per_cpu_ptr(conf->percpu, cpu);10621062+ scribble = kmalloc(conf->scribble_len, GFP_NOIO);10631063+10641064+ if (scribble) {10651065+ kfree(percpu->scribble);10661066+ percpu->scribble = scribble;10671067+ } else {10681068+ err = -ENOMEM;10691069+ break;10701070+ }10711071+ }10721072+ put_online_cpus();10731073+13811074 /* Step 4, return new stripes to service */13821075 while(!list_empty(&newstripes)) {13831076 nsh = list_entry(newstripes.next, struct stripe_head, lru);13841077 list_del_init(&nsh->lru);10781078+13851079 for (i=conf->raid_disks; i < newsize; i++)13861080 if (nsh->dev[i].page == NULL) {13871081 struct page *p = alloc_page(GFP_NOIO);···19401594}194115951942159619431943-19441944-/*19451945- * Copy data between a page in the stripe cache, and one or more bion19461946- * The page could align with the middle of the bio, or there could be19471947- * several bion, each with several bio_vecs, which cover part of the page19481948- * Multiple bion are linked together on bi_next. There may be extras19491949- * at the end of this list. We ignore them.19501950- */19511951-static void copy_data(int frombio, struct bio *bio,19521952- struct page *page,19531953- sector_t sector)19541954-{19551955- char *pa = page_address(page);19561956- struct bio_vec *bvl;19571957- int i;19581958- int page_offset;19591959-19601960- if (bio->bi_sector >= sector)19611961- page_offset = (signed)(bio->bi_sector - sector) * 512;19621962- else19631963- page_offset = (signed)(sector - bio->bi_sector) * -512;19641964- bio_for_each_segment(bvl, bio, i) {19651965- int len = bio_iovec_idx(bio,i)->bv_len;19661966- int clen;19671967- int b_offset = 0;19681968-19691969- if (page_offset < 0) {19701970- b_offset = -page_offset;19711971- page_offset += b_offset;19721972- len -= b_offset;19731973- }19741974-19751975- if (len > 0 && page_offset + len > STRIPE_SIZE)19761976- clen = STRIPE_SIZE - page_offset;19771977- else clen = len;19781978-19791979- if (clen > 0) {19801980- char *ba = __bio_kmap_atomic(bio, i, KM_USER0);19811981- if (frombio)19821982- memcpy(pa+page_offset, ba+b_offset, clen);19831983- else19841984- memcpy(ba+b_offset, pa+page_offset, clen);19851985- __bio_kunmap_atomic(ba, KM_USER0);19861986- }19871987- if (clen < len) /* hit end of page */19881988- break;19891989- page_offset += len;19901990- }19911991-}19921992-19931993-#define check_xor() do { \19941994- if (count == MAX_XOR_BLOCKS) { \19951995- xor_blocks(count, STRIPE_SIZE, dest, ptr);\19961996- count = 0; \19971997- } \19981998- } while(0)19991999-20002000-static void compute_parity6(struct stripe_head *sh, int method)20012001-{20022002- raid5_conf_t *conf = sh->raid_conf;20032003- int i, pd_idx, qd_idx, d0_idx, disks = sh->disks, count;20042004- int syndrome_disks = sh->ddf_layout ? disks : (disks - 2);20052005- struct bio *chosen;20062006- /**** FIX THIS: This could be very bad if disks is close to 256 ****/20072007- void *ptrs[syndrome_disks+2];20082008-20092009- pd_idx = sh->pd_idx;20102010- qd_idx = sh->qd_idx;20112011- d0_idx = raid6_d0(sh);20122012-20132013- pr_debug("compute_parity, stripe %llu, method %d\n",20142014- (unsigned long long)sh->sector, method);20152015-20162016- switch(method) {20172017- case READ_MODIFY_WRITE:20182018- BUG(); /* READ_MODIFY_WRITE N/A for RAID-6 */20192019- case RECONSTRUCT_WRITE:20202020- for (i= disks; i-- ;)20212021- if ( i != pd_idx && i != qd_idx && sh->dev[i].towrite ) {20222022- chosen = sh->dev[i].towrite;20232023- sh->dev[i].towrite = NULL;20242024-20252025- if (test_and_clear_bit(R5_Overlap, &sh->dev[i].flags))20262026- wake_up(&conf->wait_for_overlap);20272027-20282028- BUG_ON(sh->dev[i].written);20292029- sh->dev[i].written = chosen;20302030- }20312031- break;20322032- case CHECK_PARITY:20332033- BUG(); /* Not implemented yet */20342034- }20352035-20362036- for (i = disks; i--;)20372037- if (sh->dev[i].written) {20382038- sector_t sector = sh->dev[i].sector;20392039- struct bio *wbi = sh->dev[i].written;20402040- while (wbi && wbi->bi_sector < sector + STRIPE_SECTORS) {20412041- copy_data(1, wbi, sh->dev[i].page, sector);20422042- wbi = r5_next_bio(wbi, sector);20432043- }20442044-20452045- set_bit(R5_LOCKED, &sh->dev[i].flags);20462046- set_bit(R5_UPTODATE, &sh->dev[i].flags);20472047- }20482048-20492049- /* Note that unlike RAID-5, the ordering of the disks matters greatly.*/20502050-20512051- for (i = 0; i < disks; i++)20522052- ptrs[i] = (void *)raid6_empty_zero_page;20532053-20542054- count = 0;20552055- i = d0_idx;20562056- do {20572057- int slot = raid6_idx_to_slot(i, sh, &count, syndrome_disks);20582058-20592059- ptrs[slot] = page_address(sh->dev[i].page);20602060- if (slot < syndrome_disks &&20612061- !test_bit(R5_UPTODATE, &sh->dev[i].flags)) {20622062- printk(KERN_ERR "block %d/%d not uptodate "20632063- "on parity calc\n", i, count);20642064- BUG();20652065- }20662066-20672067- i = raid6_next_disk(i, disks);20682068- } while (i != d0_idx);20692069- BUG_ON(count != syndrome_disks);20702070-20712071- raid6_call.gen_syndrome(syndrome_disks+2, STRIPE_SIZE, ptrs);20722072-20732073- switch(method) {20742074- case RECONSTRUCT_WRITE:20752075- set_bit(R5_UPTODATE, &sh->dev[pd_idx].flags);20762076- set_bit(R5_UPTODATE, &sh->dev[qd_idx].flags);20772077- set_bit(R5_LOCKED, &sh->dev[pd_idx].flags);20782078- set_bit(R5_LOCKED, &sh->dev[qd_idx].flags);20792079- break;20802080- case UPDATE_PARITY:20812081- set_bit(R5_UPTODATE, &sh->dev[pd_idx].flags);20822082- set_bit(R5_UPTODATE, &sh->dev[qd_idx].flags);20832083- break;20842084- }20852085-}20862086-20872087-20882088-/* Compute one missing block */20892089-static void compute_block_1(struct stripe_head *sh, int dd_idx, int nozero)20902090-{20912091- int i, count, disks = sh->disks;20922092- void *ptr[MAX_XOR_BLOCKS], *dest, *p;20932093- int qd_idx = sh->qd_idx;20942094-20952095- pr_debug("compute_block_1, stripe %llu, idx %d\n",20962096- (unsigned long long)sh->sector, dd_idx);20972097-20982098- if ( dd_idx == qd_idx ) {20992099- /* We're actually computing the Q drive */21002100- compute_parity6(sh, UPDATE_PARITY);21012101- } else {21022102- dest = page_address(sh->dev[dd_idx].page);21032103- if (!nozero) memset(dest, 0, STRIPE_SIZE);21042104- count = 0;21052105- for (i = disks ; i--; ) {21062106- if (i == dd_idx || i == qd_idx)21072107- continue;21082108- p = page_address(sh->dev[i].page);21092109- if (test_bit(R5_UPTODATE, &sh->dev[i].flags))21102110- ptr[count++] = p;21112111- else21122112- printk("compute_block() %d, stripe %llu, %d"21132113- " not present\n", dd_idx,21142114- (unsigned long long)sh->sector, i);21152115-21162116- check_xor();21172117- }21182118- if (count)21192119- xor_blocks(count, STRIPE_SIZE, dest, ptr);21202120- if (!nozero) set_bit(R5_UPTODATE, &sh->dev[dd_idx].flags);21212121- else clear_bit(R5_UPTODATE, &sh->dev[dd_idx].flags);21222122- }21232123-}21242124-21252125-/* Compute two missing blocks */21262126-static void compute_block_2(struct stripe_head *sh, int dd_idx1, int dd_idx2)21272127-{21282128- int i, count, disks = sh->disks;21292129- int syndrome_disks = sh->ddf_layout ? disks : disks-2;21302130- int d0_idx = raid6_d0(sh);21312131- int faila = -1, failb = -1;21322132- /**** FIX THIS: This could be very bad if disks is close to 256 ****/21332133- void *ptrs[syndrome_disks+2];21342134-21352135- for (i = 0; i < disks ; i++)21362136- ptrs[i] = (void *)raid6_empty_zero_page;21372137- count = 0;21382138- i = d0_idx;21392139- do {21402140- int slot = raid6_idx_to_slot(i, sh, &count, syndrome_disks);21412141-21422142- ptrs[slot] = page_address(sh->dev[i].page);21432143-21442144- if (i == dd_idx1)21452145- faila = slot;21462146- if (i == dd_idx2)21472147- failb = slot;21482148- i = raid6_next_disk(i, disks);21492149- } while (i != d0_idx);21502150- BUG_ON(count != syndrome_disks);21512151-21522152- BUG_ON(faila == failb);21532153- if ( failb < faila ) { int tmp = faila; faila = failb; failb = tmp; }21542154-21552155- pr_debug("compute_block_2, stripe %llu, idx %d,%d (%d,%d)\n",21562156- (unsigned long long)sh->sector, dd_idx1, dd_idx2,21572157- faila, failb);21582158-21592159- if (failb == syndrome_disks+1) {21602160- /* Q disk is one of the missing disks */21612161- if (faila == syndrome_disks) {21622162- /* Missing P+Q, just recompute */21632163- compute_parity6(sh, UPDATE_PARITY);21642164- return;21652165- } else {21662166- /* We're missing D+Q; recompute D from P */21672167- compute_block_1(sh, ((dd_idx1 == sh->qd_idx) ?21682168- dd_idx2 : dd_idx1),21692169- 0);21702170- compute_parity6(sh, UPDATE_PARITY); /* Is this necessary? */21712171- return;21722172- }21732173- }21742174-21752175- /* We're missing D+P or D+D; */21762176- if (failb == syndrome_disks) {21772177- /* We're missing D+P. */21782178- raid6_datap_recov(syndrome_disks+2, STRIPE_SIZE, faila, ptrs);21792179- } else {21802180- /* We're missing D+D. */21812181- raid6_2data_recov(syndrome_disks+2, STRIPE_SIZE, faila, failb,21822182- ptrs);21832183- }21842184-21852185- /* Both the above update both missing blocks */21862186- set_bit(R5_UPTODATE, &sh->dev[dd_idx1].flags);21872187- set_bit(R5_UPTODATE, &sh->dev[dd_idx2].flags);21882188-}21892189-21901597static void21912191-schedule_reconstruction5(struct stripe_head *sh, struct stripe_head_state *s,15981598+schedule_reconstruction(struct stripe_head *sh, struct stripe_head_state *s,21921599 int rcw, int expand)21931600{21941601 int i, pd_idx = sh->pd_idx, disks = sh->disks;16021602+ raid5_conf_t *conf = sh->raid_conf;16031603+ int level = conf->level;2195160421961605 if (rcw) {21971606 /* if we are not expanding this is a proper write request, and···19591858 } else19601859 sh->reconstruct_state = reconstruct_state_run;1961186019621962- set_bit(STRIPE_OP_POSTXOR, &s->ops_request);18611861+ set_bit(STRIPE_OP_RECONSTRUCT, &s->ops_request);1963186219641863 for (i = disks; i--; ) {19651864 struct r5dev *dev = &sh->dev[i];···19721871 s->locked++;19731872 }19741873 }19751975- if (s->locked + 1 == disks)18741874+ if (s->locked + conf->max_degraded == disks)19761875 if (!test_and_set_bit(STRIPE_FULL_WRITE, &sh->state))19771977- atomic_inc(&sh->raid_conf->pending_full_writes);18761876+ atomic_inc(&conf->pending_full_writes);19781877 } else {18781878+ BUG_ON(level == 6);19791879 BUG_ON(!(test_bit(R5_UPTODATE, &sh->dev[pd_idx].flags) ||19801880 test_bit(R5_Wantcompute, &sh->dev[pd_idx].flags)));1981188119821882 sh->reconstruct_state = reconstruct_state_prexor_drain_run;19831883 set_bit(STRIPE_OP_PREXOR, &s->ops_request);19841884 set_bit(STRIPE_OP_BIODRAIN, &s->ops_request);19851985- set_bit(STRIPE_OP_POSTXOR, &s->ops_request);18851885+ set_bit(STRIPE_OP_RECONSTRUCT, &s->ops_request);1986188619871887 for (i = disks; i--; ) {19881888 struct r5dev *dev = &sh->dev[i];···20011899 }20021900 }2003190120042004- /* keep the parity disk locked while asynchronous operations19021902+ /* keep the parity disk(s) locked while asynchronous operations20051903 * are in flight20061904 */20071905 set_bit(R5_LOCKED, &sh->dev[pd_idx].flags);20081906 clear_bit(R5_UPTODATE, &sh->dev[pd_idx].flags);20091907 s->locked++;19081908+19091909+ if (level == 6) {19101910+ int qd_idx = sh->qd_idx;19111911+ struct r5dev *dev = &sh->dev[qd_idx];19121912+19131913+ set_bit(R5_LOCKED, &dev->flags);19141914+ clear_bit(R5_UPTODATE, &dev->flags);19151915+ s->locked++;19161916+ }2010191720111918 pr_debug("%s: stripe %llu locked: %d ops_request: %lx\n",20121919 __func__, (unsigned long long)sh->sector,···20961985}2097198620981987static void end_reshape(raid5_conf_t *conf);20992099-21002100-static int page_is_zero(struct page *p)21012101-{21022102- char *a = page_address(p);21032103- return ((*(u32*)a) == 0 &&21042104- memcmp(a, a+4, STRIPE_SIZE-4)==0);21052105-}2106198821071989static void stripe_set_idx(sector_t stripe, raid5_conf_t *conf, int previous,21081990 struct stripe_head *sh)···22362132 set_bit(STRIPE_OP_COMPUTE_BLK, &s->ops_request);22372133 set_bit(R5_Wantcompute, &dev->flags);22382134 sh->ops.target = disk_idx;21352135+ sh->ops.target2 = -1;22392136 s->req_compute = 1;22402137 /* Careful: from this point on 'uptodate' is in the eye22412241- * of raid5_run_ops which services 'compute' operations21382138+ * of raid_run_ops which services 'compute' operations22422139 * before writes. R5_Wantcompute flags a block that will22432140 * be R5_UPTODATE by the time it is needed for a22442141 * subsequent operation.···22782173 set_bit(STRIPE_HANDLE, &sh->state);22792174}2280217521762176+/* fetch_block6 - checks the given member device to see if its data needs21772177+ * to be read or computed to satisfy a request.21782178+ *21792179+ * Returns 1 when no more member devices need to be checked, otherwise returns21802180+ * 0 to tell the loop in handle_stripe_fill6 to continue21812181+ */21822182+static int fetch_block6(struct stripe_head *sh, struct stripe_head_state *s,21832183+ struct r6_state *r6s, int disk_idx, int disks)21842184+{21852185+ struct r5dev *dev = &sh->dev[disk_idx];21862186+ struct r5dev *fdev[2] = { &sh->dev[r6s->failed_num[0]],21872187+ &sh->dev[r6s->failed_num[1]] };21882188+21892189+ if (!test_bit(R5_LOCKED, &dev->flags) &&21902190+ !test_bit(R5_UPTODATE, &dev->flags) &&21912191+ (dev->toread ||21922192+ (dev->towrite && !test_bit(R5_OVERWRITE, &dev->flags)) ||21932193+ s->syncing || s->expanding ||21942194+ (s->failed >= 1 &&21952195+ (fdev[0]->toread || s->to_write)) ||21962196+ (s->failed >= 2 &&21972197+ (fdev[1]->toread || s->to_write)))) {21982198+ /* we would like to get this block, possibly by computing it,21992199+ * otherwise read it if the backing disk is insync22002200+ */22012201+ BUG_ON(test_bit(R5_Wantcompute, &dev->flags));22022202+ BUG_ON(test_bit(R5_Wantread, &dev->flags));22032203+ if ((s->uptodate == disks - 1) &&22042204+ (s->failed && (disk_idx == r6s->failed_num[0] ||22052205+ disk_idx == r6s->failed_num[1]))) {22062206+ /* have disk failed, and we're requested to fetch it;22072207+ * do compute it22082208+ */22092209+ pr_debug("Computing stripe %llu block %d\n",22102210+ (unsigned long long)sh->sector, disk_idx);22112211+ set_bit(STRIPE_COMPUTE_RUN, &sh->state);22122212+ set_bit(STRIPE_OP_COMPUTE_BLK, &s->ops_request);22132213+ set_bit(R5_Wantcompute, &dev->flags);22142214+ sh->ops.target = disk_idx;22152215+ sh->ops.target2 = -1; /* no 2nd target */22162216+ s->req_compute = 1;22172217+ s->uptodate++;22182218+ return 1;22192219+ } else if (s->uptodate == disks-2 && s->failed >= 2) {22202220+ /* Computing 2-failure is *very* expensive; only22212221+ * do it if failed >= 222222222+ */22232223+ int other;22242224+ for (other = disks; other--; ) {22252225+ if (other == disk_idx)22262226+ continue;22272227+ if (!test_bit(R5_UPTODATE,22282228+ &sh->dev[other].flags))22292229+ break;22302230+ }22312231+ BUG_ON(other < 0);22322232+ pr_debug("Computing stripe %llu blocks %d,%d\n",22332233+ (unsigned long long)sh->sector,22342234+ disk_idx, other);22352235+ set_bit(STRIPE_COMPUTE_RUN, &sh->state);22362236+ set_bit(STRIPE_OP_COMPUTE_BLK, &s->ops_request);22372237+ set_bit(R5_Wantcompute, &sh->dev[disk_idx].flags);22382238+ set_bit(R5_Wantcompute, &sh->dev[other].flags);22392239+ sh->ops.target = disk_idx;22402240+ sh->ops.target2 = other;22412241+ s->uptodate += 2;22422242+ s->req_compute = 1;22432243+ return 1;22442244+ } else if (test_bit(R5_Insync, &dev->flags)) {22452245+ set_bit(R5_LOCKED, &dev->flags);22462246+ set_bit(R5_Wantread, &dev->flags);22472247+ s->locked++;22482248+ pr_debug("Reading block %d (sync=%d)\n",22492249+ disk_idx, s->syncing);22502250+ }22512251+ }22522252+22532253+ return 0;22542254+}22552255+22562256+/**22572257+ * handle_stripe_fill6 - read or compute data to satisfy pending requests.22582258+ */22812259static void handle_stripe_fill6(struct stripe_head *sh,22822260 struct stripe_head_state *s, struct r6_state *r6s,22832261 int disks)22842262{22852263 int i;22862286- for (i = disks; i--; ) {22872287- struct r5dev *dev = &sh->dev[i];22882288- if (!test_bit(R5_LOCKED, &dev->flags) &&22892289- !test_bit(R5_UPTODATE, &dev->flags) &&22902290- (dev->toread || (dev->towrite &&22912291- !test_bit(R5_OVERWRITE, &dev->flags)) ||22922292- s->syncing || s->expanding ||22932293- (s->failed >= 1 &&22942294- (sh->dev[r6s->failed_num[0]].toread ||22952295- s->to_write)) ||22962296- (s->failed >= 2 &&22972297- (sh->dev[r6s->failed_num[1]].toread ||22982298- s->to_write)))) {22992299- /* we would like to get this block, possibly23002300- * by computing it, but we might not be able to23012301- */23022302- if ((s->uptodate == disks - 1) &&23032303- (s->failed && (i == r6s->failed_num[0] ||23042304- i == r6s->failed_num[1]))) {23052305- pr_debug("Computing stripe %llu block %d\n",23062306- (unsigned long long)sh->sector, i);23072307- compute_block_1(sh, i, 0);23082308- s->uptodate++;23092309- } else if ( s->uptodate == disks-2 && s->failed >= 2 ) {23102310- /* Computing 2-failure is *very* expensive; only23112311- * do it if failed >= 223122312- */23132313- int other;23142314- for (other = disks; other--; ) {23152315- if (other == i)23162316- continue;23172317- if (!test_bit(R5_UPTODATE,23182318- &sh->dev[other].flags))23192319- break;23202320- }23212321- BUG_ON(other < 0);23222322- pr_debug("Computing stripe %llu blocks %d,%d\n",23232323- (unsigned long long)sh->sector,23242324- i, other);23252325- compute_block_2(sh, i, other);23262326- s->uptodate += 2;23272327- } else if (test_bit(R5_Insync, &dev->flags)) {23282328- set_bit(R5_LOCKED, &dev->flags);23292329- set_bit(R5_Wantread, &dev->flags);23302330- s->locked++;23312331- pr_debug("Reading block %d (sync=%d)\n",23322332- i, s->syncing);23332333- }23342334- }23352335- }22642264+22652265+ /* look for blocks to read/compute, skip this if a compute22662266+ * is already in flight, or if the stripe contents are in the22672267+ * midst of changing due to a write22682268+ */22692269+ if (!test_bit(STRIPE_COMPUTE_RUN, &sh->state) && !sh->check_state &&22702270+ !sh->reconstruct_state)22712271+ for (i = disks; i--; )22722272+ if (fetch_block6(sh, s, r6s, i, disks))22732273+ break;23362274 set_bit(STRIPE_HANDLE, &sh->state);23372275}23382276···25092361 */25102362 /* since handle_stripe can be called at any time we need to handle the25112363 * case where a compute block operation has been submitted and then a25122512- * subsequent call wants to start a write request. raid5_run_ops only25132513- * handles the case where compute block and postxor are requested23642364+ * subsequent call wants to start a write request. raid_run_ops only23652365+ * handles the case where compute block and reconstruct are requested25142366 * simultaneously. If this is not the case then new writes need to be25152367 * held off until the compute completes.25162368 */25172369 if ((s->req_compute || !test_bit(STRIPE_COMPUTE_RUN, &sh->state)) &&25182370 (s->locked == 0 && (rcw == 0 || rmw == 0) &&25192371 !test_bit(STRIPE_BIT_DELAY, &sh->state)))25202520- schedule_reconstruction5(sh, s, rcw == 0, 0);23722372+ schedule_reconstruction(sh, s, rcw == 0, 0);25212373}2522237425232375static void handle_stripe_dirtying6(raid5_conf_t *conf,25242376 struct stripe_head *sh, struct stripe_head_state *s,25252377 struct r6_state *r6s, int disks)25262378{25272527- int rcw = 0, must_compute = 0, pd_idx = sh->pd_idx, i;23792379+ int rcw = 0, pd_idx = sh->pd_idx, i;25282380 int qd_idx = sh->qd_idx;23812381+23822382+ set_bit(STRIPE_HANDLE, &sh->state);25292383 for (i = disks; i--; ) {25302384 struct r5dev *dev = &sh->dev[i];25312531- /* Would I have to read this buffer for reconstruct_write */25322532- if (!test_bit(R5_OVERWRITE, &dev->flags)25332533- && i != pd_idx && i != qd_idx25342534- && (!test_bit(R5_LOCKED, &dev->flags)25352535- ) &&25362536- !test_bit(R5_UPTODATE, &dev->flags)) {25372537- if (test_bit(R5_Insync, &dev->flags)) rcw++;25382538- else {25392539- pr_debug("raid6: must_compute: "25402540- "disk %d flags=%#lx\n", i, dev->flags);25412541- must_compute++;23852385+ /* check if we haven't enough data */23862386+ if (!test_bit(R5_OVERWRITE, &dev->flags) &&23872387+ i != pd_idx && i != qd_idx &&23882388+ !test_bit(R5_LOCKED, &dev->flags) &&23892389+ !(test_bit(R5_UPTODATE, &dev->flags) ||23902390+ test_bit(R5_Wantcompute, &dev->flags))) {23912391+ rcw++;23922392+ if (!test_bit(R5_Insync, &dev->flags))23932393+ continue; /* it's a failed drive */23942394+23952395+ if (23962396+ test_bit(STRIPE_PREREAD_ACTIVE, &sh->state)) {23972397+ pr_debug("Read_old stripe %llu "23982398+ "block %d for Reconstruct\n",23992399+ (unsigned long long)sh->sector, i);24002400+ set_bit(R5_LOCKED, &dev->flags);24012401+ set_bit(R5_Wantread, &dev->flags);24022402+ s->locked++;24032403+ } else {24042404+ pr_debug("Request delayed stripe %llu "24052405+ "block %d for Reconstruct\n",24062406+ (unsigned long long)sh->sector, i);24072407+ set_bit(STRIPE_DELAYED, &sh->state);24082408+ set_bit(STRIPE_HANDLE, &sh->state);25422409 }25432410 }25442411 }25452545- pr_debug("for sector %llu, rcw=%d, must_compute=%d\n",25462546- (unsigned long long)sh->sector, rcw, must_compute);25472547- set_bit(STRIPE_HANDLE, &sh->state);25482548-25492549- if (rcw > 0)25502550- /* want reconstruct write, but need to get some data */25512551- for (i = disks; i--; ) {25522552- struct r5dev *dev = &sh->dev[i];25532553- if (!test_bit(R5_OVERWRITE, &dev->flags)25542554- && !(s->failed == 0 && (i == pd_idx || i == qd_idx))25552555- && !test_bit(R5_LOCKED, &dev->flags) &&25562556- !test_bit(R5_UPTODATE, &dev->flags) &&25572557- test_bit(R5_Insync, &dev->flags)) {25582558- if (25592559- test_bit(STRIPE_PREREAD_ACTIVE, &sh->state)) {25602560- pr_debug("Read_old stripe %llu "25612561- "block %d for Reconstruct\n",25622562- (unsigned long long)sh->sector, i);25632563- set_bit(R5_LOCKED, &dev->flags);25642564- set_bit(R5_Wantread, &dev->flags);25652565- s->locked++;25662566- } else {25672567- pr_debug("Request delayed stripe %llu "25682568- "block %d for Reconstruct\n",25692569- (unsigned long long)sh->sector, i);25702570- set_bit(STRIPE_DELAYED, &sh->state);25712571- set_bit(STRIPE_HANDLE, &sh->state);25722572- }25732573- }25742574- }25752412 /* now if nothing is locked, and if we have enough data, we can start a25762413 * write request25772414 */25782578- if (s->locked == 0 && rcw == 0 &&24152415+ if ((s->req_compute || !test_bit(STRIPE_COMPUTE_RUN, &sh->state)) &&24162416+ s->locked == 0 && rcw == 0 &&25792417 !test_bit(STRIPE_BIT_DELAY, &sh->state)) {25802580- if (must_compute > 0) {25812581- /* We have failed blocks and need to compute them */25822582- switch (s->failed) {25832583- case 0:25842584- BUG();25852585- case 1:25862586- compute_block_1(sh, r6s->failed_num[0], 0);25872587- break;25882588- case 2:25892589- compute_block_2(sh, r6s->failed_num[0],25902590- r6s->failed_num[1]);25912591- break;25922592- default: /* This request should have been failed? */25932593- BUG();25942594- }25952595- }25962596-25972597- pr_debug("Computing parity for stripe %llu\n",25982598- (unsigned long long)sh->sector);25992599- compute_parity6(sh, RECONSTRUCT_WRITE);26002600- /* now every locked buffer is ready to be written */26012601- for (i = disks; i--; )26022602- if (test_bit(R5_LOCKED, &sh->dev[i].flags)) {26032603- pr_debug("Writing stripe %llu block %d\n",26042604- (unsigned long long)sh->sector, i);26052605- s->locked++;26062606- set_bit(R5_Wantwrite, &sh->dev[i].flags);26072607- }26082608- if (s->locked == disks)26092609- if (!test_and_set_bit(STRIPE_FULL_WRITE, &sh->state))26102610- atomic_inc(&conf->pending_full_writes);26112611- /* after a RECONSTRUCT_WRITE, the stripe MUST be in-sync */26122612- set_bit(STRIPE_INSYNC, &sh->state);26132613-26142614- if (test_and_clear_bit(STRIPE_PREREAD_ACTIVE, &sh->state)) {26152615- atomic_dec(&conf->preread_active_stripes);26162616- if (atomic_read(&conf->preread_active_stripes) <26172617- IO_THRESHOLD)26182618- md_wakeup_thread(conf->mddev->thread);26192619- }24182418+ schedule_reconstruction(sh, s, 1, 0);26202419 }26212420}26222421···26222527 * we are done. Otherwise update the mismatch count and repair26232528 * parity if !MD_RECOVERY_CHECK26242529 */26252625- if (sh->ops.zero_sum_result == 0)25302530+ if ((sh->ops.zero_sum_result & SUM_CHECK_P_RESULT) == 0)26262531 /* parity is correct (on disc,26272532 * not in buffer any more)26282533 */···26392544 set_bit(R5_Wantcompute,26402545 &sh->dev[sh->pd_idx].flags);26412546 sh->ops.target = sh->pd_idx;25472547+ sh->ops.target2 = -1;26422548 s->uptodate++;26432549 }26442550 }···265625602657256126582562static void handle_parity_checks6(raid5_conf_t *conf, struct stripe_head *sh,26592659- struct stripe_head_state *s,26602660- struct r6_state *r6s, struct page *tmp_page,26612661- int disks)25632563+ struct stripe_head_state *s,25642564+ struct r6_state *r6s, int disks)26622565{26632663- int update_p = 0, update_q = 0;26642664- struct r5dev *dev;26652566 int pd_idx = sh->pd_idx;26662567 int qd_idx = sh->qd_idx;25682568+ struct r5dev *dev;2667256926682570 set_bit(STRIPE_HANDLE, &sh->state);2669257126702572 BUG_ON(s->failed > 2);26712671- BUG_ON(s->uptodate < disks);25732573+26722574 /* Want to check and possibly repair P and Q.26732575 * However there could be one 'failed' device, in which26742576 * case we can only check one of them, possibly using the26752577 * other to generate missing data26762578 */2677257926782678- /* If !tmp_page, we cannot do the calculations,26792679- * but as we have set STRIPE_HANDLE, we will soon be called26802680- * by stripe_handle with a tmp_page - just wait until then.26812681- */26822682- if (tmp_page) {25802580+ switch (sh->check_state) {25812581+ case check_state_idle:25822582+ /* start a new check operation if there are < 2 failures */26832583 if (s->failed == r6s->q_failed) {26842684- /* The only possible failed device holds 'Q', so it25842584+ /* The only possible failed device holds Q, so it26852585 * makes sense to check P (If anything else were failed,26862586 * we would have used P to recreate it).26872587 */26882688- compute_block_1(sh, pd_idx, 1);26892689- if (!page_is_zero(sh->dev[pd_idx].page)) {26902690- compute_block_1(sh, pd_idx, 0);26912691- update_p = 1;26922692- }25882588+ sh->check_state = check_state_run;26932589 }26942590 if (!r6s->q_failed && s->failed < 2) {26952695- /* q is not failed, and we didn't use it to generate25912591+ /* Q is not failed, and we didn't use it to generate26962592 * anything, so it makes sense to check it26972593 */26982698- memcpy(page_address(tmp_page),26992699- page_address(sh->dev[qd_idx].page),27002700- STRIPE_SIZE);27012701- compute_parity6(sh, UPDATE_PARITY);27022702- if (memcmp(page_address(tmp_page),27032703- page_address(sh->dev[qd_idx].page),27042704- STRIPE_SIZE) != 0) {27052705- clear_bit(STRIPE_INSYNC, &sh->state);27062706- update_q = 1;27072707- }25942594+ if (sh->check_state == check_state_run)25952595+ sh->check_state = check_state_run_pq;25962596+ else25972597+ sh->check_state = check_state_run_q;27082598 }27092709- if (update_p || update_q) {27102710- conf->mddev->resync_mismatches += STRIPE_SECTORS;27112711- if (test_bit(MD_RECOVERY_CHECK, &conf->mddev->recovery))27122712- /* don't try to repair!! */27132713- update_p = update_q = 0;25992599+26002600+ /* discard potentially stale zero_sum_result */26012601+ sh->ops.zero_sum_result = 0;26022602+26032603+ if (sh->check_state == check_state_run) {26042604+ /* async_xor_zero_sum destroys the contents of P */26052605+ clear_bit(R5_UPTODATE, &sh->dev[pd_idx].flags);26062606+ s->uptodate--;27142607 }26082608+ if (sh->check_state >= check_state_run &&26092609+ sh->check_state <= check_state_run_pq) {26102610+ /* async_syndrome_zero_sum preserves P and Q, so26112611+ * no need to mark them !uptodate here26122612+ */26132613+ set_bit(STRIPE_OP_CHECK, &s->ops_request);26142614+ break;26152615+ }26162616+26172617+ /* we have 2-disk failure */26182618+ BUG_ON(s->failed != 2);26192619+ /* fall through */26202620+ case check_state_compute_result:26212621+ sh->check_state = check_state_idle;26222622+26232623+ /* check that a write has not made the stripe insync */26242624+ if (test_bit(STRIPE_INSYNC, &sh->state))26252625+ break;2715262627162627 /* now write out any block on a failed drive,27172717- * or P or Q if they need it26282628+ * or P or Q if they were recomputed27182629 */27192719-26302630+ BUG_ON(s->uptodate < disks - 1); /* We don't need Q to recover */27202631 if (s->failed == 2) {27212632 dev = &sh->dev[r6s->failed_num[1]];27222633 s->locked++;···27362633 set_bit(R5_LOCKED, &dev->flags);27372634 set_bit(R5_Wantwrite, &dev->flags);27382635 }27392739-27402740- if (update_p) {26362636+ if (sh->ops.zero_sum_result & SUM_CHECK_P_RESULT) {27412637 dev = &sh->dev[pd_idx];27422638 s->locked++;27432639 set_bit(R5_LOCKED, &dev->flags);27442640 set_bit(R5_Wantwrite, &dev->flags);27452641 }27462746- if (update_q) {26422642+ if (sh->ops.zero_sum_result & SUM_CHECK_Q_RESULT) {27472643 dev = &sh->dev[qd_idx];27482644 s->locked++;27492645 set_bit(R5_LOCKED, &dev->flags);···27512649 clear_bit(STRIPE_DEGRADED, &sh->state);2752265027532651 set_bit(STRIPE_INSYNC, &sh->state);26522652+ break;26532653+ case check_state_run:26542654+ case check_state_run_q:26552655+ case check_state_run_pq:26562656+ break; /* we will be called again upon completion */26572657+ case check_state_check_result:26582658+ sh->check_state = check_state_idle;26592659+26602660+ /* handle a successful check operation, if parity is correct26612661+ * we are done. Otherwise update the mismatch count and repair26622662+ * parity if !MD_RECOVERY_CHECK26632663+ */26642664+ if (sh->ops.zero_sum_result == 0) {26652665+ /* both parities are correct */26662666+ if (!s->failed)26672667+ set_bit(STRIPE_INSYNC, &sh->state);26682668+ else {26692669+ /* in contrast to the raid5 case we can validate26702670+ * parity, but still have a failure to write26712671+ * back26722672+ */26732673+ sh->check_state = check_state_compute_result;26742674+ /* Returning at this point means that we may go26752675+ * off and bring p and/or q uptodate again so26762676+ * we make sure to check zero_sum_result again26772677+ * to verify if p or q need writeback26782678+ */26792679+ }26802680+ } else {26812681+ conf->mddev->resync_mismatches += STRIPE_SECTORS;26822682+ if (test_bit(MD_RECOVERY_CHECK, &conf->mddev->recovery))26832683+ /* don't try to repair!! */26842684+ set_bit(STRIPE_INSYNC, &sh->state);26852685+ else {26862686+ int *target = &sh->ops.target;26872687+26882688+ sh->ops.target = -1;26892689+ sh->ops.target2 = -1;26902690+ sh->check_state = check_state_compute_run;26912691+ set_bit(STRIPE_COMPUTE_RUN, &sh->state);26922692+ set_bit(STRIPE_OP_COMPUTE_BLK, &s->ops_request);26932693+ if (sh->ops.zero_sum_result & SUM_CHECK_P_RESULT) {26942694+ set_bit(R5_Wantcompute,26952695+ &sh->dev[pd_idx].flags);26962696+ *target = pd_idx;26972697+ target = &sh->ops.target2;26982698+ s->uptodate++;26992699+ }27002700+ if (sh->ops.zero_sum_result & SUM_CHECK_Q_RESULT) {27012701+ set_bit(R5_Wantcompute,27022702+ &sh->dev[qd_idx].flags);27032703+ *target = qd_idx;27042704+ s->uptodate++;27052705+ }27062706+ }27072707+ }27082708+ break;27092709+ case check_state_compute_run:27102710+ break;27112711+ default:27122712+ printk(KERN_ERR "%s: unknown check_state: %d sector: %llu\n",27132713+ __func__, sh->check_state,27142714+ (unsigned long long) sh->sector);27152715+ BUG();27542716 }27552717}27562718···28322666 if (i != sh->pd_idx && i != sh->qd_idx) {28332667 int dd_idx, j;28342668 struct stripe_head *sh2;26692669+ struct async_submit_ctl submit;2835267028362671 sector_t bn = compute_blocknr(sh, i, 1);28372672 sector_t s = raid5_compute_sector(conf, bn, 0,···28522685 }2853268628542687 /* place all the copies on one channel */26882688+ init_async_submit(&submit, 0, tx, NULL, NULL, NULL);28552689 tx = async_memcpy(sh2->dev[dd_idx].page,28562856- sh->dev[i].page, 0, 0, STRIPE_SIZE,28572857- ASYNC_TX_DEP_ACK, tx, NULL, NULL);26902690+ sh->dev[i].page, 0, 0, STRIPE_SIZE,26912691+ &submit);2858269228592693 set_bit(R5_Expanded, &sh2->dev[dd_idx].flags);28602694 set_bit(R5_UPTODATE, &sh2->dev[dd_idx].flags);···31422974 /* Need to write out all blocks after computing parity */31432975 sh->disks = conf->raid_disks;31442976 stripe_set_idx(sh->sector, conf, 0, sh);31453145- schedule_reconstruction5(sh, &s, 1, 1);29772977+ schedule_reconstruction(sh, &s, 1, 1);31462978 } else if (s.expanded && !sh->reconstruct_state && s.locked == 0) {31472979 clear_bit(STRIPE_EXPAND_READY, &sh->state);31482980 atomic_dec(&conf->reshape_stripes);···31622994 md_wait_for_blocked_rdev(blocked_rdev, conf->mddev);3163299531642996 if (s.ops_request)31653165- raid5_run_ops(sh, s.ops_request);29972997+ raid_run_ops(sh, s.ops_request);3166299831672999 ops_run_io(sh, &s);31683000···31713003 return blocked_rdev == NULL;31723004}3173300531743174-static bool handle_stripe6(struct stripe_head *sh, struct page *tmp_page)30063006+static bool handle_stripe6(struct stripe_head *sh)31753007{31763008 raid5_conf_t *conf = sh->raid_conf;31773009 int disks = sh->disks;···31833015 mdk_rdev_t *blocked_rdev = NULL;3184301631853017 pr_debug("handling stripe %llu, state=%#lx cnt=%d, "31863186- "pd_idx=%d, qd_idx=%d\n",30183018+ "pd_idx=%d, qd_idx=%d\n, check:%d, reconstruct:%d\n",31873019 (unsigned long long)sh->sector, sh->state,31883188- atomic_read(&sh->count), pd_idx, qd_idx);30203020+ atomic_read(&sh->count), pd_idx, qd_idx,30213021+ sh->check_state, sh->reconstruct_state);31893022 memset(&s, 0, sizeof(s));3190302331913024 spin_lock(&sh->lock);···3206303732073038 pr_debug("check %d: state 0x%lx read %p write %p written %p\n",32083039 i, dev->flags, dev->toread, dev->towrite, dev->written);32093209- /* maybe we can reply to a read */32103210- if (test_bit(R5_UPTODATE, &dev->flags) && dev->toread) {32113211- struct bio *rbi, *rbi2;32123212- pr_debug("Return read for disc %d\n", i);32133213- spin_lock_irq(&conf->device_lock);32143214- rbi = dev->toread;32153215- dev->toread = NULL;32163216- if (test_and_clear_bit(R5_Overlap, &dev->flags))32173217- wake_up(&conf->wait_for_overlap);32183218- spin_unlock_irq(&conf->device_lock);32193219- while (rbi && rbi->bi_sector < dev->sector + STRIPE_SECTORS) {32203220- copy_data(0, rbi, dev->page, dev->sector);32213221- rbi2 = r5_next_bio(rbi, dev->sector);32223222- spin_lock_irq(&conf->device_lock);32233223- if (!raid5_dec_bi_phys_segments(rbi)) {32243224- rbi->bi_next = return_bi;32253225- return_bi = rbi;32263226- }32273227- spin_unlock_irq(&conf->device_lock);32283228- rbi = rbi2;32293229- }32303230- }30403040+ /* maybe we can reply to a read30413041+ *30423042+ * new wantfill requests are only permitted while30433043+ * ops_complete_biofill is guaranteed to be inactive30443044+ */30453045+ if (test_bit(R5_UPTODATE, &dev->flags) && dev->toread &&30463046+ !test_bit(STRIPE_BIOFILL_RUN, &sh->state))30473047+ set_bit(R5_Wantfill, &dev->flags);3231304832323049 /* now count some things */32333050 if (test_bit(R5_LOCKED, &dev->flags)) s.locked++;32343051 if (test_bit(R5_UPTODATE, &dev->flags)) s.uptodate++;30523052+ if (test_bit(R5_Wantcompute, &dev->flags)) {30533053+ s.compute++;30543054+ BUG_ON(s.compute > 2);30553055+ }3235305632363236-32373237- if (dev->toread)30573057+ if (test_bit(R5_Wantfill, &dev->flags)) {30583058+ s.to_fill++;30593059+ } else if (dev->toread)32383060 s.to_read++;32393061 if (dev->towrite) {32403062 s.to_write++;···32643104 /* There is nothing for the blocked_rdev to block */32653105 rdev_dec_pending(blocked_rdev, conf->mddev);32663106 blocked_rdev = NULL;31073107+ }31083108+31093109+ if (s.to_fill && !test_bit(STRIPE_BIOFILL_RUN, &sh->state)) {31103110+ set_bit(STRIPE_OP_BIOFILL, &s.ops_request);31113111+ set_bit(STRIPE_BIOFILL_RUN, &sh->state);32673112 }3268311332693114 pr_debug("locked=%d uptodate=%d to_read=%d"···33113146 * or to load a block that is being partially written.33123147 */33133148 if (s.to_read || s.non_overwrite || (s.to_write && s.failed) ||33143314- (s.syncing && (s.uptodate < disks)) || s.expanding)31493149+ (s.syncing && (s.uptodate + s.compute < disks)) || s.expanding)33153150 handle_stripe_fill6(sh, &s, &r6s, disks);3316315133173317- /* now to consider writing and what else, if anything should be read */33183318- if (s.to_write)31523152+ /* Now we check to see if any write operations have recently31533153+ * completed31543154+ */31553155+ if (sh->reconstruct_state == reconstruct_state_drain_result) {31563156+ int qd_idx = sh->qd_idx;31573157+31583158+ sh->reconstruct_state = reconstruct_state_idle;31593159+ /* All the 'written' buffers and the parity blocks are ready to31603160+ * be written back to disk31613161+ */31623162+ BUG_ON(!test_bit(R5_UPTODATE, &sh->dev[sh->pd_idx].flags));31633163+ BUG_ON(!test_bit(R5_UPTODATE, &sh->dev[qd_idx].flags));31643164+ for (i = disks; i--; ) {31653165+ dev = &sh->dev[i];31663166+ if (test_bit(R5_LOCKED, &dev->flags) &&31673167+ (i == sh->pd_idx || i == qd_idx ||31683168+ dev->written)) {31693169+ pr_debug("Writing block %d\n", i);31703170+ BUG_ON(!test_bit(R5_UPTODATE, &dev->flags));31713171+ set_bit(R5_Wantwrite, &dev->flags);31723172+ if (!test_bit(R5_Insync, &dev->flags) ||31733173+ ((i == sh->pd_idx || i == qd_idx) &&31743174+ s.failed == 0))31753175+ set_bit(STRIPE_INSYNC, &sh->state);31763176+ }31773177+ }31783178+ if (test_and_clear_bit(STRIPE_PREREAD_ACTIVE, &sh->state)) {31793179+ atomic_dec(&conf->preread_active_stripes);31803180+ if (atomic_read(&conf->preread_active_stripes) <31813181+ IO_THRESHOLD)31823182+ md_wakeup_thread(conf->mddev->thread);31833183+ }31843184+ }31853185+31863186+ /* Now to consider new write requests and what else, if anything31873187+ * should be read. We do not handle new writes when:31883188+ * 1/ A 'write' operation (copy+gen_syndrome) is already in flight.31893189+ * 2/ A 'check' operation is in flight, as it may clobber the parity31903190+ * block.31913191+ */31923192+ if (s.to_write && !sh->reconstruct_state && !sh->check_state)33193193 handle_stripe_dirtying6(conf, sh, &s, &r6s, disks);3320319433213195 /* maybe we need to check and possibly fix the parity for this stripe33223196 * Any reads will already have been scheduled, so we just see if enough33233323- * data is available31973197+ * data is available. The parity check is held off while parity31983198+ * dependent operations are in flight.33243199 */33253325- if (s.syncing && s.locked == 0 && !test_bit(STRIPE_INSYNC, &sh->state))33263326- handle_parity_checks6(conf, sh, &s, &r6s, tmp_page, disks);32003200+ if (sh->check_state ||32013201+ (s.syncing && s.locked == 0 &&32023202+ !test_bit(STRIPE_COMPUTE_RUN, &sh->state) &&32033203+ !test_bit(STRIPE_INSYNC, &sh->state)))32043204+ handle_parity_checks6(conf, sh, &s, &r6s, disks);3327320533283206 if (s.syncing && s.locked == 0 && test_bit(STRIPE_INSYNC, &sh->state)) {33293207 md_done_sync(conf->mddev, STRIPE_SECTORS,1);···33873179 set_bit(R5_Wantwrite, &dev->flags);33883180 set_bit(R5_ReWrite, &dev->flags);33893181 set_bit(R5_LOCKED, &dev->flags);31823182+ s.locked++;33903183 } else {33913184 /* let's read it back */33923185 set_bit(R5_Wantread, &dev->flags);33933186 set_bit(R5_LOCKED, &dev->flags);31873187+ s.locked++;33943188 }33953189 }33963190 }3397319133983398- if (s.expanded && test_bit(STRIPE_EXPANDING, &sh->state)) {31923192+ /* Finish reconstruct operations initiated by the expansion process */31933193+ if (sh->reconstruct_state == reconstruct_state_result) {31943194+ sh->reconstruct_state = reconstruct_state_idle;31953195+ clear_bit(STRIPE_EXPANDING, &sh->state);31963196+ for (i = conf->raid_disks; i--; ) {31973197+ set_bit(R5_Wantwrite, &sh->dev[i].flags);31983198+ set_bit(R5_LOCKED, &sh->dev[i].flags);31993199+ s.locked++;32003200+ }32013201+ }32023202+32033203+ if (s.expanded && test_bit(STRIPE_EXPANDING, &sh->state) &&32043204+ !sh->reconstruct_state) {33993205 struct stripe_head *sh234003206 = get_active_stripe(conf, sh->sector, 1, 1, 1);34013207 if (sh2 && test_bit(STRIPE_EXPAND_SOURCE, &sh2->state)) {···34303208 /* Need to write out all blocks after computing P&Q */34313209 sh->disks = conf->raid_disks;34323210 stripe_set_idx(sh->sector, conf, 0, sh);34333433- compute_parity6(sh, RECONSTRUCT_WRITE);34343434- for (i = conf->raid_disks ; i-- ; ) {34353435- set_bit(R5_LOCKED, &sh->dev[i].flags);34363436- s.locked++;34373437- set_bit(R5_Wantwrite, &sh->dev[i].flags);34383438- }34393439- clear_bit(STRIPE_EXPANDING, &sh->state);34403440- } else if (s.expanded) {32113211+ schedule_reconstruction(sh, &s, 1, 1);32123212+ } else if (s.expanded && !sh->reconstruct_state && s.locked == 0) {34413213 clear_bit(STRIPE_EXPAND_READY, &sh->state);34423214 atomic_dec(&conf->reshape_stripes);34433215 wake_up(&conf->wait_for_overlap);···34493233 if (unlikely(blocked_rdev))34503234 md_wait_for_blocked_rdev(blocked_rdev, conf->mddev);3451323532363236+ if (s.ops_request)32373237+ raid_run_ops(sh, s.ops_request);32383238+34523239 ops_run_io(sh, &s);3453324034543241 return_io(return_bi);···34603241}3461324234623243/* returns true if the stripe was handled */34633463-static bool handle_stripe(struct stripe_head *sh, struct page *tmp_page)32443244+static bool handle_stripe(struct stripe_head *sh)34643245{34653246 if (sh->raid_conf->level == 6)34663466- return handle_stripe6(sh, tmp_page);32473247+ return handle_stripe6(sh);34673248 else34683249 return handle_stripe5(sh);34693250}34703470-34713471-3472325134733252static void raid5_activate_delayed(raid5_conf_t *conf)34743253{···42784061 spin_unlock(&sh->lock);4279406242804063 /* wait for any blocked device to be handled */42814281- while(unlikely(!handle_stripe(sh, NULL)))40644064+ while (unlikely(!handle_stripe(sh)))42824065 ;42834066 release_stripe(sh);42844067···43354118 return handled;43364119 }4337412043384338- handle_stripe(sh, NULL);41214121+ handle_stripe(sh);43394122 release_stripe(sh);43404123 handled++;43414124 }···43494132 return handled;43504133}4351413441354135+#ifdef CONFIG_MULTICORE_RAID45641364136+static void __process_stripe(void *param, async_cookie_t cookie)41374137+{41384138+ struct stripe_head *sh = param;41394139+41404140+ handle_stripe(sh);41414141+ release_stripe(sh);41424142+}41434143+41444144+static void process_stripe(struct stripe_head *sh, struct list_head *domain)41454145+{41464146+ async_schedule_domain(__process_stripe, sh, domain);41474147+}41484148+41494149+static void synchronize_stripe_processing(struct list_head *domain)41504150+{41514151+ async_synchronize_full_domain(domain);41524152+}41534153+#else41544154+static void process_stripe(struct stripe_head *sh, struct list_head *domain)41554155+{41564156+ handle_stripe(sh);41574157+ release_stripe(sh);41584158+ cond_resched();41594159+}41604160+41614161+static void synchronize_stripe_processing(struct list_head *domain)41624162+{41634163+}41644164+#endif435241654353416643544167/*···43934146 struct stripe_head *sh;43944147 raid5_conf_t *conf = mddev->private;43954148 int handled;41494149+ LIST_HEAD(raid_domain);4396415043974151 pr_debug("+++ raid5d active\n");43984152···44304182 spin_unlock_irq(&conf->device_lock);4431418344324184 handled++;44334433- handle_stripe(sh, conf->spare_page);44344434- release_stripe(sh);41854185+ process_stripe(sh, &raid_domain);4435418644364187 spin_lock_irq(&conf->device_lock);44374188 }···4438419144394192 spin_unlock_irq(&conf->device_lock);4440419341944194+ synchronize_stripe_processing(&raid_domain);44414195 async_tx_issue_pending_all();44424196 unplug_slaves(mddev);44434197···45714323 return sectors * (raid_disks - conf->max_degraded);45724324}4573432543264326+static void raid5_free_percpu(raid5_conf_t *conf)43274327+{43284328+ struct raid5_percpu *percpu;43294329+ unsigned long cpu;43304330+43314331+ if (!conf->percpu)43324332+ return;43334333+43344334+ get_online_cpus();43354335+ for_each_possible_cpu(cpu) {43364336+ percpu = per_cpu_ptr(conf->percpu, cpu);43374337+ safe_put_page(percpu->spare_page);43384338+ kfree(percpu->scribble);43394339+ }43404340+#ifdef CONFIG_HOTPLUG_CPU43414341+ unregister_cpu_notifier(&conf->cpu_notify);43424342+#endif43434343+ put_online_cpus();43444344+43454345+ free_percpu(conf->percpu);43464346+}43474347+45744348static void free_conf(raid5_conf_t *conf)45754349{45764350 shrink_stripes(conf);45774577- safe_put_page(conf->spare_page);43514351+ raid5_free_percpu(conf);45784352 kfree(conf->disks);45794353 kfree(conf->stripe_hashtbl);45804354 kfree(conf);43554355+}43564356+43574357+#ifdef CONFIG_HOTPLUG_CPU43584358+static int raid456_cpu_notify(struct notifier_block *nfb, unsigned long action,43594359+ void *hcpu)43604360+{43614361+ raid5_conf_t *conf = container_of(nfb, raid5_conf_t, cpu_notify);43624362+ long cpu = (long)hcpu;43634363+ struct raid5_percpu *percpu = per_cpu_ptr(conf->percpu, cpu);43644364+43654365+ switch (action) {43664366+ case CPU_UP_PREPARE:43674367+ case CPU_UP_PREPARE_FROZEN:43684368+ if (conf->level == 6 && !percpu->spare_page)43694369+ percpu->spare_page = alloc_page(GFP_KERNEL);43704370+ if (!percpu->scribble)43714371+ percpu->scribble = kmalloc(conf->scribble_len, GFP_KERNEL);43724372+43734373+ if (!percpu->scribble ||43744374+ (conf->level == 6 && !percpu->spare_page)) {43754375+ safe_put_page(percpu->spare_page);43764376+ kfree(percpu->scribble);43774377+ pr_err("%s: failed memory allocation for cpu%ld\n",43784378+ __func__, cpu);43794379+ return NOTIFY_BAD;43804380+ }43814381+ break;43824382+ case CPU_DEAD:43834383+ case CPU_DEAD_FROZEN:43844384+ safe_put_page(percpu->spare_page);43854385+ kfree(percpu->scribble);43864386+ percpu->spare_page = NULL;43874387+ percpu->scribble = NULL;43884388+ break;43894389+ default:43904390+ break;43914391+ }43924392+ return NOTIFY_OK;43934393+}43944394+#endif43954395+43964396+static int raid5_alloc_percpu(raid5_conf_t *conf)43974397+{43984398+ unsigned long cpu;43994399+ struct page *spare_page;44004400+ struct raid5_percpu *allcpus;44014401+ void *scribble;44024402+ int err;44034403+44044404+ allcpus = alloc_percpu(struct raid5_percpu);44054405+ if (!allcpus)44064406+ return -ENOMEM;44074407+ conf->percpu = allcpus;44084408+44094409+ get_online_cpus();44104410+ err = 0;44114411+ for_each_present_cpu(cpu) {44124412+ if (conf->level == 6) {44134413+ spare_page = alloc_page(GFP_KERNEL);44144414+ if (!spare_page) {44154415+ err = -ENOMEM;44164416+ break;44174417+ }44184418+ per_cpu_ptr(conf->percpu, cpu)->spare_page = spare_page;44194419+ }44204420+ scribble = kmalloc(scribble_len(conf->raid_disks), GFP_KERNEL);44214421+ if (!scribble) {44224422+ err = -ENOMEM;44234423+ break;44244424+ }44254425+ per_cpu_ptr(conf->percpu, cpu)->scribble = scribble;44264426+ }44274427+#ifdef CONFIG_HOTPLUG_CPU44284428+ conf->cpu_notify.notifier_call = raid456_cpu_notify;44294429+ conf->cpu_notify.priority = 0;44304430+ if (err == 0)44314431+ err = register_cpu_notifier(&conf->cpu_notify);44324432+#endif44334433+ put_online_cpus();44344434+44354435+ return err;45814436}4582443745834438static raid5_conf_t *setup_conf(mddev_t *mddev)···47244373 goto abort;4725437447264375 conf->raid_disks = mddev->raid_disks;43764376+ conf->scribble_len = scribble_len(conf->raid_disks);47274377 if (mddev->reshape_position == MaxSector)47284378 conf->previous_raid_disks = mddev->raid_disks;47294379 else···47404388 if ((conf->stripe_hashtbl = kzalloc(PAGE_SIZE, GFP_KERNEL)) == NULL)47414389 goto abort;4742439047434743- if (mddev->new_level == 6) {47444744- conf->spare_page = alloc_page(GFP_KERNEL);47454745- if (!conf->spare_page)47464746- goto abort;47474747- }43914391+ conf->level = mddev->new_level;43924392+ if (raid5_alloc_percpu(conf) != 0)43934393+ goto abort;43944394+47484395 spin_lock_init(&conf->device_lock);47494396 init_waitqueue_head(&conf->wait_for_stripe);47504397 init_waitqueue_head(&conf->wait_for_overlap);
+22-6
drivers/md/raid5.h
···22#define _RAID5_H3344#include <linux/raid/xor.h>55+#include <linux/dmaengine.h>5667/*78 *···176175 */177176enum check_states {178177 check_state_idle = 0,179179- check_state_run, /* parity check */178178+ check_state_run, /* xor parity check */179179+ check_state_run_q, /* q-parity check */180180+ check_state_run_pq, /* pq dual parity check */180181 check_state_check_result,181182 check_state_compute_run, /* parity repair */182183 check_state_compute_result,···218215 * @target - STRIPE_OP_COMPUTE_BLK target219216 */220217 struct stripe_operations {221221- int target;222222- u32 zero_sum_result;218218+ int target, target2;219219+ enum sum_check_flags zero_sum_result;223220 } ops;224221 struct r5dev {225222 struct bio req;···301298#define STRIPE_OP_COMPUTE_BLK 1302299#define STRIPE_OP_PREXOR 2303300#define STRIPE_OP_BIODRAIN 3304304-#define STRIPE_OP_POSTXOR 4301301+#define STRIPE_OP_RECONSTRUCT 4305302#define STRIPE_OP_CHECK 5306303307304/*···388385 * (fresh device added).389386 * Cleared when a sync completes.390387 */391391-392392- struct page *spare_page; /* Used when checking P/Q in raid6 */388388+ /* per cpu variables */389389+ struct raid5_percpu {390390+ struct page *spare_page; /* Used when checking P/Q in raid6 */391391+ void *scribble; /* space for constructing buffer392392+ * lists and performing address393393+ * conversions394394+ */395395+ } *percpu;396396+ size_t scribble_len; /* size of scribble region must be397397+ * associated with conf to handle398398+ * cpu hotplug while reshaping399399+ */400400+#ifdef CONFIG_HOTPLUG_CPU401401+ struct notifier_block cpu_notify;402402+#endif393403394404 /*395405 * Free stripes pool
+8-1
drivers/mmc/host/atmel-mci.c
···576576 struct scatterlist *sg;577577 unsigned int i;578578 enum dma_data_direction direction;579579+ unsigned int sglen;579580580581 /*581582 * We don't do DMA on "complex" transfers, i.e. with···606605 else607606 direction = DMA_TO_DEVICE;608607608608+ sglen = dma_map_sg(&host->pdev->dev, data->sg, data->sg_len, direction);609609+ if (sglen != data->sg_len)610610+ goto unmap_exit;609611 desc = chan->device->device_prep_slave_sg(chan,610612 data->sg, data->sg_len, direction,611613 DMA_PREP_INTERRUPT | DMA_CTRL_ACK);612614 if (!desc)613613- return -ENOMEM;615615+ goto unmap_exit;614616615617 host->dma.data_desc = desc;616618 desc->callback = atmci_dma_complete;···624620 chan->device->device_issue_pending(chan);625621626622 return 0;623623+unmap_exit:624624+ dma_unmap_sg(&host->pdev->dev, data->sg, sglen, direction);625625+ return -ENOMEM;627626}628627629628#else /* CONFIG_MMC_ATMELMCI_DMA */
+97-32
include/linux/async_tx.h
···5858 * array.5959 * @ASYNC_TX_ACK: immediately ack the descriptor, precludes setting up a6060 * dependency chain6161- * @ASYNC_TX_DEP_ACK: ack the dependency descriptor. Useful for chaining.6161+ * @ASYNC_TX_FENCE: specify that the next operation in the dependency6262+ * chain uses this operation's result as an input6263 */6364enum async_tx_flags {6465 ASYNC_TX_XOR_ZERO_DST = (1 << 0),6566 ASYNC_TX_XOR_DROP_DST = (1 << 1),6666- ASYNC_TX_ACK = (1 << 3),6767- ASYNC_TX_DEP_ACK = (1 << 4),6767+ ASYNC_TX_ACK = (1 << 2),6868+ ASYNC_TX_FENCE = (1 << 3),6969+};7070+7171+/**7272+ * struct async_submit_ctl - async_tx submission/completion modifiers7373+ * @flags: submission modifiers7474+ * @depend_tx: parent dependency of the current operation being submitted7575+ * @cb_fn: callback routine to run at operation completion7676+ * @cb_param: parameter for the callback routine7777+ * @scribble: caller provided space for dma/page address conversions7878+ */7979+struct async_submit_ctl {8080+ enum async_tx_flags flags;8181+ struct dma_async_tx_descriptor *depend_tx;8282+ dma_async_tx_callback cb_fn;8383+ void *cb_param;8484+ void *scribble;6885};69867087#ifdef CONFIG_DMA_ENGINE7188#define async_tx_issue_pending_all dma_issue_pending_all8989+9090+/**9191+ * async_tx_issue_pending - send pending descriptor to the hardware channel9292+ * @tx: descriptor handle to retrieve hardware context9393+ *9494+ * Note: any dependent operations will have already been issued by9595+ * async_tx_channel_switch, or (in the case of no channel switch) will9696+ * be already pending on this channel.9797+ */9898+static inline void async_tx_issue_pending(struct dma_async_tx_descriptor *tx)9999+{100100+ if (likely(tx)) {101101+ struct dma_chan *chan = tx->chan;102102+ struct dma_device *dma = chan->device;103103+104104+ dma->device_issue_pending(chan);105105+ }106106+}72107#ifdef CONFIG_ARCH_HAS_ASYNC_TX_FIND_CHANNEL73108#include <asm/async_tx.h>74109#else75110#define async_tx_find_channel(dep, type, dst, dst_count, src, src_count, len) \76111 __async_tx_find_channel(dep, type)77112struct dma_chan *7878-__async_tx_find_channel(struct dma_async_tx_descriptor *depend_tx,7979- enum dma_transaction_type tx_type);113113+__async_tx_find_channel(struct async_submit_ctl *submit,114114+ enum dma_transaction_type tx_type);80115#endif /* CONFIG_ARCH_HAS_ASYNC_TX_FIND_CHANNEL */81116#else82117static inline void async_tx_issue_pending_all(void)···11984 do { } while (0);12085}121868787+static inline void async_tx_issue_pending(struct dma_async_tx_descriptor *tx)8888+{8989+ do { } while (0);9090+}9191+12292static inline struct dma_chan *123123-async_tx_find_channel(struct dma_async_tx_descriptor *depend_tx,124124- enum dma_transaction_type tx_type, struct page **dst, int dst_count,125125- struct page **src, int src_count, size_t len)9393+async_tx_find_channel(struct async_submit_ctl *submit,9494+ enum dma_transaction_type tx_type, struct page **dst,9595+ int dst_count, struct page **src, int src_count,9696+ size_t len)12697{12798 return NULL;12899}···14099 * @cb_fn_param: parameter to pass to the callback routine141100 */142101static inline void143143-async_tx_sync_epilog(dma_async_tx_callback cb_fn, void *cb_fn_param)102102+async_tx_sync_epilog(struct async_submit_ctl *submit)144103{145145- if (cb_fn)146146- cb_fn(cb_fn_param);104104+ if (submit->cb_fn)105105+ submit->cb_fn(submit->cb_param);147106}148107149149-void150150-async_tx_submit(struct dma_chan *chan, struct dma_async_tx_descriptor *tx,151151- enum async_tx_flags flags, struct dma_async_tx_descriptor *depend_tx,152152- dma_async_tx_callback cb_fn, void *cb_fn_param);108108+typedef union {109109+ unsigned long addr;110110+ struct page *page;111111+ dma_addr_t dma;112112+} addr_conv_t;113113+114114+static inline void115115+init_async_submit(struct async_submit_ctl *args, enum async_tx_flags flags,116116+ struct dma_async_tx_descriptor *tx,117117+ dma_async_tx_callback cb_fn, void *cb_param,118118+ addr_conv_t *scribble)119119+{120120+ args->flags = flags;121121+ args->depend_tx = tx;122122+ args->cb_fn = cb_fn;123123+ args->cb_param = cb_param;124124+ args->scribble = scribble;125125+}126126+127127+void async_tx_submit(struct dma_chan *chan, struct dma_async_tx_descriptor *tx,128128+ struct async_submit_ctl *submit);153129154130struct dma_async_tx_descriptor *155131async_xor(struct page *dest, struct page **src_list, unsigned int offset,156156- int src_cnt, size_t len, enum async_tx_flags flags,157157- struct dma_async_tx_descriptor *depend_tx,158158- dma_async_tx_callback cb_fn, void *cb_fn_param);132132+ int src_cnt, size_t len, struct async_submit_ctl *submit);159133160134struct dma_async_tx_descriptor *161161-async_xor_zero_sum(struct page *dest, struct page **src_list,162162- unsigned int offset, int src_cnt, size_t len,163163- u32 *result, enum async_tx_flags flags,164164- struct dma_async_tx_descriptor *depend_tx,165165- dma_async_tx_callback cb_fn, void *cb_fn_param);135135+async_xor_val(struct page *dest, struct page **src_list, unsigned int offset,136136+ int src_cnt, size_t len, enum sum_check_flags *result,137137+ struct async_submit_ctl *submit);166138167139struct dma_async_tx_descriptor *168140async_memcpy(struct page *dest, struct page *src, unsigned int dest_offset,169169- unsigned int src_offset, size_t len, enum async_tx_flags flags,170170- struct dma_async_tx_descriptor *depend_tx,171171- dma_async_tx_callback cb_fn, void *cb_fn_param);141141+ unsigned int src_offset, size_t len,142142+ struct async_submit_ctl *submit);172143173144struct dma_async_tx_descriptor *174145async_memset(struct page *dest, int val, unsigned int offset,175175- size_t len, enum async_tx_flags flags,176176- struct dma_async_tx_descriptor *depend_tx,177177- dma_async_tx_callback cb_fn, void *cb_fn_param);146146+ size_t len, struct async_submit_ctl *submit);147147+148148+struct dma_async_tx_descriptor *async_trigger_callback(struct async_submit_ctl *submit);178149179150struct dma_async_tx_descriptor *180180-async_trigger_callback(enum async_tx_flags flags,181181- struct dma_async_tx_descriptor *depend_tx,182182- dma_async_tx_callback cb_fn, void *cb_fn_param);151151+async_gen_syndrome(struct page **blocks, unsigned int offset, int src_cnt,152152+ size_t len, struct async_submit_ctl *submit);153153+154154+struct dma_async_tx_descriptor *155155+async_syndrome_val(struct page **blocks, unsigned int offset, int src_cnt,156156+ size_t len, enum sum_check_flags *pqres, struct page *spare,157157+ struct async_submit_ctl *submit);158158+159159+struct dma_async_tx_descriptor *160160+async_raid6_2data_recov(int src_num, size_t bytes, int faila, int failb,161161+ struct page **ptrs, struct async_submit_ctl *submit);162162+163163+struct dma_async_tx_descriptor *164164+async_raid6_datap_recov(int src_num, size_t bytes, int faila,165165+ struct page **ptrs, struct async_submit_ctl *submit);183166184167void async_tx_quiesce(struct dma_async_tx_descriptor **tx);185168#endif /* _ASYNC_TX_H_ */
···48484949/**5050 * enum dma_transaction_type - DMA transaction types/indexes5151+ *5252+ * Note: The DMA_ASYNC_TX capability is not to be set by drivers. It is5353+ * automatically set as dma devices are registered.5154 */5255enum dma_transaction_type {5356 DMA_MEMCPY,5457 DMA_XOR,5555- DMA_PQ_XOR,5656- DMA_DUAL_XOR,5757- DMA_PQ_UPDATE,5858- DMA_ZERO_SUM,5959- DMA_PQ_ZERO_SUM,5858+ DMA_PQ,5959+ DMA_XOR_VAL,6060+ DMA_PQ_VAL,6061 DMA_MEMSET,6161- DMA_MEMCPY_CRC32C,6262 DMA_INTERRUPT,6363 DMA_PRIVATE,6464+ DMA_ASYNC_TX,6465 DMA_SLAVE,6566};6667···71707271/**7372 * enum dma_ctrl_flags - DMA flags to augment operation preparation,7474- * control completion, and communicate status.7373+ * control completion, and communicate status.7574 * @DMA_PREP_INTERRUPT - trigger an interrupt (callback) upon completion of7676- * this transaction7575+ * this transaction7776 * @DMA_CTRL_ACK - the descriptor cannot be reused until the client7878- * acknowledges receipt, i.e. has has a chance to establish any7979- * dependency chains7777+ * acknowledges receipt, i.e. has has a chance to establish any dependency7878+ * chains8079 * @DMA_COMPL_SKIP_SRC_UNMAP - set to disable dma-unmapping the source buffer(s)8180 * @DMA_COMPL_SKIP_DEST_UNMAP - set to disable dma-unmapping the destination(s)8281 * @DMA_COMPL_SRC_UNMAP_SINGLE - set to do the source dma-unmapping as single8382 * (if not set, do the source dma-unmapping as page)8483 * @DMA_COMPL_DEST_UNMAP_SINGLE - set to do the destination dma-unmapping as single8584 * (if not set, do the destination dma-unmapping as page)8585+ * @DMA_PREP_PQ_DISABLE_P - prevent generation of P while generating Q8686+ * @DMA_PREP_PQ_DISABLE_Q - prevent generation of Q while generating P8787+ * @DMA_PREP_CONTINUE - indicate to a driver that it is reusing buffers as8888+ * sources that were the result of a previous operation, in the case of a PQ8989+ * operation it continues the calculation with new sources9090+ * @DMA_PREP_FENCE - tell the driver that subsequent operations depend9191+ * on the result of this operation8692 */8793enum dma_ctrl_flags {8894 DMA_PREP_INTERRUPT = (1 << 0),···9890 DMA_COMPL_SKIP_DEST_UNMAP = (1 << 3),9991 DMA_COMPL_SRC_UNMAP_SINGLE = (1 << 4),10092 DMA_COMPL_DEST_UNMAP_SINGLE = (1 << 5),9393+ DMA_PREP_PQ_DISABLE_P = (1 << 6),9494+ DMA_PREP_PQ_DISABLE_Q = (1 << 7),9595+ DMA_PREP_CONTINUE = (1 << 8),9696+ DMA_PREP_FENCE = (1 << 9),10197};9898+9999+/**100100+ * enum sum_check_bits - bit position of pq_check_flags101101+ */102102+enum sum_check_bits {103103+ SUM_CHECK_P = 0,104104+ SUM_CHECK_Q = 1,105105+};106106+107107+/**108108+ * enum pq_check_flags - result of async_{xor,pq}_zero_sum operations109109+ * @SUM_CHECK_P_RESULT - 1 if xor zero sum error, 0 otherwise110110+ * @SUM_CHECK_Q_RESULT - 1 if reed-solomon zero sum error, 0 otherwise111111+ */112112+enum sum_check_flags {113113+ SUM_CHECK_P_RESULT = (1 << SUM_CHECK_P),114114+ SUM_CHECK_Q_RESULT = (1 << SUM_CHECK_Q),115115+};116116+102117103118/**104119 * dma_cap_mask_t - capabilities bitmap modeled after cpumask_t.···211180 * @flags: flags to augment operation preparation, control completion, and212181 * communicate status213182 * @phys: physical address of the descriptor214214- * @tx_list: driver common field for operations that require multiple215215- * descriptors216183 * @chan: target channel for this operation217184 * @tx_submit: set the prepared descriptor(s) to be executed by the engine218185 * @callback: routine to call after this operation is complete···224195 dma_cookie_t cookie;225196 enum dma_ctrl_flags flags; /* not a 'long' to pack with cookie */226197 dma_addr_t phys;227227- struct list_head tx_list;228198 struct dma_chan *chan;229199 dma_cookie_t (*tx_submit)(struct dma_async_tx_descriptor *tx);230200 dma_async_tx_callback callback;···241213 * @global_node: list_head for global dma_device_list242214 * @cap_mask: one or more dma_capability flags243215 * @max_xor: maximum number of xor sources, 0 if no capability216216+ * @max_pq: maximum number of PQ sources and PQ-continue capability217217+ * @copy_align: alignment shift for memcpy operations218218+ * @xor_align: alignment shift for xor operations219219+ * @pq_align: alignment shift for pq operations220220+ * @fill_align: alignment shift for memset operations244221 * @dev_id: unique device ID245222 * @dev: struct device reference for dma mapping api246223 * @device_alloc_chan_resources: allocate resources and return the···253220 * @device_free_chan_resources: release DMA channel's resources254221 * @device_prep_dma_memcpy: prepares a memcpy operation255222 * @device_prep_dma_xor: prepares a xor operation256256- * @device_prep_dma_zero_sum: prepares a zero_sum operation223223+ * @device_prep_dma_xor_val: prepares a xor validation operation224224+ * @device_prep_dma_pq: prepares a pq operation225225+ * @device_prep_dma_pq_val: prepares a pqzero_sum operation257226 * @device_prep_dma_memset: prepares a memset operation258227 * @device_prep_dma_interrupt: prepares an end of chain interrupt operation259228 * @device_prep_slave_sg: prepares a slave dma operation···270235 struct list_head channels;271236 struct list_head global_node;272237 dma_cap_mask_t cap_mask;273273- int max_xor;238238+ unsigned short max_xor;239239+ unsigned short max_pq;240240+ u8 copy_align;241241+ u8 xor_align;242242+ u8 pq_align;243243+ u8 fill_align;244244+ #define DMA_HAS_PQ_CONTINUE (1 << 15)274245275246 int dev_id;276247 struct device *dev;···290249 struct dma_async_tx_descriptor *(*device_prep_dma_xor)(291250 struct dma_chan *chan, dma_addr_t dest, dma_addr_t *src,292251 unsigned int src_cnt, size_t len, unsigned long flags);293293- struct dma_async_tx_descriptor *(*device_prep_dma_zero_sum)(252252+ struct dma_async_tx_descriptor *(*device_prep_dma_xor_val)(294253 struct dma_chan *chan, dma_addr_t *src, unsigned int src_cnt,295295- size_t len, u32 *result, unsigned long flags);254254+ size_t len, enum sum_check_flags *result, unsigned long flags);255255+ struct dma_async_tx_descriptor *(*device_prep_dma_pq)(256256+ struct dma_chan *chan, dma_addr_t *dst, dma_addr_t *src,257257+ unsigned int src_cnt, const unsigned char *scf,258258+ size_t len, unsigned long flags);259259+ struct dma_async_tx_descriptor *(*device_prep_dma_pq_val)(260260+ struct dma_chan *chan, dma_addr_t *pq, dma_addr_t *src,261261+ unsigned int src_cnt, const unsigned char *scf, size_t len,262262+ enum sum_check_flags *pqres, unsigned long flags);296263 struct dma_async_tx_descriptor *(*device_prep_dma_memset)(297264 struct dma_chan *chan, dma_addr_t dest, int value, size_t len,298265 unsigned long flags);···318269 dma_cookie_t *used);319270 void (*device_issue_pending)(struct dma_chan *chan);320271};272272+273273+static inline bool dmaengine_check_align(u8 align, size_t off1, size_t off2, size_t len)274274+{275275+ size_t mask;276276+277277+ if (!align)278278+ return true;279279+ mask = (1 << align) - 1;280280+ if (mask & (off1 | off2 | len))281281+ return false;282282+ return true;283283+}284284+285285+static inline bool is_dma_copy_aligned(struct dma_device *dev, size_t off1,286286+ size_t off2, size_t len)287287+{288288+ return dmaengine_check_align(dev->copy_align, off1, off2, len);289289+}290290+291291+static inline bool is_dma_xor_aligned(struct dma_device *dev, size_t off1,292292+ size_t off2, size_t len)293293+{294294+ return dmaengine_check_align(dev->xor_align, off1, off2, len);295295+}296296+297297+static inline bool is_dma_pq_aligned(struct dma_device *dev, size_t off1,298298+ size_t off2, size_t len)299299+{300300+ return dmaengine_check_align(dev->pq_align, off1, off2, len);301301+}302302+303303+static inline bool is_dma_fill_aligned(struct dma_device *dev, size_t off1,304304+ size_t off2, size_t len)305305+{306306+ return dmaengine_check_align(dev->fill_align, off1, off2, len);307307+}308308+309309+static inline void310310+dma_set_maxpq(struct dma_device *dma, int maxpq, int has_pq_continue)311311+{312312+ dma->max_pq = maxpq;313313+ if (has_pq_continue)314314+ dma->max_pq |= DMA_HAS_PQ_CONTINUE;315315+}316316+317317+static inline bool dmaf_continue(enum dma_ctrl_flags flags)318318+{319319+ return (flags & DMA_PREP_CONTINUE) == DMA_PREP_CONTINUE;320320+}321321+322322+static inline bool dmaf_p_disabled_continue(enum dma_ctrl_flags flags)323323+{324324+ enum dma_ctrl_flags mask = DMA_PREP_CONTINUE | DMA_PREP_PQ_DISABLE_P;325325+326326+ return (flags & mask) == mask;327327+}328328+329329+static inline bool dma_dev_has_pq_continue(struct dma_device *dma)330330+{331331+ return (dma->max_pq & DMA_HAS_PQ_CONTINUE) == DMA_HAS_PQ_CONTINUE;332332+}333333+334334+static unsigned short dma_dev_to_maxpq(struct dma_device *dma)335335+{336336+ return dma->max_pq & ~DMA_HAS_PQ_CONTINUE;337337+}338338+339339+/* dma_maxpq - reduce maxpq in the face of continued operations340340+ * @dma - dma device with PQ capability341341+ * @flags - to check if DMA_PREP_CONTINUE and DMA_PREP_PQ_DISABLE_P are set342342+ *343343+ * When an engine does not support native continuation we need 3 extra344344+ * source slots to reuse P and Q with the following coefficients:345345+ * 1/ {00} * P : remove P from Q', but use it as a source for P'346346+ * 2/ {01} * Q : use Q to continue Q' calculation347347+ * 3/ {00} * Q : subtract Q from P' to cancel (2)348348+ *349349+ * In the case where P is disabled we only need 1 extra source:350350+ * 1/ {01} * Q : use Q to continue Q' calculation351351+ */352352+static inline int dma_maxpq(struct dma_device *dma, enum dma_ctrl_flags flags)353353+{354354+ if (dma_dev_has_pq_continue(dma) || !dmaf_continue(flags))355355+ return dma_dev_to_maxpq(dma);356356+ else if (dmaf_p_disabled_continue(flags))357357+ return dma_dev_to_maxpq(dma) - 1;358358+ else if (dmaf_continue(flags))359359+ return dma_dev_to_maxpq(dma) - 3;360360+ BUG();361361+}321362322363/* --- public DMA engine API --- */323364···438299#ifdef CONFIG_ASYNC_TX_DMA439300#define async_dmaengine_get() dmaengine_get()440301#define async_dmaengine_put() dmaengine_put()302302+#ifdef CONFIG_ASYNC_TX_DISABLE_CHANNEL_SWITCH303303+#define async_dma_find_channel(type) dma_find_channel(DMA_ASYNC_TX)304304+#else441305#define async_dma_find_channel(type) dma_find_channel(type)306306+#endif /* CONFIG_ASYNC_TX_DISABLE_CHANNEL_SWITCH */442307#else443308static inline void async_dmaengine_get(void)444309{···455312{456313 return NULL;457314}458458-#endif315315+#endif /* CONFIG_ASYNC_TX_DMA */459316460317dma_cookie_t dma_async_memcpy_buf_to_buf(struct dma_chan *chan,461318 void *dest, void *src, size_t len);