18c2ecf20Sopenharmony_ci/*
28c2ecf20Sopenharmony_ci * Copyright 2008 Cisco Systems, Inc.  All rights reserved.
38c2ecf20Sopenharmony_ci * Copyright 2007 Nuova Systems, Inc.  All rights reserved.
48c2ecf20Sopenharmony_ci *
58c2ecf20Sopenharmony_ci * This program is free software; you may redistribute it and/or modify
68c2ecf20Sopenharmony_ci * it under the terms of the GNU General Public License as published by
78c2ecf20Sopenharmony_ci * the Free Software Foundation; version 2 of the License.
88c2ecf20Sopenharmony_ci *
98c2ecf20Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
108c2ecf20Sopenharmony_ci * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
118c2ecf20Sopenharmony_ci * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
128c2ecf20Sopenharmony_ci * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
138c2ecf20Sopenharmony_ci * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
148c2ecf20Sopenharmony_ci * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
158c2ecf20Sopenharmony_ci * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
168c2ecf20Sopenharmony_ci * SOFTWARE.
178c2ecf20Sopenharmony_ci */
188c2ecf20Sopenharmony_ci
198c2ecf20Sopenharmony_ci#include <linux/errno.h>
208c2ecf20Sopenharmony_ci#include <linux/types.h>
218c2ecf20Sopenharmony_ci#include <linux/pci.h>
228c2ecf20Sopenharmony_ci#include <linux/delay.h>
238c2ecf20Sopenharmony_ci#include "vnic_wq_copy.h"
248c2ecf20Sopenharmony_ci
258c2ecf20Sopenharmony_civoid vnic_wq_copy_enable(struct vnic_wq_copy *wq)
268c2ecf20Sopenharmony_ci{
278c2ecf20Sopenharmony_ci	iowrite32(1, &wq->ctrl->enable);
288c2ecf20Sopenharmony_ci}
298c2ecf20Sopenharmony_ci
308c2ecf20Sopenharmony_ciint vnic_wq_copy_disable(struct vnic_wq_copy *wq)
318c2ecf20Sopenharmony_ci{
328c2ecf20Sopenharmony_ci	unsigned int wait;
338c2ecf20Sopenharmony_ci
348c2ecf20Sopenharmony_ci	iowrite32(0, &wq->ctrl->enable);
358c2ecf20Sopenharmony_ci
368c2ecf20Sopenharmony_ci	/* Wait for HW to ACK disable request */
378c2ecf20Sopenharmony_ci	for (wait = 0; wait < 100; wait++) {
388c2ecf20Sopenharmony_ci		if (!(ioread32(&wq->ctrl->running)))
398c2ecf20Sopenharmony_ci			return 0;
408c2ecf20Sopenharmony_ci		udelay(1);
418c2ecf20Sopenharmony_ci	}
428c2ecf20Sopenharmony_ci
438c2ecf20Sopenharmony_ci	printk(KERN_ERR "Failed to disable Copy WQ[%d],"
448c2ecf20Sopenharmony_ci	       " fetch index=%d, posted_index=%d\n",
458c2ecf20Sopenharmony_ci	       wq->index, ioread32(&wq->ctrl->fetch_index),
468c2ecf20Sopenharmony_ci	       ioread32(&wq->ctrl->posted_index));
478c2ecf20Sopenharmony_ci
488c2ecf20Sopenharmony_ci	return -ENODEV;
498c2ecf20Sopenharmony_ci}
508c2ecf20Sopenharmony_ci
518c2ecf20Sopenharmony_civoid vnic_wq_copy_clean(struct vnic_wq_copy *wq,
528c2ecf20Sopenharmony_ci	void (*q_clean)(struct vnic_wq_copy *wq,
538c2ecf20Sopenharmony_ci	struct fcpio_host_req *wq_desc))
548c2ecf20Sopenharmony_ci{
558c2ecf20Sopenharmony_ci	BUG_ON(ioread32(&wq->ctrl->enable));
568c2ecf20Sopenharmony_ci
578c2ecf20Sopenharmony_ci	if (vnic_wq_copy_desc_in_use(wq))
588c2ecf20Sopenharmony_ci		vnic_wq_copy_service(wq, -1, q_clean);
598c2ecf20Sopenharmony_ci
608c2ecf20Sopenharmony_ci	wq->to_use_index = wq->to_clean_index = 0;
618c2ecf20Sopenharmony_ci
628c2ecf20Sopenharmony_ci	iowrite32(0, &wq->ctrl->fetch_index);
638c2ecf20Sopenharmony_ci	iowrite32(0, &wq->ctrl->posted_index);
648c2ecf20Sopenharmony_ci	iowrite32(0, &wq->ctrl->error_status);
658c2ecf20Sopenharmony_ci
668c2ecf20Sopenharmony_ci	vnic_dev_clear_desc_ring(&wq->ring);
678c2ecf20Sopenharmony_ci}
688c2ecf20Sopenharmony_ci
698c2ecf20Sopenharmony_civoid vnic_wq_copy_free(struct vnic_wq_copy *wq)
708c2ecf20Sopenharmony_ci{
718c2ecf20Sopenharmony_ci	struct vnic_dev *vdev;
728c2ecf20Sopenharmony_ci
738c2ecf20Sopenharmony_ci	vdev = wq->vdev;
748c2ecf20Sopenharmony_ci	vnic_dev_free_desc_ring(vdev, &wq->ring);
758c2ecf20Sopenharmony_ci	wq->ctrl = NULL;
768c2ecf20Sopenharmony_ci}
778c2ecf20Sopenharmony_ci
788c2ecf20Sopenharmony_ciint vnic_wq_copy_alloc(struct vnic_dev *vdev, struct vnic_wq_copy *wq,
798c2ecf20Sopenharmony_ci		       unsigned int index, unsigned int desc_count,
808c2ecf20Sopenharmony_ci		       unsigned int desc_size)
818c2ecf20Sopenharmony_ci{
828c2ecf20Sopenharmony_ci	wq->index = index;
838c2ecf20Sopenharmony_ci	wq->vdev = vdev;
848c2ecf20Sopenharmony_ci	wq->to_use_index = wq->to_clean_index = 0;
858c2ecf20Sopenharmony_ci	wq->ctrl = vnic_dev_get_res(vdev, RES_TYPE_WQ, index);
868c2ecf20Sopenharmony_ci	if (!wq->ctrl) {
878c2ecf20Sopenharmony_ci		printk(KERN_ERR "Failed to hook COPY WQ[%d] resource\n", index);
888c2ecf20Sopenharmony_ci		return -EINVAL;
898c2ecf20Sopenharmony_ci	}
908c2ecf20Sopenharmony_ci
918c2ecf20Sopenharmony_ci	vnic_wq_copy_disable(wq);
928c2ecf20Sopenharmony_ci
938c2ecf20Sopenharmony_ci	return vnic_dev_alloc_desc_ring(vdev, &wq->ring, desc_count, desc_size);
948c2ecf20Sopenharmony_ci}
958c2ecf20Sopenharmony_ci
968c2ecf20Sopenharmony_civoid vnic_wq_copy_init(struct vnic_wq_copy *wq, unsigned int cq_index,
978c2ecf20Sopenharmony_ci	unsigned int error_interrupt_enable,
988c2ecf20Sopenharmony_ci	unsigned int error_interrupt_offset)
998c2ecf20Sopenharmony_ci{
1008c2ecf20Sopenharmony_ci	u64 paddr;
1018c2ecf20Sopenharmony_ci
1028c2ecf20Sopenharmony_ci	paddr = (u64)wq->ring.base_addr | VNIC_PADDR_TARGET;
1038c2ecf20Sopenharmony_ci	writeq(paddr, &wq->ctrl->ring_base);
1048c2ecf20Sopenharmony_ci	iowrite32(wq->ring.desc_count, &wq->ctrl->ring_size);
1058c2ecf20Sopenharmony_ci	iowrite32(0, &wq->ctrl->fetch_index);
1068c2ecf20Sopenharmony_ci	iowrite32(0, &wq->ctrl->posted_index);
1078c2ecf20Sopenharmony_ci	iowrite32(cq_index, &wq->ctrl->cq_index);
1088c2ecf20Sopenharmony_ci	iowrite32(error_interrupt_enable, &wq->ctrl->error_interrupt_enable);
1098c2ecf20Sopenharmony_ci	iowrite32(error_interrupt_offset, &wq->ctrl->error_interrupt_offset);
1108c2ecf20Sopenharmony_ci}
1118c2ecf20Sopenharmony_ci
112