brintos

brintos / linux-shallow public Read only

0
0
Text · 5.2 KiB · 426b901 Raw
235 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*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 <linux/slab.h>12#include "vnic_dev.h"13#include "vnic_wq.h"14 15 16static int vnic_wq_get_ctrl(struct vnic_dev *vdev, struct vnic_wq *wq,17		unsigned int index, enum vnic_res_type res_type)18{19	wq->ctrl = vnic_dev_get_res(vdev, res_type, index);20 21	if (!wq->ctrl)22		return -EINVAL;23 24	return 0;25}26 27 28static int vnic_wq_alloc_ring(struct vnic_dev *vdev, struct vnic_wq *wq,29		unsigned int desc_count, unsigned int desc_size)30{31	return vnic_dev_alloc_desc_ring(vdev, &wq->ring, desc_count, desc_size);32}33 34 35static int vnic_wq_alloc_bufs(struct vnic_wq *wq)36{37	struct vnic_wq_buf *buf;38	unsigned int i, j, count = wq->ring.desc_count;39	unsigned int blks = VNIC_WQ_BUF_BLKS_NEEDED(count);40 41	for (i = 0; i < blks; i++) {42		wq->bufs[i] = kzalloc(VNIC_WQ_BUF_BLK_SZ, GFP_ATOMIC);43		if (!wq->bufs[i]) {44			printk(KERN_ERR "Failed to alloc wq_bufs\n");45			return -ENOMEM;46		}47	}48 49	for (i = 0; i < blks; i++) {50		buf = wq->bufs[i];51		for (j = 0; j < VNIC_WQ_BUF_BLK_ENTRIES; j++) {52			buf->index = i * VNIC_WQ_BUF_BLK_ENTRIES + j;53			buf->desc = (u8 *)wq->ring.descs +54				wq->ring.desc_size * buf->index;55			if (buf->index + 1 == count) {56				buf->next = wq->bufs[0];57				break;58			} else if (j + 1 == VNIC_WQ_BUF_BLK_ENTRIES) {59				buf->next = wq->bufs[i + 1];60			} else {61				buf->next = buf + 1;62				buf++;63			}64		}65	}66 67	wq->to_use = wq->to_clean = wq->bufs[0];68 69	return 0;70}71 72void vnic_wq_free(struct vnic_wq *wq)73{74	struct vnic_dev *vdev;75	unsigned int i;76 77	vdev = wq->vdev;78 79	vnic_dev_free_desc_ring(vdev, &wq->ring);80 81	for (i = 0; i < VNIC_WQ_BUF_BLKS_MAX; i++) {82		kfree(wq->bufs[i]);83		wq->bufs[i] = NULL;84	}85 86	wq->ctrl = NULL;87 88}89 90int vnic_wq_alloc(struct vnic_dev *vdev, struct vnic_wq *wq, unsigned int index,91	unsigned int desc_count, unsigned int desc_size)92{93	int err;94 95	wq->index = index;96	wq->vdev = vdev;97 98	wq->ctrl = vnic_dev_get_res(vdev, RES_TYPE_WQ, index);99	if (!wq->ctrl) {100		printk(KERN_ERR "Failed to hook WQ[%d] resource\n", index);101		return -EINVAL;102	}103 104	vnic_wq_disable(wq);105 106	err = vnic_dev_alloc_desc_ring(vdev, &wq->ring, desc_count, desc_size);107	if (err)108		return err;109 110	err = vnic_wq_alloc_bufs(wq);111	if (err) {112		vnic_wq_free(wq);113		return err;114	}115 116	return 0;117}118 119 120int vnic_wq_devcmd2_alloc(struct vnic_dev *vdev, struct vnic_wq *wq,121		unsigned int desc_count, unsigned int desc_size)122{123	int err;124 125	wq->index = 0;126	wq->vdev = vdev;127 128	err = vnic_wq_get_ctrl(vdev, wq, 0, RES_TYPE_DEVCMD2);129	if (err) {130		pr_err("Failed to get devcmd2 resource\n");131		return err;132	}133	vnic_wq_disable(wq);134 135	err = vnic_wq_alloc_ring(vdev, wq, desc_count, desc_size);136	if (err)137		return err;138	return 0;139}140 141void vnic_wq_init_start(struct vnic_wq *wq, unsigned int cq_index,142		unsigned int fetch_index, unsigned int posted_index,143		unsigned int error_interrupt_enable,144		unsigned int error_interrupt_offset)145{146	u64 paddr;147	unsigned int count = wq->ring.desc_count;148 149	paddr = (u64)wq->ring.base_addr | VNIC_PADDR_TARGET;150	writeq(paddr, &wq->ctrl->ring_base);151	iowrite32(count, &wq->ctrl->ring_size);152	iowrite32(fetch_index, &wq->ctrl->fetch_index);153	iowrite32(posted_index, &wq->ctrl->posted_index);154	iowrite32(cq_index, &wq->ctrl->cq_index);155	iowrite32(error_interrupt_enable, &wq->ctrl->error_interrupt_enable);156	iowrite32(error_interrupt_offset, &wq->ctrl->error_interrupt_offset);157	iowrite32(0, &wq->ctrl->error_status);158 159	wq->to_use = wq->to_clean =160		&wq->bufs[fetch_index / VNIC_WQ_BUF_BLK_ENTRIES]161		[fetch_index % VNIC_WQ_BUF_BLK_ENTRIES];162}163 164 165void vnic_wq_init(struct vnic_wq *wq, unsigned int cq_index,166	unsigned int error_interrupt_enable,167	unsigned int error_interrupt_offset)168{169	u64 paddr;170 171	paddr = (u64)wq->ring.base_addr | VNIC_PADDR_TARGET;172	writeq(paddr, &wq->ctrl->ring_base);173	iowrite32(wq->ring.desc_count, &wq->ctrl->ring_size);174	iowrite32(0, &wq->ctrl->fetch_index);175	iowrite32(0, &wq->ctrl->posted_index);176	iowrite32(cq_index, &wq->ctrl->cq_index);177	iowrite32(error_interrupt_enable, &wq->ctrl->error_interrupt_enable);178	iowrite32(error_interrupt_offset, &wq->ctrl->error_interrupt_offset);179	iowrite32(0, &wq->ctrl->error_status);180}181 182unsigned int vnic_wq_error_status(struct vnic_wq *wq)183{184	return ioread32(&wq->ctrl->error_status);185}186 187void vnic_wq_enable(struct vnic_wq *wq)188{189	iowrite32(1, &wq->ctrl->enable);190}191 192int vnic_wq_disable(struct vnic_wq *wq)193{194	unsigned int wait;195 196	iowrite32(0, &wq->ctrl->enable);197 198	/* Wait for HW to ACK disable request */199	for (wait = 0; wait < 100; wait++) {200		if (!(ioread32(&wq->ctrl->running)))201			return 0;202		udelay(1);203	}204 205	printk(KERN_ERR "Failed to disable WQ[%d]\n", wq->index);206 207	return -ETIMEDOUT;208}209 210void vnic_wq_clean(struct vnic_wq *wq,211	void (*buf_clean)(struct vnic_wq *wq, struct vnic_wq_buf *buf))212{213	struct vnic_wq_buf *buf;214 215	BUG_ON(ioread32(&wq->ctrl->enable));216 217	buf = wq->to_clean;218 219	while (vnic_wq_desc_used(wq) > 0) {220 221		(*buf_clean)(wq, buf);222 223		buf = wq->to_clean = buf->next;224		wq->ring.desc_avail++;225	}226 227	wq->to_use = wq->to_clean = wq->bufs[0];228 229	iowrite32(0, &wq->ctrl->fetch_index);230	iowrite32(0, &wq->ctrl->posted_index);231	iowrite32(0, &wq->ctrl->error_status);232 233	vnic_dev_clear_desc_ring(&wq->ring);234}235