brintos

brintos / linux-shallow public Read only

0
0
Text · 11.1 KiB · a2f7b4c Raw
445 lines · c
1// SPDX-License-Identifier: ISC2/*3 * Copyright (c) 2012-2015,2017 Qualcomm Atheros, Inc.4 * Copyright (c) 2018, The Linux Foundation. All rights reserved.5 */6 7#include <linux/types.h>8#include <linux/errno.h>9#include <linux/fs.h>10#include <linux/seq_file.h>11#include "wmi.h"12#include "wil6210.h"13#include "txrx.h"14#include "pmc.h"15 16struct desc_alloc_info {17	dma_addr_t pa;18	void	  *va;19};20 21static int wil_is_pmc_allocated(struct pmc_ctx *pmc)22{23	return !!pmc->pring_va;24}25 26void wil_pmc_init(struct wil6210_priv *wil)27{28	memset(&wil->pmc, 0, sizeof(struct pmc_ctx));29	mutex_init(&wil->pmc.lock);30}31 32/* Allocate the physical ring (p-ring) and the required33 * number of descriptors of required size.34 * Initialize the descriptors as required by pmc dma.35 * The descriptors' buffers dwords are initialized to hold36 * dword's serial number in the lsw and reserved value37 * PCM_DATA_INVALID_DW_VAL in the msw.38 */39void wil_pmc_alloc(struct wil6210_priv *wil,40		   int num_descriptors,41		   int descriptor_size)42{43	u32 i;44	struct pmc_ctx *pmc = &wil->pmc;45	struct device *dev = wil_to_dev(wil);46	struct wil6210_vif *vif = ndev_to_vif(wil->main_ndev);47	struct wmi_pmc_cmd pmc_cmd = {0};48	int last_cmd_err = -ENOMEM;49 50	mutex_lock(&pmc->lock);51 52	if (wil_is_pmc_allocated(pmc)) {53		/* sanity check */54		wil_err(wil, "ERROR pmc is already allocated\n");55		goto no_release_err;56	}57	if ((num_descriptors <= 0) || (descriptor_size <= 0)) {58		wil_err(wil,59			"Invalid params num_descriptors(%d), descriptor_size(%d)\n",60			num_descriptors, descriptor_size);61		last_cmd_err = -EINVAL;62		goto no_release_err;63	}64 65	if (num_descriptors > (1 << WIL_RING_SIZE_ORDER_MAX)) {66		wil_err(wil,67			"num_descriptors(%d) exceeds max ring size %d\n",68			num_descriptors, 1 << WIL_RING_SIZE_ORDER_MAX);69		last_cmd_err = -EINVAL;70		goto no_release_err;71	}72 73	if (num_descriptors > INT_MAX / descriptor_size) {74		wil_err(wil,75			"Overflow in num_descriptors(%d)*descriptor_size(%d)\n",76			num_descriptors, descriptor_size);77		last_cmd_err = -EINVAL;78		goto no_release_err;79	}80 81	pmc->num_descriptors = num_descriptors;82	pmc->descriptor_size = descriptor_size;83 84	wil_dbg_misc(wil, "pmc_alloc: %d descriptors x %d bytes each\n",85		     num_descriptors, descriptor_size);86 87	/* allocate descriptors info list in pmc context*/88	pmc->descriptors = kcalloc(num_descriptors,89				  sizeof(struct desc_alloc_info),90				  GFP_KERNEL);91	if (!pmc->descriptors) {92		wil_err(wil, "ERROR allocating pmc skb list\n");93		goto no_release_err;94	}95 96	wil_dbg_misc(wil, "pmc_alloc: allocated descriptors info list %p\n",97		     pmc->descriptors);98 99	/* Allocate pring buffer and descriptors.100	 * vring->va should be aligned on its size rounded up to power of 2101	 * This is granted by the dma_alloc_coherent.102	 *103	 * HW has limitation that all vrings addresses must share the same104	 * upper 16 msb bits part of 48 bits address. To workaround that,105	 * if we are using more than 32 bit addresses switch to 32 bit106	 * allocation before allocating vring memory.107	 *108	 * There's no check for the return value of dma_set_mask_and_coherent,109	 * since we assume if we were able to set the mask during110	 * initialization in this system it will not fail if we set it again111	 */112	if (wil->dma_addr_size > 32)113		dma_set_mask_and_coherent(dev, DMA_BIT_MASK(32));114 115	pmc->pring_va = dma_alloc_coherent(dev,116			sizeof(struct vring_tx_desc) * num_descriptors,117			&pmc->pring_pa,118			GFP_KERNEL);119 120	if (wil->dma_addr_size > 32)121		dma_set_mask_and_coherent(dev,122					  DMA_BIT_MASK(wil->dma_addr_size));123 124	wil_dbg_misc(wil,125		     "pmc_alloc: allocated pring %p => %pad. %zd x %d = total %zd bytes\n",126		     pmc->pring_va, &pmc->pring_pa,127		     sizeof(struct vring_tx_desc),128		     num_descriptors,129		     sizeof(struct vring_tx_desc) * num_descriptors);130 131	if (!pmc->pring_va) {132		wil_err(wil, "ERROR allocating pmc pring\n");133		goto release_pmc_skb_list;134	}135 136	/* initially, all descriptors are SW owned137	 * For Tx, Rx, and PMC, ownership bit is at the same location, thus138	 * we can use any139	 */140	for (i = 0; i < num_descriptors; i++) {141		struct vring_tx_desc *_d = &pmc->pring_va[i];142		struct vring_tx_desc dd = {}, *d = &dd;143		int j = 0;144 145		pmc->descriptors[i].va = dma_alloc_coherent(dev,146			descriptor_size,147			&pmc->descriptors[i].pa,148			GFP_KERNEL);149 150		if (unlikely(!pmc->descriptors[i].va)) {151			wil_err(wil, "ERROR allocating pmc descriptor %d", i);152			goto release_pmc_skbs;153		}154 155		for (j = 0; j < descriptor_size / sizeof(u32); j++) {156			u32 *p = (u32 *)pmc->descriptors[i].va + j;157			*p = PCM_DATA_INVALID_DW_VAL | j;158		}159 160		/* configure dma descriptor */161		d->dma.addr.addr_low =162			cpu_to_le32(lower_32_bits(pmc->descriptors[i].pa));163		d->dma.addr.addr_high =164			cpu_to_le16((u16)upper_32_bits(pmc->descriptors[i].pa));165		d->dma.status = 0; /* 0 = HW_OWNED */166		d->dma.length = cpu_to_le16(descriptor_size);167		d->dma.d0 = BIT(9) | RX_DMA_D0_CMD_DMA_IT;168		*_d = *d;169	}170 171	wil_dbg_misc(wil, "pmc_alloc: allocated successfully\n");172 173	pmc_cmd.op = WMI_PMC_ALLOCATE;174	pmc_cmd.ring_size = cpu_to_le16(pmc->num_descriptors);175	pmc_cmd.mem_base = cpu_to_le64(pmc->pring_pa);176 177	wil_dbg_misc(wil, "pmc_alloc: send WMI_PMC_CMD with ALLOCATE op\n");178	pmc->last_cmd_status = wmi_send(wil,179					WMI_PMC_CMDID,180					vif->mid,181					&pmc_cmd,182					sizeof(pmc_cmd));183	if (pmc->last_cmd_status) {184		wil_err(wil,185			"WMI_PMC_CMD with ALLOCATE op failed with status %d",186			pmc->last_cmd_status);187		goto release_pmc_skbs;188	}189 190	mutex_unlock(&pmc->lock);191 192	return;193 194release_pmc_skbs:195	wil_err(wil, "exit on error: Releasing skbs...\n");196	for (i = 0; i < num_descriptors && pmc->descriptors[i].va; i++) {197		dma_free_coherent(dev,198				  descriptor_size,199				  pmc->descriptors[i].va,200				  pmc->descriptors[i].pa);201 202		pmc->descriptors[i].va = NULL;203	}204	wil_err(wil, "exit on error: Releasing pring...\n");205 206	dma_free_coherent(dev,207			  sizeof(struct vring_tx_desc) * num_descriptors,208			  pmc->pring_va,209			  pmc->pring_pa);210 211	pmc->pring_va = NULL;212 213release_pmc_skb_list:214	wil_err(wil, "exit on error: Releasing descriptors info list...\n");215	kfree(pmc->descriptors);216	pmc->descriptors = NULL;217 218no_release_err:219	pmc->last_cmd_status = last_cmd_err;220	mutex_unlock(&pmc->lock);221}222 223/* Traverse the p-ring and release all buffers.224 * At the end release the p-ring memory225 */226void wil_pmc_free(struct wil6210_priv *wil, int send_pmc_cmd)227{228	struct pmc_ctx *pmc = &wil->pmc;229	struct device *dev = wil_to_dev(wil);230	struct wil6210_vif *vif = ndev_to_vif(wil->main_ndev);231	struct wmi_pmc_cmd pmc_cmd = {0};232 233	mutex_lock(&pmc->lock);234 235	pmc->last_cmd_status = 0;236 237	if (!wil_is_pmc_allocated(pmc)) {238		wil_dbg_misc(wil,239			     "pmc_free: Error, can't free - not allocated\n");240		pmc->last_cmd_status = -EPERM;241		mutex_unlock(&pmc->lock);242		return;243	}244 245	if (send_pmc_cmd) {246		wil_dbg_misc(wil, "send WMI_PMC_CMD with RELEASE op\n");247		pmc_cmd.op = WMI_PMC_RELEASE;248		pmc->last_cmd_status =249				wmi_send(wil, WMI_PMC_CMDID, vif->mid,250					 &pmc_cmd, sizeof(pmc_cmd));251		if (pmc->last_cmd_status) {252			wil_err(wil,253				"WMI_PMC_CMD with RELEASE op failed, status %d",254				pmc->last_cmd_status);255			/* There's nothing we can do with this error.256			 * Normally, it should never occur.257			 * Continue to freeing all memory allocated for pmc.258			 */259		}260	}261 262	if (pmc->pring_va) {263		size_t buf_size = sizeof(struct vring_tx_desc) *264				  pmc->num_descriptors;265 266		wil_dbg_misc(wil, "pmc_free: free pring va %p\n",267			     pmc->pring_va);268		dma_free_coherent(dev, buf_size, pmc->pring_va, pmc->pring_pa);269 270		pmc->pring_va = NULL;271	} else {272		pmc->last_cmd_status = -ENOENT;273	}274 275	if (pmc->descriptors) {276		int i;277 278		for (i = 0;279		     i < pmc->num_descriptors && pmc->descriptors[i].va; i++) {280			dma_free_coherent(dev,281					  pmc->descriptor_size,282					  pmc->descriptors[i].va,283					  pmc->descriptors[i].pa);284			pmc->descriptors[i].va = NULL;285		}286		wil_dbg_misc(wil, "pmc_free: free descriptor info %d/%d\n", i,287			     pmc->num_descriptors);288		wil_dbg_misc(wil,289			     "pmc_free: free pmc descriptors info list %p\n",290			     pmc->descriptors);291		kfree(pmc->descriptors);292		pmc->descriptors = NULL;293	} else {294		pmc->last_cmd_status = -ENOENT;295	}296 297	mutex_unlock(&pmc->lock);298}299 300/* Status of the last operation requested via debugfs: alloc/free/read.301 * 0 - success or negative errno302 */303int wil_pmc_last_cmd_status(struct wil6210_priv *wil)304{305	wil_dbg_misc(wil, "pmc_last_cmd_status: status %d\n",306		     wil->pmc.last_cmd_status);307 308	return wil->pmc.last_cmd_status;309}310 311/* Read from required position up to the end of current descriptor,312 * depends on descriptor size configured during alloc request.313 */314ssize_t wil_pmc_read(struct file *filp, char __user *buf, size_t count,315		     loff_t *f_pos)316{317	struct wil6210_priv *wil = filp->private_data;318	struct pmc_ctx *pmc = &wil->pmc;319	size_t retval = 0;320	unsigned long long idx;321	loff_t offset;322	size_t pmc_size;323 324	mutex_lock(&pmc->lock);325 326	if (!wil_is_pmc_allocated(pmc)) {327		wil_err(wil, "error, pmc is not allocated!\n");328		pmc->last_cmd_status = -EPERM;329		mutex_unlock(&pmc->lock);330		return -EPERM;331	}332 333	pmc_size = pmc->descriptor_size * pmc->num_descriptors;334 335	wil_dbg_misc(wil,336		     "pmc_read: size %u, pos %lld\n",337		     (u32)count, *f_pos);338 339	pmc->last_cmd_status = 0;340 341	idx = *f_pos;342	do_div(idx, pmc->descriptor_size);343	offset = *f_pos - (idx * pmc->descriptor_size);344 345	if (*f_pos >= pmc_size) {346		wil_dbg_misc(wil,347			     "pmc_read: reached end of pmc buf: %lld >= %u\n",348			     *f_pos, (u32)pmc_size);349		pmc->last_cmd_status = -ERANGE;350		goto out;351	}352 353	wil_dbg_misc(wil,354		     "pmc_read: read from pos %lld (descriptor %llu, offset %llu) %zu bytes\n",355		     *f_pos, idx, offset, count);356 357	/* if no errors, return the copied byte count */358	retval = simple_read_from_buffer(buf,359					 count,360					 &offset,361					 pmc->descriptors[idx].va,362					 pmc->descriptor_size);363	*f_pos += retval;364out:365	mutex_unlock(&pmc->lock);366 367	return retval;368}369 370loff_t wil_pmc_llseek(struct file *filp, loff_t off, int whence)371{372	loff_t newpos;373	struct wil6210_priv *wil = filp->private_data;374	struct pmc_ctx *pmc = &wil->pmc;375	size_t pmc_size;376 377	mutex_lock(&pmc->lock);378 379	if (!wil_is_pmc_allocated(pmc)) {380		wil_err(wil, "error, pmc is not allocated!\n");381		pmc->last_cmd_status = -EPERM;382		mutex_unlock(&pmc->lock);383		return -EPERM;384	}385 386	pmc_size = pmc->descriptor_size * pmc->num_descriptors;387 388	switch (whence) {389	case 0: /* SEEK_SET */390		newpos = off;391		break;392 393	case 1: /* SEEK_CUR */394		newpos = filp->f_pos + off;395		break;396 397	case 2: /* SEEK_END */398		newpos = pmc_size;399		break;400 401	default: /* can't happen */402		newpos = -EINVAL;403		goto out;404	}405 406	if (newpos < 0) {407		newpos = -EINVAL;408		goto out;409	}410	if (newpos > pmc_size)411		newpos = pmc_size;412 413	filp->f_pos = newpos;414 415out:416	mutex_unlock(&pmc->lock);417 418	return newpos;419}420 421int wil_pmcring_read(struct seq_file *s, void *data)422{423	struct wil6210_priv *wil = s->private;424	struct pmc_ctx *pmc = &wil->pmc;425	size_t pmc_ring_size =426		sizeof(struct vring_rx_desc) * pmc->num_descriptors;427 428	mutex_lock(&pmc->lock);429 430	if (!wil_is_pmc_allocated(pmc)) {431		wil_err(wil, "error, pmc is not allocated!\n");432		pmc->last_cmd_status = -EPERM;433		mutex_unlock(&pmc->lock);434		return -EPERM;435	}436 437	wil_dbg_misc(wil, "pmcring_read: size %zu\n", pmc_ring_size);438 439	seq_write(s, pmc->pring_va, pmc_ring_size);440 441	mutex_unlock(&pmc->lock);442 443	return 0;444}445