1 | // SPDX-License-Identifier: GPL-2.0-only |
2 | /* |
3 | * Copyright 2008 Cisco Systems, Inc. All rights reserved. |
4 | * Copyright 2007 Nuova Systems, Inc. All rights reserved. |
5 | */ |
6 | |
7 | #include <linux/errno.h> |
8 | #include <linux/types.h> |
9 | #include <linux/pci.h> |
10 | #include <linux/delay.h> |
11 | #include "vnic_wq_copy.h" |
12 | |
13 | void vnic_wq_copy_enable(struct vnic_wq_copy *wq) |
14 | { |
15 | iowrite32(1, &wq->ctrl->enable); |
16 | } |
17 | |
18 | int vnic_wq_copy_disable(struct vnic_wq_copy *wq) |
19 | { |
20 | unsigned int wait; |
21 | |
22 | iowrite32(0, &wq->ctrl->enable); |
23 | |
24 | /* Wait for HW to ACK disable request */ |
25 | for (wait = 0; wait < 100; wait++) { |
26 | if (!(ioread32(&wq->ctrl->running))) |
27 | return 0; |
28 | udelay(1); |
29 | } |
30 | |
31 | printk(KERN_ERR "Failed to disable Copy WQ[%d]," |
32 | " fetch index=%d, posted_index=%d\n" , |
33 | wq->index, ioread32(&wq->ctrl->fetch_index), |
34 | ioread32(&wq->ctrl->posted_index)); |
35 | |
36 | return -ENODEV; |
37 | } |
38 | |
39 | void vnic_wq_copy_clean(struct vnic_wq_copy *wq, |
40 | void (*q_clean)(struct vnic_wq_copy *wq, |
41 | struct fcpio_host_req *wq_desc)) |
42 | { |
43 | BUG_ON(ioread32(&wq->ctrl->enable)); |
44 | |
45 | if (vnic_wq_copy_desc_in_use(wq)) |
46 | vnic_wq_copy_service(wq, completed_index: -1, q_service: q_clean); |
47 | |
48 | wq->to_use_index = wq->to_clean_index = 0; |
49 | |
50 | iowrite32(0, &wq->ctrl->fetch_index); |
51 | iowrite32(0, &wq->ctrl->posted_index); |
52 | iowrite32(0, &wq->ctrl->error_status); |
53 | |
54 | vnic_dev_clear_desc_ring(ring: &wq->ring); |
55 | } |
56 | |
57 | void vnic_wq_copy_free(struct vnic_wq_copy *wq) |
58 | { |
59 | struct vnic_dev *vdev; |
60 | |
61 | vdev = wq->vdev; |
62 | vnic_dev_free_desc_ring(vdev, ring: &wq->ring); |
63 | wq->ctrl = NULL; |
64 | } |
65 | |
66 | int vnic_wq_copy_alloc(struct vnic_dev *vdev, struct vnic_wq_copy *wq, |
67 | unsigned int index, unsigned int desc_count, |
68 | unsigned int desc_size) |
69 | { |
70 | wq->index = index; |
71 | wq->vdev = vdev; |
72 | wq->to_use_index = wq->to_clean_index = 0; |
73 | wq->ctrl = vnic_dev_get_res(vdev, type: RES_TYPE_WQ, index); |
74 | if (!wq->ctrl) { |
75 | printk(KERN_ERR "Failed to hook COPY WQ[%d] resource\n" , index); |
76 | return -EINVAL; |
77 | } |
78 | |
79 | vnic_wq_copy_disable(wq); |
80 | |
81 | return vnic_dev_alloc_desc_ring(vdev, ring: &wq->ring, desc_count, desc_size); |
82 | } |
83 | |
84 | void vnic_wq_copy_init(struct vnic_wq_copy *wq, unsigned int cq_index, |
85 | unsigned int error_interrupt_enable, |
86 | unsigned int error_interrupt_offset) |
87 | { |
88 | u64 paddr; |
89 | |
90 | paddr = (u64)wq->ring.base_addr | VNIC_PADDR_TARGET; |
91 | writeq(val: paddr, addr: &wq->ctrl->ring_base); |
92 | iowrite32(wq->ring.desc_count, &wq->ctrl->ring_size); |
93 | iowrite32(0, &wq->ctrl->fetch_index); |
94 | iowrite32(0, &wq->ctrl->posted_index); |
95 | iowrite32(cq_index, &wq->ctrl->cq_index); |
96 | iowrite32(error_interrupt_enable, &wq->ctrl->error_interrupt_enable); |
97 | iowrite32(error_interrupt_offset, &wq->ctrl->error_interrupt_offset); |
98 | } |
99 | |