1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun * Microsemi Switchtec(tm) PCIe Management Driver
4*4882a593Smuzhiyun * Copyright (c) 2019, Logan Gunthorpe <logang@deltatee.com>
5*4882a593Smuzhiyun * Copyright (c) 2019, GigaIO Networks, Inc
6*4882a593Smuzhiyun */
7*4882a593Smuzhiyun
8*4882a593Smuzhiyun #include "dmaengine.h"
9*4882a593Smuzhiyun
10*4882a593Smuzhiyun #include <linux/circ_buf.h>
11*4882a593Smuzhiyun #include <linux/dmaengine.h>
12*4882a593Smuzhiyun #include <linux/kref.h>
13*4882a593Smuzhiyun #include <linux/list.h>
14*4882a593Smuzhiyun #include <linux/module.h>
15*4882a593Smuzhiyun #include <linux/pci.h>
16*4882a593Smuzhiyun
17*4882a593Smuzhiyun MODULE_DESCRIPTION("PLX ExpressLane PEX PCI Switch DMA Engine");
18*4882a593Smuzhiyun MODULE_VERSION("0.1");
19*4882a593Smuzhiyun MODULE_LICENSE("GPL");
20*4882a593Smuzhiyun MODULE_AUTHOR("Logan Gunthorpe");
21*4882a593Smuzhiyun
22*4882a593Smuzhiyun #define PLX_REG_DESC_RING_ADDR 0x214
23*4882a593Smuzhiyun #define PLX_REG_DESC_RING_ADDR_HI 0x218
24*4882a593Smuzhiyun #define PLX_REG_DESC_RING_NEXT_ADDR 0x21C
25*4882a593Smuzhiyun #define PLX_REG_DESC_RING_COUNT 0x220
26*4882a593Smuzhiyun #define PLX_REG_DESC_RING_LAST_ADDR 0x224
27*4882a593Smuzhiyun #define PLX_REG_DESC_RING_LAST_SIZE 0x228
28*4882a593Smuzhiyun #define PLX_REG_PREF_LIMIT 0x234
29*4882a593Smuzhiyun #define PLX_REG_CTRL 0x238
30*4882a593Smuzhiyun #define PLX_REG_CTRL2 0x23A
31*4882a593Smuzhiyun #define PLX_REG_INTR_CTRL 0x23C
32*4882a593Smuzhiyun #define PLX_REG_INTR_STATUS 0x23E
33*4882a593Smuzhiyun
34*4882a593Smuzhiyun #define PLX_REG_PREF_LIMIT_PREF_FOUR 8
35*4882a593Smuzhiyun
36*4882a593Smuzhiyun #define PLX_REG_CTRL_GRACEFUL_PAUSE BIT(0)
37*4882a593Smuzhiyun #define PLX_REG_CTRL_ABORT BIT(1)
38*4882a593Smuzhiyun #define PLX_REG_CTRL_WRITE_BACK_EN BIT(2)
39*4882a593Smuzhiyun #define PLX_REG_CTRL_START BIT(3)
40*4882a593Smuzhiyun #define PLX_REG_CTRL_RING_STOP_MODE BIT(4)
41*4882a593Smuzhiyun #define PLX_REG_CTRL_DESC_MODE_BLOCK (0 << 5)
42*4882a593Smuzhiyun #define PLX_REG_CTRL_DESC_MODE_ON_CHIP (1 << 5)
43*4882a593Smuzhiyun #define PLX_REG_CTRL_DESC_MODE_OFF_CHIP (2 << 5)
44*4882a593Smuzhiyun #define PLX_REG_CTRL_DESC_INVALID BIT(8)
45*4882a593Smuzhiyun #define PLX_REG_CTRL_GRACEFUL_PAUSE_DONE BIT(9)
46*4882a593Smuzhiyun #define PLX_REG_CTRL_ABORT_DONE BIT(10)
47*4882a593Smuzhiyun #define PLX_REG_CTRL_IMM_PAUSE_DONE BIT(12)
48*4882a593Smuzhiyun #define PLX_REG_CTRL_IN_PROGRESS BIT(30)
49*4882a593Smuzhiyun
50*4882a593Smuzhiyun #define PLX_REG_CTRL_RESET_VAL (PLX_REG_CTRL_DESC_INVALID | \
51*4882a593Smuzhiyun PLX_REG_CTRL_GRACEFUL_PAUSE_DONE | \
52*4882a593Smuzhiyun PLX_REG_CTRL_ABORT_DONE | \
53*4882a593Smuzhiyun PLX_REG_CTRL_IMM_PAUSE_DONE)
54*4882a593Smuzhiyun
55*4882a593Smuzhiyun #define PLX_REG_CTRL_START_VAL (PLX_REG_CTRL_WRITE_BACK_EN | \
56*4882a593Smuzhiyun PLX_REG_CTRL_DESC_MODE_OFF_CHIP | \
57*4882a593Smuzhiyun PLX_REG_CTRL_START | \
58*4882a593Smuzhiyun PLX_REG_CTRL_RESET_VAL)
59*4882a593Smuzhiyun
60*4882a593Smuzhiyun #define PLX_REG_CTRL2_MAX_TXFR_SIZE_64B 0
61*4882a593Smuzhiyun #define PLX_REG_CTRL2_MAX_TXFR_SIZE_128B 1
62*4882a593Smuzhiyun #define PLX_REG_CTRL2_MAX_TXFR_SIZE_256B 2
63*4882a593Smuzhiyun #define PLX_REG_CTRL2_MAX_TXFR_SIZE_512B 3
64*4882a593Smuzhiyun #define PLX_REG_CTRL2_MAX_TXFR_SIZE_1KB 4
65*4882a593Smuzhiyun #define PLX_REG_CTRL2_MAX_TXFR_SIZE_2KB 5
66*4882a593Smuzhiyun #define PLX_REG_CTRL2_MAX_TXFR_SIZE_4B 7
67*4882a593Smuzhiyun
68*4882a593Smuzhiyun #define PLX_REG_INTR_CRTL_ERROR_EN BIT(0)
69*4882a593Smuzhiyun #define PLX_REG_INTR_CRTL_INV_DESC_EN BIT(1)
70*4882a593Smuzhiyun #define PLX_REG_INTR_CRTL_ABORT_DONE_EN BIT(3)
71*4882a593Smuzhiyun #define PLX_REG_INTR_CRTL_PAUSE_DONE_EN BIT(4)
72*4882a593Smuzhiyun #define PLX_REG_INTR_CRTL_IMM_PAUSE_DONE_EN BIT(5)
73*4882a593Smuzhiyun
74*4882a593Smuzhiyun #define PLX_REG_INTR_STATUS_ERROR BIT(0)
75*4882a593Smuzhiyun #define PLX_REG_INTR_STATUS_INV_DESC BIT(1)
76*4882a593Smuzhiyun #define PLX_REG_INTR_STATUS_DESC_DONE BIT(2)
77*4882a593Smuzhiyun #define PLX_REG_INTR_CRTL_ABORT_DONE BIT(3)
78*4882a593Smuzhiyun
79*4882a593Smuzhiyun struct plx_dma_hw_std_desc {
80*4882a593Smuzhiyun __le32 flags_and_size;
81*4882a593Smuzhiyun __le16 dst_addr_hi;
82*4882a593Smuzhiyun __le16 src_addr_hi;
83*4882a593Smuzhiyun __le32 dst_addr_lo;
84*4882a593Smuzhiyun __le32 src_addr_lo;
85*4882a593Smuzhiyun };
86*4882a593Smuzhiyun
87*4882a593Smuzhiyun #define PLX_DESC_SIZE_MASK 0x7ffffff
88*4882a593Smuzhiyun #define PLX_DESC_FLAG_VALID BIT(31)
89*4882a593Smuzhiyun #define PLX_DESC_FLAG_INT_WHEN_DONE BIT(30)
90*4882a593Smuzhiyun
91*4882a593Smuzhiyun #define PLX_DESC_WB_SUCCESS BIT(30)
92*4882a593Smuzhiyun #define PLX_DESC_WB_RD_FAIL BIT(29)
93*4882a593Smuzhiyun #define PLX_DESC_WB_WR_FAIL BIT(28)
94*4882a593Smuzhiyun
95*4882a593Smuzhiyun #define PLX_DMA_RING_COUNT 2048
96*4882a593Smuzhiyun
97*4882a593Smuzhiyun struct plx_dma_desc {
98*4882a593Smuzhiyun struct dma_async_tx_descriptor txd;
99*4882a593Smuzhiyun struct plx_dma_hw_std_desc *hw;
100*4882a593Smuzhiyun u32 orig_size;
101*4882a593Smuzhiyun };
102*4882a593Smuzhiyun
103*4882a593Smuzhiyun struct plx_dma_dev {
104*4882a593Smuzhiyun struct dma_device dma_dev;
105*4882a593Smuzhiyun struct dma_chan dma_chan;
106*4882a593Smuzhiyun struct pci_dev __rcu *pdev;
107*4882a593Smuzhiyun void __iomem *bar;
108*4882a593Smuzhiyun struct tasklet_struct desc_task;
109*4882a593Smuzhiyun
110*4882a593Smuzhiyun spinlock_t ring_lock;
111*4882a593Smuzhiyun bool ring_active;
112*4882a593Smuzhiyun int head;
113*4882a593Smuzhiyun int tail;
114*4882a593Smuzhiyun struct plx_dma_hw_std_desc *hw_ring;
115*4882a593Smuzhiyun dma_addr_t hw_ring_dma;
116*4882a593Smuzhiyun struct plx_dma_desc **desc_ring;
117*4882a593Smuzhiyun };
118*4882a593Smuzhiyun
chan_to_plx_dma_dev(struct dma_chan * c)119*4882a593Smuzhiyun static struct plx_dma_dev *chan_to_plx_dma_dev(struct dma_chan *c)
120*4882a593Smuzhiyun {
121*4882a593Smuzhiyun return container_of(c, struct plx_dma_dev, dma_chan);
122*4882a593Smuzhiyun }
123*4882a593Smuzhiyun
to_plx_desc(struct dma_async_tx_descriptor * txd)124*4882a593Smuzhiyun static struct plx_dma_desc *to_plx_desc(struct dma_async_tx_descriptor *txd)
125*4882a593Smuzhiyun {
126*4882a593Smuzhiyun return container_of(txd, struct plx_dma_desc, txd);
127*4882a593Smuzhiyun }
128*4882a593Smuzhiyun
plx_dma_get_desc(struct plx_dma_dev * plxdev,int i)129*4882a593Smuzhiyun static struct plx_dma_desc *plx_dma_get_desc(struct plx_dma_dev *plxdev, int i)
130*4882a593Smuzhiyun {
131*4882a593Smuzhiyun return plxdev->desc_ring[i & (PLX_DMA_RING_COUNT - 1)];
132*4882a593Smuzhiyun }
133*4882a593Smuzhiyun
plx_dma_process_desc(struct plx_dma_dev * plxdev)134*4882a593Smuzhiyun static void plx_dma_process_desc(struct plx_dma_dev *plxdev)
135*4882a593Smuzhiyun {
136*4882a593Smuzhiyun struct dmaengine_result res;
137*4882a593Smuzhiyun struct plx_dma_desc *desc;
138*4882a593Smuzhiyun u32 flags;
139*4882a593Smuzhiyun
140*4882a593Smuzhiyun spin_lock_bh(&plxdev->ring_lock);
141*4882a593Smuzhiyun
142*4882a593Smuzhiyun while (plxdev->tail != plxdev->head) {
143*4882a593Smuzhiyun desc = plx_dma_get_desc(plxdev, plxdev->tail);
144*4882a593Smuzhiyun
145*4882a593Smuzhiyun flags = le32_to_cpu(READ_ONCE(desc->hw->flags_and_size));
146*4882a593Smuzhiyun
147*4882a593Smuzhiyun if (flags & PLX_DESC_FLAG_VALID)
148*4882a593Smuzhiyun break;
149*4882a593Smuzhiyun
150*4882a593Smuzhiyun res.residue = desc->orig_size - (flags & PLX_DESC_SIZE_MASK);
151*4882a593Smuzhiyun
152*4882a593Smuzhiyun if (flags & PLX_DESC_WB_SUCCESS)
153*4882a593Smuzhiyun res.result = DMA_TRANS_NOERROR;
154*4882a593Smuzhiyun else if (flags & PLX_DESC_WB_WR_FAIL)
155*4882a593Smuzhiyun res.result = DMA_TRANS_WRITE_FAILED;
156*4882a593Smuzhiyun else
157*4882a593Smuzhiyun res.result = DMA_TRANS_READ_FAILED;
158*4882a593Smuzhiyun
159*4882a593Smuzhiyun dma_cookie_complete(&desc->txd);
160*4882a593Smuzhiyun dma_descriptor_unmap(&desc->txd);
161*4882a593Smuzhiyun dmaengine_desc_get_callback_invoke(&desc->txd, &res);
162*4882a593Smuzhiyun desc->txd.callback = NULL;
163*4882a593Smuzhiyun desc->txd.callback_result = NULL;
164*4882a593Smuzhiyun
165*4882a593Smuzhiyun plxdev->tail++;
166*4882a593Smuzhiyun }
167*4882a593Smuzhiyun
168*4882a593Smuzhiyun spin_unlock_bh(&plxdev->ring_lock);
169*4882a593Smuzhiyun }
170*4882a593Smuzhiyun
plx_dma_abort_desc(struct plx_dma_dev * plxdev)171*4882a593Smuzhiyun static void plx_dma_abort_desc(struct plx_dma_dev *plxdev)
172*4882a593Smuzhiyun {
173*4882a593Smuzhiyun struct dmaengine_result res;
174*4882a593Smuzhiyun struct plx_dma_desc *desc;
175*4882a593Smuzhiyun
176*4882a593Smuzhiyun plx_dma_process_desc(plxdev);
177*4882a593Smuzhiyun
178*4882a593Smuzhiyun spin_lock_bh(&plxdev->ring_lock);
179*4882a593Smuzhiyun
180*4882a593Smuzhiyun while (plxdev->tail != plxdev->head) {
181*4882a593Smuzhiyun desc = plx_dma_get_desc(plxdev, plxdev->tail);
182*4882a593Smuzhiyun
183*4882a593Smuzhiyun res.residue = desc->orig_size;
184*4882a593Smuzhiyun res.result = DMA_TRANS_ABORTED;
185*4882a593Smuzhiyun
186*4882a593Smuzhiyun dma_cookie_complete(&desc->txd);
187*4882a593Smuzhiyun dma_descriptor_unmap(&desc->txd);
188*4882a593Smuzhiyun dmaengine_desc_get_callback_invoke(&desc->txd, &res);
189*4882a593Smuzhiyun desc->txd.callback = NULL;
190*4882a593Smuzhiyun desc->txd.callback_result = NULL;
191*4882a593Smuzhiyun
192*4882a593Smuzhiyun plxdev->tail++;
193*4882a593Smuzhiyun }
194*4882a593Smuzhiyun
195*4882a593Smuzhiyun spin_unlock_bh(&plxdev->ring_lock);
196*4882a593Smuzhiyun }
197*4882a593Smuzhiyun
__plx_dma_stop(struct plx_dma_dev * plxdev)198*4882a593Smuzhiyun static void __plx_dma_stop(struct plx_dma_dev *plxdev)
199*4882a593Smuzhiyun {
200*4882a593Smuzhiyun unsigned long timeout = jiffies + msecs_to_jiffies(1000);
201*4882a593Smuzhiyun u32 val;
202*4882a593Smuzhiyun
203*4882a593Smuzhiyun val = readl(plxdev->bar + PLX_REG_CTRL);
204*4882a593Smuzhiyun if (!(val & ~PLX_REG_CTRL_GRACEFUL_PAUSE))
205*4882a593Smuzhiyun return;
206*4882a593Smuzhiyun
207*4882a593Smuzhiyun writel(PLX_REG_CTRL_RESET_VAL | PLX_REG_CTRL_GRACEFUL_PAUSE,
208*4882a593Smuzhiyun plxdev->bar + PLX_REG_CTRL);
209*4882a593Smuzhiyun
210*4882a593Smuzhiyun while (!time_after(jiffies, timeout)) {
211*4882a593Smuzhiyun val = readl(plxdev->bar + PLX_REG_CTRL);
212*4882a593Smuzhiyun if (val & PLX_REG_CTRL_GRACEFUL_PAUSE_DONE)
213*4882a593Smuzhiyun break;
214*4882a593Smuzhiyun
215*4882a593Smuzhiyun cpu_relax();
216*4882a593Smuzhiyun }
217*4882a593Smuzhiyun
218*4882a593Smuzhiyun if (!(val & PLX_REG_CTRL_GRACEFUL_PAUSE_DONE))
219*4882a593Smuzhiyun dev_err(plxdev->dma_dev.dev,
220*4882a593Smuzhiyun "Timeout waiting for graceful pause!\n");
221*4882a593Smuzhiyun
222*4882a593Smuzhiyun writel(PLX_REG_CTRL_RESET_VAL | PLX_REG_CTRL_GRACEFUL_PAUSE,
223*4882a593Smuzhiyun plxdev->bar + PLX_REG_CTRL);
224*4882a593Smuzhiyun
225*4882a593Smuzhiyun writel(0, plxdev->bar + PLX_REG_DESC_RING_COUNT);
226*4882a593Smuzhiyun writel(0, plxdev->bar + PLX_REG_DESC_RING_ADDR);
227*4882a593Smuzhiyun writel(0, plxdev->bar + PLX_REG_DESC_RING_ADDR_HI);
228*4882a593Smuzhiyun writel(0, plxdev->bar + PLX_REG_DESC_RING_NEXT_ADDR);
229*4882a593Smuzhiyun }
230*4882a593Smuzhiyun
plx_dma_stop(struct plx_dma_dev * plxdev)231*4882a593Smuzhiyun static void plx_dma_stop(struct plx_dma_dev *plxdev)
232*4882a593Smuzhiyun {
233*4882a593Smuzhiyun rcu_read_lock();
234*4882a593Smuzhiyun if (!rcu_dereference(plxdev->pdev)) {
235*4882a593Smuzhiyun rcu_read_unlock();
236*4882a593Smuzhiyun return;
237*4882a593Smuzhiyun }
238*4882a593Smuzhiyun
239*4882a593Smuzhiyun __plx_dma_stop(plxdev);
240*4882a593Smuzhiyun
241*4882a593Smuzhiyun rcu_read_unlock();
242*4882a593Smuzhiyun }
243*4882a593Smuzhiyun
plx_dma_desc_task(struct tasklet_struct * t)244*4882a593Smuzhiyun static void plx_dma_desc_task(struct tasklet_struct *t)
245*4882a593Smuzhiyun {
246*4882a593Smuzhiyun struct plx_dma_dev *plxdev = from_tasklet(plxdev, t, desc_task);
247*4882a593Smuzhiyun
248*4882a593Smuzhiyun plx_dma_process_desc(plxdev);
249*4882a593Smuzhiyun }
250*4882a593Smuzhiyun
plx_dma_prep_memcpy(struct dma_chan * c,dma_addr_t dma_dst,dma_addr_t dma_src,size_t len,unsigned long flags)251*4882a593Smuzhiyun static struct dma_async_tx_descriptor *plx_dma_prep_memcpy(struct dma_chan *c,
252*4882a593Smuzhiyun dma_addr_t dma_dst, dma_addr_t dma_src, size_t len,
253*4882a593Smuzhiyun unsigned long flags)
254*4882a593Smuzhiyun __acquires(plxdev->ring_lock)
255*4882a593Smuzhiyun {
256*4882a593Smuzhiyun struct plx_dma_dev *plxdev = chan_to_plx_dma_dev(c);
257*4882a593Smuzhiyun struct plx_dma_desc *plxdesc;
258*4882a593Smuzhiyun
259*4882a593Smuzhiyun spin_lock_bh(&plxdev->ring_lock);
260*4882a593Smuzhiyun if (!plxdev->ring_active)
261*4882a593Smuzhiyun goto err_unlock;
262*4882a593Smuzhiyun
263*4882a593Smuzhiyun if (!CIRC_SPACE(plxdev->head, plxdev->tail, PLX_DMA_RING_COUNT))
264*4882a593Smuzhiyun goto err_unlock;
265*4882a593Smuzhiyun
266*4882a593Smuzhiyun if (len > PLX_DESC_SIZE_MASK)
267*4882a593Smuzhiyun goto err_unlock;
268*4882a593Smuzhiyun
269*4882a593Smuzhiyun plxdesc = plx_dma_get_desc(plxdev, plxdev->head);
270*4882a593Smuzhiyun plxdev->head++;
271*4882a593Smuzhiyun
272*4882a593Smuzhiyun plxdesc->hw->dst_addr_lo = cpu_to_le32(lower_32_bits(dma_dst));
273*4882a593Smuzhiyun plxdesc->hw->dst_addr_hi = cpu_to_le16(upper_32_bits(dma_dst));
274*4882a593Smuzhiyun plxdesc->hw->src_addr_lo = cpu_to_le32(lower_32_bits(dma_src));
275*4882a593Smuzhiyun plxdesc->hw->src_addr_hi = cpu_to_le16(upper_32_bits(dma_src));
276*4882a593Smuzhiyun
277*4882a593Smuzhiyun plxdesc->orig_size = len;
278*4882a593Smuzhiyun
279*4882a593Smuzhiyun if (flags & DMA_PREP_INTERRUPT)
280*4882a593Smuzhiyun len |= PLX_DESC_FLAG_INT_WHEN_DONE;
281*4882a593Smuzhiyun
282*4882a593Smuzhiyun plxdesc->hw->flags_and_size = cpu_to_le32(len);
283*4882a593Smuzhiyun plxdesc->txd.flags = flags;
284*4882a593Smuzhiyun
285*4882a593Smuzhiyun /* return with the lock held, it will be released in tx_submit */
286*4882a593Smuzhiyun
287*4882a593Smuzhiyun return &plxdesc->txd;
288*4882a593Smuzhiyun
289*4882a593Smuzhiyun err_unlock:
290*4882a593Smuzhiyun /*
291*4882a593Smuzhiyun * Keep sparse happy by restoring an even lock count on
292*4882a593Smuzhiyun * this lock.
293*4882a593Smuzhiyun */
294*4882a593Smuzhiyun __acquire(plxdev->ring_lock);
295*4882a593Smuzhiyun
296*4882a593Smuzhiyun spin_unlock_bh(&plxdev->ring_lock);
297*4882a593Smuzhiyun return NULL;
298*4882a593Smuzhiyun }
299*4882a593Smuzhiyun
plx_dma_tx_submit(struct dma_async_tx_descriptor * desc)300*4882a593Smuzhiyun static dma_cookie_t plx_dma_tx_submit(struct dma_async_tx_descriptor *desc)
301*4882a593Smuzhiyun __releases(plxdev->ring_lock)
302*4882a593Smuzhiyun {
303*4882a593Smuzhiyun struct plx_dma_dev *plxdev = chan_to_plx_dma_dev(desc->chan);
304*4882a593Smuzhiyun struct plx_dma_desc *plxdesc = to_plx_desc(desc);
305*4882a593Smuzhiyun dma_cookie_t cookie;
306*4882a593Smuzhiyun
307*4882a593Smuzhiyun cookie = dma_cookie_assign(desc);
308*4882a593Smuzhiyun
309*4882a593Smuzhiyun /*
310*4882a593Smuzhiyun * Ensure the descriptor updates are visible to the dma device
311*4882a593Smuzhiyun * before setting the valid bit.
312*4882a593Smuzhiyun */
313*4882a593Smuzhiyun wmb();
314*4882a593Smuzhiyun
315*4882a593Smuzhiyun plxdesc->hw->flags_and_size |= cpu_to_le32(PLX_DESC_FLAG_VALID);
316*4882a593Smuzhiyun
317*4882a593Smuzhiyun spin_unlock_bh(&plxdev->ring_lock);
318*4882a593Smuzhiyun
319*4882a593Smuzhiyun return cookie;
320*4882a593Smuzhiyun }
321*4882a593Smuzhiyun
plx_dma_tx_status(struct dma_chan * chan,dma_cookie_t cookie,struct dma_tx_state * txstate)322*4882a593Smuzhiyun static enum dma_status plx_dma_tx_status(struct dma_chan *chan,
323*4882a593Smuzhiyun dma_cookie_t cookie, struct dma_tx_state *txstate)
324*4882a593Smuzhiyun {
325*4882a593Smuzhiyun struct plx_dma_dev *plxdev = chan_to_plx_dma_dev(chan);
326*4882a593Smuzhiyun enum dma_status ret;
327*4882a593Smuzhiyun
328*4882a593Smuzhiyun ret = dma_cookie_status(chan, cookie, txstate);
329*4882a593Smuzhiyun if (ret == DMA_COMPLETE)
330*4882a593Smuzhiyun return ret;
331*4882a593Smuzhiyun
332*4882a593Smuzhiyun plx_dma_process_desc(plxdev);
333*4882a593Smuzhiyun
334*4882a593Smuzhiyun return dma_cookie_status(chan, cookie, txstate);
335*4882a593Smuzhiyun }
336*4882a593Smuzhiyun
plx_dma_issue_pending(struct dma_chan * chan)337*4882a593Smuzhiyun static void plx_dma_issue_pending(struct dma_chan *chan)
338*4882a593Smuzhiyun {
339*4882a593Smuzhiyun struct plx_dma_dev *plxdev = chan_to_plx_dma_dev(chan);
340*4882a593Smuzhiyun
341*4882a593Smuzhiyun rcu_read_lock();
342*4882a593Smuzhiyun if (!rcu_dereference(plxdev->pdev)) {
343*4882a593Smuzhiyun rcu_read_unlock();
344*4882a593Smuzhiyun return;
345*4882a593Smuzhiyun }
346*4882a593Smuzhiyun
347*4882a593Smuzhiyun /*
348*4882a593Smuzhiyun * Ensure the valid bits are visible before starting the
349*4882a593Smuzhiyun * DMA engine.
350*4882a593Smuzhiyun */
351*4882a593Smuzhiyun wmb();
352*4882a593Smuzhiyun
353*4882a593Smuzhiyun writew(PLX_REG_CTRL_START_VAL, plxdev->bar + PLX_REG_CTRL);
354*4882a593Smuzhiyun
355*4882a593Smuzhiyun rcu_read_unlock();
356*4882a593Smuzhiyun }
357*4882a593Smuzhiyun
plx_dma_isr(int irq,void * devid)358*4882a593Smuzhiyun static irqreturn_t plx_dma_isr(int irq, void *devid)
359*4882a593Smuzhiyun {
360*4882a593Smuzhiyun struct plx_dma_dev *plxdev = devid;
361*4882a593Smuzhiyun u32 status;
362*4882a593Smuzhiyun
363*4882a593Smuzhiyun status = readw(plxdev->bar + PLX_REG_INTR_STATUS);
364*4882a593Smuzhiyun
365*4882a593Smuzhiyun if (!status)
366*4882a593Smuzhiyun return IRQ_NONE;
367*4882a593Smuzhiyun
368*4882a593Smuzhiyun if (status & PLX_REG_INTR_STATUS_DESC_DONE && plxdev->ring_active)
369*4882a593Smuzhiyun tasklet_schedule(&plxdev->desc_task);
370*4882a593Smuzhiyun
371*4882a593Smuzhiyun writew(status, plxdev->bar + PLX_REG_INTR_STATUS);
372*4882a593Smuzhiyun
373*4882a593Smuzhiyun return IRQ_HANDLED;
374*4882a593Smuzhiyun }
375*4882a593Smuzhiyun
plx_dma_alloc_desc(struct plx_dma_dev * plxdev)376*4882a593Smuzhiyun static int plx_dma_alloc_desc(struct plx_dma_dev *plxdev)
377*4882a593Smuzhiyun {
378*4882a593Smuzhiyun struct plx_dma_desc *desc;
379*4882a593Smuzhiyun int i;
380*4882a593Smuzhiyun
381*4882a593Smuzhiyun plxdev->desc_ring = kcalloc(PLX_DMA_RING_COUNT,
382*4882a593Smuzhiyun sizeof(*plxdev->desc_ring), GFP_KERNEL);
383*4882a593Smuzhiyun if (!plxdev->desc_ring)
384*4882a593Smuzhiyun return -ENOMEM;
385*4882a593Smuzhiyun
386*4882a593Smuzhiyun for (i = 0; i < PLX_DMA_RING_COUNT; i++) {
387*4882a593Smuzhiyun desc = kzalloc(sizeof(*desc), GFP_KERNEL);
388*4882a593Smuzhiyun if (!desc)
389*4882a593Smuzhiyun goto free_and_exit;
390*4882a593Smuzhiyun
391*4882a593Smuzhiyun dma_async_tx_descriptor_init(&desc->txd, &plxdev->dma_chan);
392*4882a593Smuzhiyun desc->txd.tx_submit = plx_dma_tx_submit;
393*4882a593Smuzhiyun desc->hw = &plxdev->hw_ring[i];
394*4882a593Smuzhiyun
395*4882a593Smuzhiyun plxdev->desc_ring[i] = desc;
396*4882a593Smuzhiyun }
397*4882a593Smuzhiyun
398*4882a593Smuzhiyun return 0;
399*4882a593Smuzhiyun
400*4882a593Smuzhiyun free_and_exit:
401*4882a593Smuzhiyun for (i = 0; i < PLX_DMA_RING_COUNT; i++)
402*4882a593Smuzhiyun kfree(plxdev->desc_ring[i]);
403*4882a593Smuzhiyun kfree(plxdev->desc_ring);
404*4882a593Smuzhiyun return -ENOMEM;
405*4882a593Smuzhiyun }
406*4882a593Smuzhiyun
plx_dma_alloc_chan_resources(struct dma_chan * chan)407*4882a593Smuzhiyun static int plx_dma_alloc_chan_resources(struct dma_chan *chan)
408*4882a593Smuzhiyun {
409*4882a593Smuzhiyun struct plx_dma_dev *plxdev = chan_to_plx_dma_dev(chan);
410*4882a593Smuzhiyun size_t ring_sz = PLX_DMA_RING_COUNT * sizeof(*plxdev->hw_ring);
411*4882a593Smuzhiyun int rc;
412*4882a593Smuzhiyun
413*4882a593Smuzhiyun plxdev->head = plxdev->tail = 0;
414*4882a593Smuzhiyun plxdev->hw_ring = dma_alloc_coherent(plxdev->dma_dev.dev, ring_sz,
415*4882a593Smuzhiyun &plxdev->hw_ring_dma, GFP_KERNEL);
416*4882a593Smuzhiyun if (!plxdev->hw_ring)
417*4882a593Smuzhiyun return -ENOMEM;
418*4882a593Smuzhiyun
419*4882a593Smuzhiyun rc = plx_dma_alloc_desc(plxdev);
420*4882a593Smuzhiyun if (rc)
421*4882a593Smuzhiyun goto out_free_hw_ring;
422*4882a593Smuzhiyun
423*4882a593Smuzhiyun rcu_read_lock();
424*4882a593Smuzhiyun if (!rcu_dereference(plxdev->pdev)) {
425*4882a593Smuzhiyun rcu_read_unlock();
426*4882a593Smuzhiyun rc = -ENODEV;
427*4882a593Smuzhiyun goto out_free_hw_ring;
428*4882a593Smuzhiyun }
429*4882a593Smuzhiyun
430*4882a593Smuzhiyun writel(PLX_REG_CTRL_RESET_VAL, plxdev->bar + PLX_REG_CTRL);
431*4882a593Smuzhiyun writel(lower_32_bits(plxdev->hw_ring_dma),
432*4882a593Smuzhiyun plxdev->bar + PLX_REG_DESC_RING_ADDR);
433*4882a593Smuzhiyun writel(upper_32_bits(plxdev->hw_ring_dma),
434*4882a593Smuzhiyun plxdev->bar + PLX_REG_DESC_RING_ADDR_HI);
435*4882a593Smuzhiyun writel(lower_32_bits(plxdev->hw_ring_dma),
436*4882a593Smuzhiyun plxdev->bar + PLX_REG_DESC_RING_NEXT_ADDR);
437*4882a593Smuzhiyun writel(PLX_DMA_RING_COUNT, plxdev->bar + PLX_REG_DESC_RING_COUNT);
438*4882a593Smuzhiyun writel(PLX_REG_PREF_LIMIT_PREF_FOUR, plxdev->bar + PLX_REG_PREF_LIMIT);
439*4882a593Smuzhiyun
440*4882a593Smuzhiyun plxdev->ring_active = true;
441*4882a593Smuzhiyun
442*4882a593Smuzhiyun rcu_read_unlock();
443*4882a593Smuzhiyun
444*4882a593Smuzhiyun return PLX_DMA_RING_COUNT;
445*4882a593Smuzhiyun
446*4882a593Smuzhiyun out_free_hw_ring:
447*4882a593Smuzhiyun dma_free_coherent(plxdev->dma_dev.dev, ring_sz, plxdev->hw_ring,
448*4882a593Smuzhiyun plxdev->hw_ring_dma);
449*4882a593Smuzhiyun return rc;
450*4882a593Smuzhiyun }
451*4882a593Smuzhiyun
plx_dma_free_chan_resources(struct dma_chan * chan)452*4882a593Smuzhiyun static void plx_dma_free_chan_resources(struct dma_chan *chan)
453*4882a593Smuzhiyun {
454*4882a593Smuzhiyun struct plx_dma_dev *plxdev = chan_to_plx_dma_dev(chan);
455*4882a593Smuzhiyun size_t ring_sz = PLX_DMA_RING_COUNT * sizeof(*plxdev->hw_ring);
456*4882a593Smuzhiyun struct pci_dev *pdev;
457*4882a593Smuzhiyun int irq = -1;
458*4882a593Smuzhiyun int i;
459*4882a593Smuzhiyun
460*4882a593Smuzhiyun spin_lock_bh(&plxdev->ring_lock);
461*4882a593Smuzhiyun plxdev->ring_active = false;
462*4882a593Smuzhiyun spin_unlock_bh(&plxdev->ring_lock);
463*4882a593Smuzhiyun
464*4882a593Smuzhiyun plx_dma_stop(plxdev);
465*4882a593Smuzhiyun
466*4882a593Smuzhiyun rcu_read_lock();
467*4882a593Smuzhiyun pdev = rcu_dereference(plxdev->pdev);
468*4882a593Smuzhiyun if (pdev)
469*4882a593Smuzhiyun irq = pci_irq_vector(pdev, 0);
470*4882a593Smuzhiyun rcu_read_unlock();
471*4882a593Smuzhiyun
472*4882a593Smuzhiyun if (irq > 0)
473*4882a593Smuzhiyun synchronize_irq(irq);
474*4882a593Smuzhiyun
475*4882a593Smuzhiyun tasklet_kill(&plxdev->desc_task);
476*4882a593Smuzhiyun
477*4882a593Smuzhiyun plx_dma_abort_desc(plxdev);
478*4882a593Smuzhiyun
479*4882a593Smuzhiyun for (i = 0; i < PLX_DMA_RING_COUNT; i++)
480*4882a593Smuzhiyun kfree(plxdev->desc_ring[i]);
481*4882a593Smuzhiyun
482*4882a593Smuzhiyun kfree(plxdev->desc_ring);
483*4882a593Smuzhiyun dma_free_coherent(plxdev->dma_dev.dev, ring_sz, plxdev->hw_ring,
484*4882a593Smuzhiyun plxdev->hw_ring_dma);
485*4882a593Smuzhiyun
486*4882a593Smuzhiyun }
487*4882a593Smuzhiyun
plx_dma_release(struct dma_device * dma_dev)488*4882a593Smuzhiyun static void plx_dma_release(struct dma_device *dma_dev)
489*4882a593Smuzhiyun {
490*4882a593Smuzhiyun struct plx_dma_dev *plxdev =
491*4882a593Smuzhiyun container_of(dma_dev, struct plx_dma_dev, dma_dev);
492*4882a593Smuzhiyun
493*4882a593Smuzhiyun put_device(dma_dev->dev);
494*4882a593Smuzhiyun kfree(plxdev);
495*4882a593Smuzhiyun }
496*4882a593Smuzhiyun
plx_dma_create(struct pci_dev * pdev)497*4882a593Smuzhiyun static int plx_dma_create(struct pci_dev *pdev)
498*4882a593Smuzhiyun {
499*4882a593Smuzhiyun struct plx_dma_dev *plxdev;
500*4882a593Smuzhiyun struct dma_device *dma;
501*4882a593Smuzhiyun struct dma_chan *chan;
502*4882a593Smuzhiyun int rc;
503*4882a593Smuzhiyun
504*4882a593Smuzhiyun plxdev = kzalloc(sizeof(*plxdev), GFP_KERNEL);
505*4882a593Smuzhiyun if (!plxdev)
506*4882a593Smuzhiyun return -ENOMEM;
507*4882a593Smuzhiyun
508*4882a593Smuzhiyun rc = request_irq(pci_irq_vector(pdev, 0), plx_dma_isr, 0,
509*4882a593Smuzhiyun KBUILD_MODNAME, plxdev);
510*4882a593Smuzhiyun if (rc)
511*4882a593Smuzhiyun goto free_plx;
512*4882a593Smuzhiyun
513*4882a593Smuzhiyun spin_lock_init(&plxdev->ring_lock);
514*4882a593Smuzhiyun tasklet_setup(&plxdev->desc_task, plx_dma_desc_task);
515*4882a593Smuzhiyun
516*4882a593Smuzhiyun RCU_INIT_POINTER(plxdev->pdev, pdev);
517*4882a593Smuzhiyun plxdev->bar = pcim_iomap_table(pdev)[0];
518*4882a593Smuzhiyun
519*4882a593Smuzhiyun dma = &plxdev->dma_dev;
520*4882a593Smuzhiyun dma->chancnt = 1;
521*4882a593Smuzhiyun INIT_LIST_HEAD(&dma->channels);
522*4882a593Smuzhiyun dma_cap_set(DMA_MEMCPY, dma->cap_mask);
523*4882a593Smuzhiyun dma->copy_align = DMAENGINE_ALIGN_1_BYTE;
524*4882a593Smuzhiyun dma->dev = get_device(&pdev->dev);
525*4882a593Smuzhiyun
526*4882a593Smuzhiyun dma->device_alloc_chan_resources = plx_dma_alloc_chan_resources;
527*4882a593Smuzhiyun dma->device_free_chan_resources = plx_dma_free_chan_resources;
528*4882a593Smuzhiyun dma->device_prep_dma_memcpy = plx_dma_prep_memcpy;
529*4882a593Smuzhiyun dma->device_issue_pending = plx_dma_issue_pending;
530*4882a593Smuzhiyun dma->device_tx_status = plx_dma_tx_status;
531*4882a593Smuzhiyun dma->device_release = plx_dma_release;
532*4882a593Smuzhiyun
533*4882a593Smuzhiyun chan = &plxdev->dma_chan;
534*4882a593Smuzhiyun chan->device = dma;
535*4882a593Smuzhiyun dma_cookie_init(chan);
536*4882a593Smuzhiyun list_add_tail(&chan->device_node, &dma->channels);
537*4882a593Smuzhiyun
538*4882a593Smuzhiyun rc = dma_async_device_register(dma);
539*4882a593Smuzhiyun if (rc) {
540*4882a593Smuzhiyun pci_err(pdev, "Failed to register dma device: %d\n", rc);
541*4882a593Smuzhiyun goto put_device;
542*4882a593Smuzhiyun }
543*4882a593Smuzhiyun
544*4882a593Smuzhiyun pci_set_drvdata(pdev, plxdev);
545*4882a593Smuzhiyun
546*4882a593Smuzhiyun return 0;
547*4882a593Smuzhiyun
548*4882a593Smuzhiyun put_device:
549*4882a593Smuzhiyun put_device(&pdev->dev);
550*4882a593Smuzhiyun free_irq(pci_irq_vector(pdev, 0), plxdev);
551*4882a593Smuzhiyun free_plx:
552*4882a593Smuzhiyun kfree(plxdev);
553*4882a593Smuzhiyun
554*4882a593Smuzhiyun return rc;
555*4882a593Smuzhiyun }
556*4882a593Smuzhiyun
plx_dma_probe(struct pci_dev * pdev,const struct pci_device_id * id)557*4882a593Smuzhiyun static int plx_dma_probe(struct pci_dev *pdev,
558*4882a593Smuzhiyun const struct pci_device_id *id)
559*4882a593Smuzhiyun {
560*4882a593Smuzhiyun int rc;
561*4882a593Smuzhiyun
562*4882a593Smuzhiyun rc = pcim_enable_device(pdev);
563*4882a593Smuzhiyun if (rc)
564*4882a593Smuzhiyun return rc;
565*4882a593Smuzhiyun
566*4882a593Smuzhiyun rc = pci_set_dma_mask(pdev, DMA_BIT_MASK(48));
567*4882a593Smuzhiyun if (rc)
568*4882a593Smuzhiyun rc = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
569*4882a593Smuzhiyun if (rc)
570*4882a593Smuzhiyun return rc;
571*4882a593Smuzhiyun
572*4882a593Smuzhiyun rc = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(48));
573*4882a593Smuzhiyun if (rc)
574*4882a593Smuzhiyun rc = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32));
575*4882a593Smuzhiyun if (rc)
576*4882a593Smuzhiyun return rc;
577*4882a593Smuzhiyun
578*4882a593Smuzhiyun rc = pcim_iomap_regions(pdev, 1, KBUILD_MODNAME);
579*4882a593Smuzhiyun if (rc)
580*4882a593Smuzhiyun return rc;
581*4882a593Smuzhiyun
582*4882a593Smuzhiyun rc = pci_alloc_irq_vectors(pdev, 1, 1, PCI_IRQ_ALL_TYPES);
583*4882a593Smuzhiyun if (rc <= 0)
584*4882a593Smuzhiyun return rc;
585*4882a593Smuzhiyun
586*4882a593Smuzhiyun pci_set_master(pdev);
587*4882a593Smuzhiyun
588*4882a593Smuzhiyun rc = plx_dma_create(pdev);
589*4882a593Smuzhiyun if (rc)
590*4882a593Smuzhiyun goto err_free_irq_vectors;
591*4882a593Smuzhiyun
592*4882a593Smuzhiyun pci_info(pdev, "PLX DMA Channel Registered\n");
593*4882a593Smuzhiyun
594*4882a593Smuzhiyun return 0;
595*4882a593Smuzhiyun
596*4882a593Smuzhiyun err_free_irq_vectors:
597*4882a593Smuzhiyun pci_free_irq_vectors(pdev);
598*4882a593Smuzhiyun return rc;
599*4882a593Smuzhiyun }
600*4882a593Smuzhiyun
plx_dma_remove(struct pci_dev * pdev)601*4882a593Smuzhiyun static void plx_dma_remove(struct pci_dev *pdev)
602*4882a593Smuzhiyun {
603*4882a593Smuzhiyun struct plx_dma_dev *plxdev = pci_get_drvdata(pdev);
604*4882a593Smuzhiyun
605*4882a593Smuzhiyun free_irq(pci_irq_vector(pdev, 0), plxdev);
606*4882a593Smuzhiyun
607*4882a593Smuzhiyun rcu_assign_pointer(plxdev->pdev, NULL);
608*4882a593Smuzhiyun synchronize_rcu();
609*4882a593Smuzhiyun
610*4882a593Smuzhiyun spin_lock_bh(&plxdev->ring_lock);
611*4882a593Smuzhiyun plxdev->ring_active = false;
612*4882a593Smuzhiyun spin_unlock_bh(&plxdev->ring_lock);
613*4882a593Smuzhiyun
614*4882a593Smuzhiyun __plx_dma_stop(plxdev);
615*4882a593Smuzhiyun plx_dma_abort_desc(plxdev);
616*4882a593Smuzhiyun
617*4882a593Smuzhiyun plxdev->bar = NULL;
618*4882a593Smuzhiyun dma_async_device_unregister(&plxdev->dma_dev);
619*4882a593Smuzhiyun
620*4882a593Smuzhiyun pci_free_irq_vectors(pdev);
621*4882a593Smuzhiyun }
622*4882a593Smuzhiyun
623*4882a593Smuzhiyun static const struct pci_device_id plx_dma_pci_tbl[] = {
624*4882a593Smuzhiyun {
625*4882a593Smuzhiyun .vendor = PCI_VENDOR_ID_PLX,
626*4882a593Smuzhiyun .device = 0x87D0,
627*4882a593Smuzhiyun .subvendor = PCI_ANY_ID,
628*4882a593Smuzhiyun .subdevice = PCI_ANY_ID,
629*4882a593Smuzhiyun .class = PCI_CLASS_SYSTEM_OTHER << 8,
630*4882a593Smuzhiyun .class_mask = 0xFFFFFFFF,
631*4882a593Smuzhiyun },
632*4882a593Smuzhiyun {0}
633*4882a593Smuzhiyun };
634*4882a593Smuzhiyun MODULE_DEVICE_TABLE(pci, plx_dma_pci_tbl);
635*4882a593Smuzhiyun
636*4882a593Smuzhiyun static struct pci_driver plx_dma_pci_driver = {
637*4882a593Smuzhiyun .name = KBUILD_MODNAME,
638*4882a593Smuzhiyun .id_table = plx_dma_pci_tbl,
639*4882a593Smuzhiyun .probe = plx_dma_probe,
640*4882a593Smuzhiyun .remove = plx_dma_remove,
641*4882a593Smuzhiyun };
642*4882a593Smuzhiyun module_pci_driver(plx_dma_pci_driver);
643