^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-or-later
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * VME Bridge Framework
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Author: Martyn Welch <martyn.welch@ge.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * Copyright 2008 GE Intelligent Platforms Embedded Systems, Inc.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * Based on work by Tom Armistead and Ajit Prem
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * Copyright 2004 Motorola Inc.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/export.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/mm.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/types.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <linux/errno.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <linux/pci.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <linux/poll.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <linux/highmem.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include <linux/interrupt.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include <linux/pagemap.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include <linux/device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #include <linux/dma-mapping.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #include <linux/syscalls.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #include <linux/mutex.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #include <linux/spinlock.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #include <linux/vme.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) #include "vme_bridge.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) /* Bitmask and list of registered buses both protected by common mutex */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) static unsigned int vme_bus_numbers;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) static LIST_HEAD(vme_bus_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) static DEFINE_MUTEX(vme_buses_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) static int __init vme_init(void);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) static struct vme_dev *dev_to_vme_dev(struct device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) return container_of(dev, struct vme_dev, dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) * Find the bridge that the resource is associated with.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) static struct vme_bridge *find_bridge(struct vme_resource *resource)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) /* Get list to search */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) switch (resource->type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) case VME_MASTER:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) return list_entry(resource->entry, struct vme_master_resource,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) list)->parent;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) case VME_SLAVE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) return list_entry(resource->entry, struct vme_slave_resource,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) list)->parent;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) case VME_DMA:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) return list_entry(resource->entry, struct vme_dma_resource,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) list)->parent;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) case VME_LM:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) return list_entry(resource->entry, struct vme_lm_resource,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) list)->parent;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) printk(KERN_ERR "Unknown resource type\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) * vme_free_consistent - Allocate contiguous memory.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) * @resource: Pointer to VME resource.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) * @size: Size of allocation required.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) * @dma: Pointer to variable to store physical address of allocation.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) * Allocate a contiguous block of memory for use by the driver. This is used to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) * create the buffers for the slave windows.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) * Return: Virtual address of allocation on success, NULL on failure.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) void *vme_alloc_consistent(struct vme_resource *resource, size_t size,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) dma_addr_t *dma)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) struct vme_bridge *bridge;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) if (!resource) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) printk(KERN_ERR "No resource\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) bridge = find_bridge(resource);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) if (!bridge) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) printk(KERN_ERR "Can't find bridge\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) if (!bridge->parent) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) printk(KERN_ERR "Dev entry NULL for bridge %s\n", bridge->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) if (!bridge->alloc_consistent) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) printk(KERN_ERR "alloc_consistent not supported by bridge %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) bridge->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) return bridge->alloc_consistent(bridge->parent, size, dma);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) EXPORT_SYMBOL(vme_alloc_consistent);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) * vme_free_consistent - Free previously allocated memory.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) * @resource: Pointer to VME resource.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) * @size: Size of allocation to free.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) * @vaddr: Virtual address of allocation.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) * @dma: Physical address of allocation.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) * Free previously allocated block of contiguous memory.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) void vme_free_consistent(struct vme_resource *resource, size_t size,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) void *vaddr, dma_addr_t dma)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) struct vme_bridge *bridge;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) if (!resource) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) printk(KERN_ERR "No resource\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) bridge = find_bridge(resource);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) if (!bridge) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) printk(KERN_ERR "Can't find bridge\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) if (!bridge->parent) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) printk(KERN_ERR "Dev entry NULL for bridge %s\n", bridge->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) if (!bridge->free_consistent) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) printk(KERN_ERR "free_consistent not supported by bridge %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) bridge->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) bridge->free_consistent(bridge->parent, size, vaddr, dma);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) EXPORT_SYMBOL(vme_free_consistent);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) * vme_get_size - Helper function returning size of a VME window
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) * @resource: Pointer to VME slave or master resource.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) * Determine the size of the VME window provided. This is a helper
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) * function, wrappering the call to vme_master_get or vme_slave_get
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) * depending on the type of window resource handed to it.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) * Return: Size of the window on success, zero on failure.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) size_t vme_get_size(struct vme_resource *resource)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) int enabled, retval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) unsigned long long base, size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) dma_addr_t buf_base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) u32 aspace, cycle, dwidth;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) switch (resource->type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) case VME_MASTER:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) retval = vme_master_get(resource, &enabled, &base, &size,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) &aspace, &cycle, &dwidth);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) if (retval)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) return size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) case VME_SLAVE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) retval = vme_slave_get(resource, &enabled, &base, &size,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) &buf_base, &aspace, &cycle);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) if (retval)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) return size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) case VME_DMA:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) printk(KERN_ERR "Unknown resource type\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) EXPORT_SYMBOL(vme_get_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) int vme_check_window(u32 aspace, unsigned long long vme_base,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) unsigned long long size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) int retval = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) if (vme_base + size < size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) switch (aspace) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) case VME_A16:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) if (vme_base + size > VME_A16_MAX)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) retval = -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) case VME_A24:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) if (vme_base + size > VME_A24_MAX)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) retval = -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) case VME_A32:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) if (vme_base + size > VME_A32_MAX)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) retval = -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) case VME_A64:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) /* The VME_A64_MAX limit is actually U64_MAX + 1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) case VME_CRCSR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) if (vme_base + size > VME_CRCSR_MAX)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) retval = -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) case VME_USER1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) case VME_USER2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) case VME_USER3:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) case VME_USER4:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) /* User Defined */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) printk(KERN_ERR "Invalid address space\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) retval = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) return retval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) EXPORT_SYMBOL(vme_check_window);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) static u32 vme_get_aspace(int am)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) switch (am) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) case 0x29:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) case 0x2D:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) return VME_A16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) case 0x38:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) case 0x39:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) case 0x3A:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) case 0x3B:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) case 0x3C:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) case 0x3D:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) case 0x3E:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) case 0x3F:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) return VME_A24;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) case 0x8:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) case 0x9:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) case 0xA:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) case 0xB:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) case 0xC:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) case 0xD:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) case 0xE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) case 0xF:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) return VME_A32;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) case 0x0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) case 0x1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) case 0x3:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) return VME_A64;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) * vme_slave_request - Request a VME slave window resource.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) * @vdev: Pointer to VME device struct vme_dev assigned to driver instance.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) * @address: Required VME address space.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) * @cycle: Required VME data transfer cycle type.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) * Request use of a VME window resource capable of being set for the requested
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) * address space and data transfer cycle.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) * Return: Pointer to VME resource on success, NULL on failure.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) struct vme_resource *vme_slave_request(struct vme_dev *vdev, u32 address,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) u32 cycle)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) struct vme_bridge *bridge;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) struct list_head *slave_pos = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) struct vme_slave_resource *allocated_image = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) struct vme_slave_resource *slave_image = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) struct vme_resource *resource = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) bridge = vdev->bridge;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) if (!bridge) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) printk(KERN_ERR "Can't find VME bus\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) goto err_bus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) /* Loop through slave resources */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) list_for_each(slave_pos, &bridge->slave_resources) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) slave_image = list_entry(slave_pos,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) struct vme_slave_resource, list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) if (!slave_image) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) printk(KERN_ERR "Registered NULL Slave resource\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) /* Find an unlocked and compatible image */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) mutex_lock(&slave_image->mtx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) if (((slave_image->address_attr & address) == address) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) ((slave_image->cycle_attr & cycle) == cycle) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) (slave_image->locked == 0)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) slave_image->locked = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) mutex_unlock(&slave_image->mtx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) allocated_image = slave_image;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) mutex_unlock(&slave_image->mtx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) /* No free image */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) if (!allocated_image)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) goto err_image;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) resource = kmalloc(sizeof(*resource), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) if (!resource)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) goto err_alloc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) resource->type = VME_SLAVE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) resource->entry = &allocated_image->list;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) return resource;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) err_alloc:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) /* Unlock image */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) mutex_lock(&slave_image->mtx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) slave_image->locked = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) mutex_unlock(&slave_image->mtx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) err_image:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) err_bus:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) EXPORT_SYMBOL(vme_slave_request);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) * vme_slave_set - Set VME slave window configuration.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) * @resource: Pointer to VME slave resource.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) * @enabled: State to which the window should be configured.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) * @vme_base: Base address for the window.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) * @size: Size of the VME window.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) * @buf_base: Based address of buffer used to provide VME slave window storage.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) * @aspace: VME address space for the VME window.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) * @cycle: VME data transfer cycle type for the VME window.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) * Set configuration for provided VME slave window.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) * Return: Zero on success, -EINVAL if operation is not supported on this
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) * device, if an invalid resource has been provided or invalid
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) * attributes are provided. Hardware specific errors may also be
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) * returned.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) int vme_slave_set(struct vme_resource *resource, int enabled,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) unsigned long long vme_base, unsigned long long size,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) dma_addr_t buf_base, u32 aspace, u32 cycle)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) struct vme_bridge *bridge = find_bridge(resource);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) struct vme_slave_resource *image;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) int retval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) if (resource->type != VME_SLAVE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) printk(KERN_ERR "Not a slave resource\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) image = list_entry(resource->entry, struct vme_slave_resource, list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) if (!bridge->slave_set) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) printk(KERN_ERR "Function not supported\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) return -ENOSYS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) if (!(((image->address_attr & aspace) == aspace) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) ((image->cycle_attr & cycle) == cycle))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) printk(KERN_ERR "Invalid attributes\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) retval = vme_check_window(aspace, vme_base, size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) if (retval)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) return retval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) return bridge->slave_set(image, enabled, vme_base, size, buf_base,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) aspace, cycle);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) EXPORT_SYMBOL(vme_slave_set);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) * vme_slave_get - Retrieve VME slave window configuration.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) * @resource: Pointer to VME slave resource.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) * @enabled: Pointer to variable for storing state.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) * @vme_base: Pointer to variable for storing window base address.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) * @size: Pointer to variable for storing window size.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) * @buf_base: Pointer to variable for storing slave buffer base address.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) * @aspace: Pointer to variable for storing VME address space.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) * @cycle: Pointer to variable for storing VME data transfer cycle type.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) * Return configuration for provided VME slave window.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) * Return: Zero on success, -EINVAL if operation is not supported on this
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) * device or if an invalid resource has been provided.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) int vme_slave_get(struct vme_resource *resource, int *enabled,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) unsigned long long *vme_base, unsigned long long *size,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) dma_addr_t *buf_base, u32 *aspace, u32 *cycle)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) struct vme_bridge *bridge = find_bridge(resource);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) struct vme_slave_resource *image;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) if (resource->type != VME_SLAVE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) printk(KERN_ERR "Not a slave resource\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) image = list_entry(resource->entry, struct vme_slave_resource, list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) if (!bridge->slave_get) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) printk(KERN_ERR "vme_slave_get not supported\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) return bridge->slave_get(image, enabled, vme_base, size, buf_base,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) aspace, cycle);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) EXPORT_SYMBOL(vme_slave_get);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) * vme_slave_free - Free VME slave window
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) * @resource: Pointer to VME slave resource.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) * Free the provided slave resource so that it may be reallocated.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) void vme_slave_free(struct vme_resource *resource)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) struct vme_slave_resource *slave_image;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) if (resource->type != VME_SLAVE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) printk(KERN_ERR "Not a slave resource\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) slave_image = list_entry(resource->entry, struct vme_slave_resource,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) if (!slave_image) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) printk(KERN_ERR "Can't find slave resource\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) /* Unlock image */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) mutex_lock(&slave_image->mtx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) if (slave_image->locked == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) printk(KERN_ERR "Image is already free\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) slave_image->locked = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) mutex_unlock(&slave_image->mtx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) /* Free up resource memory */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) kfree(resource);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) EXPORT_SYMBOL(vme_slave_free);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) * vme_master_request - Request a VME master window resource.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) * @vdev: Pointer to VME device struct vme_dev assigned to driver instance.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) * @address: Required VME address space.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) * @cycle: Required VME data transfer cycle type.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) * @dwidth: Required VME data transfer width.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) * Request use of a VME window resource capable of being set for the requested
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) * address space, data transfer cycle and width.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) * Return: Pointer to VME resource on success, NULL on failure.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) struct vme_resource *vme_master_request(struct vme_dev *vdev, u32 address,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) u32 cycle, u32 dwidth)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) struct vme_bridge *bridge;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) struct list_head *master_pos = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) struct vme_master_resource *allocated_image = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) struct vme_master_resource *master_image = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) struct vme_resource *resource = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) bridge = vdev->bridge;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) if (!bridge) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) printk(KERN_ERR "Can't find VME bus\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) goto err_bus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) /* Loop through master resources */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) list_for_each(master_pos, &bridge->master_resources) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) master_image = list_entry(master_pos,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) struct vme_master_resource, list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) if (!master_image) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) printk(KERN_WARNING "Registered NULL master resource\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) /* Find an unlocked and compatible image */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) spin_lock(&master_image->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) if (((master_image->address_attr & address) == address) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) ((master_image->cycle_attr & cycle) == cycle) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) ((master_image->width_attr & dwidth) == dwidth) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) (master_image->locked == 0)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) master_image->locked = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) spin_unlock(&master_image->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) allocated_image = master_image;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) spin_unlock(&master_image->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) /* Check to see if we found a resource */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) if (!allocated_image) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) printk(KERN_ERR "Can't find a suitable resource\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) goto err_image;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) resource = kmalloc(sizeof(*resource), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) if (!resource)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) goto err_alloc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) resource->type = VME_MASTER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) resource->entry = &allocated_image->list;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) return resource;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) err_alloc:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) /* Unlock image */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) spin_lock(&master_image->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) master_image->locked = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) spin_unlock(&master_image->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) err_image:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) err_bus:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) EXPORT_SYMBOL(vme_master_request);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) * vme_master_set - Set VME master window configuration.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) * @resource: Pointer to VME master resource.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) * @enabled: State to which the window should be configured.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) * @vme_base: Base address for the window.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) * @size: Size of the VME window.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) * @aspace: VME address space for the VME window.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) * @cycle: VME data transfer cycle type for the VME window.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) * @dwidth: VME data transfer width for the VME window.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) * Set configuration for provided VME master window.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) * Return: Zero on success, -EINVAL if operation is not supported on this
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) * device, if an invalid resource has been provided or invalid
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) * attributes are provided. Hardware specific errors may also be
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) * returned.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) int vme_master_set(struct vme_resource *resource, int enabled,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) unsigned long long vme_base, unsigned long long size, u32 aspace,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) u32 cycle, u32 dwidth)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) struct vme_bridge *bridge = find_bridge(resource);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) struct vme_master_resource *image;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) int retval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) if (resource->type != VME_MASTER) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) printk(KERN_ERR "Not a master resource\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) image = list_entry(resource->entry, struct vme_master_resource, list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) if (!bridge->master_set) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) printk(KERN_WARNING "vme_master_set not supported\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) if (!(((image->address_attr & aspace) == aspace) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) ((image->cycle_attr & cycle) == cycle) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) ((image->width_attr & dwidth) == dwidth))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) printk(KERN_WARNING "Invalid attributes\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) retval = vme_check_window(aspace, vme_base, size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) if (retval)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) return retval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) return bridge->master_set(image, enabled, vme_base, size, aspace,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) cycle, dwidth);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) EXPORT_SYMBOL(vme_master_set);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) * vme_master_get - Retrieve VME master window configuration.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) * @resource: Pointer to VME master resource.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) * @enabled: Pointer to variable for storing state.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) * @vme_base: Pointer to variable for storing window base address.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) * @size: Pointer to variable for storing window size.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) * @aspace: Pointer to variable for storing VME address space.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) * @cycle: Pointer to variable for storing VME data transfer cycle type.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) * @dwidth: Pointer to variable for storing VME data transfer width.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) * Return configuration for provided VME master window.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) * Return: Zero on success, -EINVAL if operation is not supported on this
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) * device or if an invalid resource has been provided.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) int vme_master_get(struct vme_resource *resource, int *enabled,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) unsigned long long *vme_base, unsigned long long *size, u32 *aspace,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) u32 *cycle, u32 *dwidth)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) struct vme_bridge *bridge = find_bridge(resource);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) struct vme_master_resource *image;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) if (resource->type != VME_MASTER) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) printk(KERN_ERR "Not a master resource\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) image = list_entry(resource->entry, struct vme_master_resource, list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) if (!bridge->master_get) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) printk(KERN_WARNING "%s not supported\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) return bridge->master_get(image, enabled, vme_base, size, aspace,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) cycle, dwidth);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) EXPORT_SYMBOL(vme_master_get);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) * vme_master_write - Read data from VME space into a buffer.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) * @resource: Pointer to VME master resource.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) * @buf: Pointer to buffer where data should be transferred.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) * @count: Number of bytes to transfer.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) * @offset: Offset into VME master window at which to start transfer.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) * Perform read of count bytes of data from location on VME bus which maps into
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) * the VME master window at offset to buf.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) * Return: Number of bytes read, -EINVAL if resource is not a VME master
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) * resource or read operation is not supported. -EFAULT returned if
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) * invalid offset is provided. Hardware specific errors may also be
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) * returned.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) ssize_t vme_master_read(struct vme_resource *resource, void *buf, size_t count,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) loff_t offset)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) struct vme_bridge *bridge = find_bridge(resource);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) struct vme_master_resource *image;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) size_t length;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) if (!bridge->master_read) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) printk(KERN_WARNING "Reading from resource not supported\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) if (resource->type != VME_MASTER) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) printk(KERN_ERR "Not a master resource\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) image = list_entry(resource->entry, struct vme_master_resource, list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) length = vme_get_size(resource);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) if (offset > length) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) printk(KERN_WARNING "Invalid Offset\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) if ((offset + count) > length)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) count = length - offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) return bridge->master_read(image, buf, count, offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) EXPORT_SYMBOL(vme_master_read);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) * vme_master_write - Write data out to VME space from a buffer.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) * @resource: Pointer to VME master resource.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) * @buf: Pointer to buffer holding data to transfer.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) * @count: Number of bytes to transfer.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) * @offset: Offset into VME master window at which to start transfer.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) * Perform write of count bytes of data from buf to location on VME bus which
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) * maps into the VME master window at offset.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) * Return: Number of bytes written, -EINVAL if resource is not a VME master
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) * resource or write operation is not supported. -EFAULT returned if
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) * invalid offset is provided. Hardware specific errors may also be
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) * returned.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) ssize_t vme_master_write(struct vme_resource *resource, void *buf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) size_t count, loff_t offset)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) struct vme_bridge *bridge = find_bridge(resource);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) struct vme_master_resource *image;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) size_t length;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) if (!bridge->master_write) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) printk(KERN_WARNING "Writing to resource not supported\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) if (resource->type != VME_MASTER) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) printk(KERN_ERR "Not a master resource\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) image = list_entry(resource->entry, struct vme_master_resource, list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) length = vme_get_size(resource);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) if (offset > length) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) printk(KERN_WARNING "Invalid Offset\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) if ((offset + count) > length)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) count = length - offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) return bridge->master_write(image, buf, count, offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) EXPORT_SYMBOL(vme_master_write);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) * vme_master_rmw - Perform read-modify-write cycle.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) * @resource: Pointer to VME master resource.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) * @mask: Bits to be compared and swapped in operation.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) * @compare: Bits to be compared with data read from offset.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) * @swap: Bits to be swapped in data read from offset.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) * @offset: Offset into VME master window at which to perform operation.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) * Perform read-modify-write cycle on provided location:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) * - Location on VME bus is read.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) * - Bits selected by mask are compared with compare.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) * - Where a selected bit matches that in compare and are selected in swap,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) * the bit is swapped.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) * - Result written back to location on VME bus.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) * Return: Bytes written on success, -EINVAL if resource is not a VME master
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) * resource or RMW operation is not supported. Hardware specific
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) * errors may also be returned.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) unsigned int vme_master_rmw(struct vme_resource *resource, unsigned int mask,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) unsigned int compare, unsigned int swap, loff_t offset)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) struct vme_bridge *bridge = find_bridge(resource);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) struct vme_master_resource *image;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) if (!bridge->master_rmw) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) printk(KERN_WARNING "Writing to resource not supported\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) if (resource->type != VME_MASTER) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) printk(KERN_ERR "Not a master resource\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) image = list_entry(resource->entry, struct vme_master_resource, list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) return bridge->master_rmw(image, mask, compare, swap, offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) EXPORT_SYMBOL(vme_master_rmw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) * vme_master_mmap - Mmap region of VME master window.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) * @resource: Pointer to VME master resource.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) * @vma: Pointer to definition of user mapping.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) * Memory map a region of the VME master window into user space.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) * Return: Zero on success, -EINVAL if resource is not a VME master
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) * resource or -EFAULT if map exceeds window size. Other generic mmap
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) * errors may also be returned.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) int vme_master_mmap(struct vme_resource *resource, struct vm_area_struct *vma)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) struct vme_master_resource *image;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) phys_addr_t phys_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) unsigned long vma_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) if (resource->type != VME_MASTER) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) pr_err("Not a master resource\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) image = list_entry(resource->entry, struct vme_master_resource, list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) phys_addr = image->bus_resource.start + (vma->vm_pgoff << PAGE_SHIFT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) vma_size = vma->vm_end - vma->vm_start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) if (phys_addr + vma_size > image->bus_resource.end + 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) pr_err("Map size cannot exceed the window size\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) return vm_iomap_memory(vma, phys_addr, vma->vm_end - vma->vm_start);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) EXPORT_SYMBOL(vme_master_mmap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) * vme_master_free - Free VME master window
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) * @resource: Pointer to VME master resource.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) * Free the provided master resource so that it may be reallocated.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) void vme_master_free(struct vme_resource *resource)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) struct vme_master_resource *master_image;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) if (resource->type != VME_MASTER) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) printk(KERN_ERR "Not a master resource\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) master_image = list_entry(resource->entry, struct vme_master_resource,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) if (!master_image) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) printk(KERN_ERR "Can't find master resource\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) /* Unlock image */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) spin_lock(&master_image->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) if (master_image->locked == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) printk(KERN_ERR "Image is already free\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) master_image->locked = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) spin_unlock(&master_image->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) /* Free up resource memory */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) kfree(resource);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) EXPORT_SYMBOL(vme_master_free);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860) * vme_dma_request - Request a DMA controller.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) * @vdev: Pointer to VME device struct vme_dev assigned to driver instance.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862) * @route: Required src/destination combination.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) * Request a VME DMA controller with capability to perform transfers bewteen
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865) * requested source/destination combination.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867) * Return: Pointer to VME DMA resource on success, NULL on failure.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869) struct vme_resource *vme_dma_request(struct vme_dev *vdev, u32 route)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871) struct vme_bridge *bridge;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872) struct list_head *dma_pos = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) struct vme_dma_resource *allocated_ctrlr = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874) struct vme_dma_resource *dma_ctrlr = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875) struct vme_resource *resource = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877) /* XXX Not checking resource attributes */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878) printk(KERN_ERR "No VME resource Attribute tests done\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880) bridge = vdev->bridge;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881) if (!bridge) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882) printk(KERN_ERR "Can't find VME bus\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883) goto err_bus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) /* Loop through DMA resources */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887) list_for_each(dma_pos, &bridge->dma_resources) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888) dma_ctrlr = list_entry(dma_pos,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889) struct vme_dma_resource, list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890) if (!dma_ctrlr) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891) printk(KERN_ERR "Registered NULL DMA resource\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895) /* Find an unlocked and compatible controller */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896) mutex_lock(&dma_ctrlr->mtx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897) if (((dma_ctrlr->route_attr & route) == route) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898) (dma_ctrlr->locked == 0)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900) dma_ctrlr->locked = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901) mutex_unlock(&dma_ctrlr->mtx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902) allocated_ctrlr = dma_ctrlr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905) mutex_unlock(&dma_ctrlr->mtx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908) /* Check to see if we found a resource */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909) if (!allocated_ctrlr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910) goto err_ctrlr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912) resource = kmalloc(sizeof(*resource), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913) if (!resource)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914) goto err_alloc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916) resource->type = VME_DMA;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917) resource->entry = &allocated_ctrlr->list;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919) return resource;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921) err_alloc:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922) /* Unlock image */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923) mutex_lock(&dma_ctrlr->mtx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924) dma_ctrlr->locked = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925) mutex_unlock(&dma_ctrlr->mtx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926) err_ctrlr:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927) err_bus:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930) EXPORT_SYMBOL(vme_dma_request);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933) * vme_new_dma_list - Create new VME DMA list.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934) * @resource: Pointer to VME DMA resource.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936) * Create a new VME DMA list. It is the responsibility of the user to free
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937) * the list once it is no longer required with vme_dma_list_free().
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939) * Return: Pointer to new VME DMA list, NULL on allocation failure or invalid
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940) * VME DMA resource.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942) struct vme_dma_list *vme_new_dma_list(struct vme_resource *resource)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944) struct vme_dma_list *dma_list;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946) if (resource->type != VME_DMA) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947) printk(KERN_ERR "Not a DMA resource\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951) dma_list = kmalloc(sizeof(*dma_list), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952) if (!dma_list)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 954)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 955) INIT_LIST_HEAD(&dma_list->entries);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 956) dma_list->parent = list_entry(resource->entry,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 957) struct vme_dma_resource,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 958) list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 959) mutex_init(&dma_list->mtx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 960)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 961) return dma_list;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 962) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 963) EXPORT_SYMBOL(vme_new_dma_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 964)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 965) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 966) * vme_dma_pattern_attribute - Create "Pattern" type VME DMA list attribute.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 967) * @pattern: Value to use used as pattern
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 968) * @type: Type of pattern to be written.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 969) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 970) * Create VME DMA list attribute for pattern generation. It is the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 971) * responsibility of the user to free used attributes using
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 972) * vme_dma_free_attribute().
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 973) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 974) * Return: Pointer to VME DMA attribute, NULL on failure.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 975) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 976) struct vme_dma_attr *vme_dma_pattern_attribute(u32 pattern, u32 type)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 977) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 978) struct vme_dma_attr *attributes;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 979) struct vme_dma_pattern *pattern_attr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 980)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 981) attributes = kmalloc(sizeof(*attributes), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 982) if (!attributes)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 983) goto err_attr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 984)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 985) pattern_attr = kmalloc(sizeof(*pattern_attr), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 986) if (!pattern_attr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 987) goto err_pat;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 988)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 989) attributes->type = VME_DMA_PATTERN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 990) attributes->private = (void *)pattern_attr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 991)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 992) pattern_attr->pattern = pattern;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 993) pattern_attr->type = type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 994)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 995) return attributes;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 996)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 997) err_pat:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 998) kfree(attributes);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 999) err_attr:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002) EXPORT_SYMBOL(vme_dma_pattern_attribute);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005) * vme_dma_pci_attribute - Create "PCI" type VME DMA list attribute.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006) * @address: PCI base address for DMA transfer.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008) * Create VME DMA list attribute pointing to a location on PCI for DMA
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009) * transfers. It is the responsibility of the user to free used attributes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010) * using vme_dma_free_attribute().
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012) * Return: Pointer to VME DMA attribute, NULL on failure.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014) struct vme_dma_attr *vme_dma_pci_attribute(dma_addr_t address)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016) struct vme_dma_attr *attributes;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017) struct vme_dma_pci *pci_attr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019) /* XXX Run some sanity checks here */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021) attributes = kmalloc(sizeof(*attributes), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022) if (!attributes)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023) goto err_attr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025) pci_attr = kmalloc(sizeof(*pci_attr), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026) if (!pci_attr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027) goto err_pci;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029) attributes->type = VME_DMA_PCI;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030) attributes->private = (void *)pci_attr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032) pci_attr->address = address;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034) return attributes;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036) err_pci:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037) kfree(attributes);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038) err_attr:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041) EXPORT_SYMBOL(vme_dma_pci_attribute);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044) * vme_dma_vme_attribute - Create "VME" type VME DMA list attribute.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045) * @address: VME base address for DMA transfer.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046) * @aspace: VME address space to use for DMA transfer.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047) * @cycle: VME bus cycle to use for DMA transfer.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048) * @dwidth: VME data width to use for DMA transfer.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050) * Create VME DMA list attribute pointing to a location on the VME bus for DMA
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051) * transfers. It is the responsibility of the user to free used attributes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052) * using vme_dma_free_attribute().
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1054) * Return: Pointer to VME DMA attribute, NULL on failure.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1055) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1056) struct vme_dma_attr *vme_dma_vme_attribute(unsigned long long address,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1057) u32 aspace, u32 cycle, u32 dwidth)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1058) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1059) struct vme_dma_attr *attributes;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1060) struct vme_dma_vme *vme_attr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1061)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1062) attributes = kmalloc(sizeof(*attributes), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1063) if (!attributes)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1064) goto err_attr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1065)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1066) vme_attr = kmalloc(sizeof(*vme_attr), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1067) if (!vme_attr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1068) goto err_vme;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1069)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1070) attributes->type = VME_DMA_VME;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1071) attributes->private = (void *)vme_attr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1072)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1073) vme_attr->address = address;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1074) vme_attr->aspace = aspace;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1075) vme_attr->cycle = cycle;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1076) vme_attr->dwidth = dwidth;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1077)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1078) return attributes;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1079)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1080) err_vme:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1081) kfree(attributes);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1082) err_attr:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1083) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1084) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1085) EXPORT_SYMBOL(vme_dma_vme_attribute);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1086)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1087) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1088) * vme_dma_free_attribute - Free DMA list attribute.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1089) * @attributes: Pointer to DMA list attribute.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1090) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1091) * Free VME DMA list attribute. VME DMA list attributes can be safely freed
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1092) * once vme_dma_list_add() has returned.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1093) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1094) void vme_dma_free_attribute(struct vme_dma_attr *attributes)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1095) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1096) kfree(attributes->private);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1097) kfree(attributes);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1098) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1099) EXPORT_SYMBOL(vme_dma_free_attribute);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1100)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1101) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1102) * vme_dma_list_add - Add enty to a VME DMA list.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1103) * @list: Pointer to VME list.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1104) * @src: Pointer to DMA list attribute to use as source.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1105) * @dest: Pointer to DMA list attribute to use as destination.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1106) * @count: Number of bytes to transfer.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1107) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1108) * Add an entry to the provided VME DMA list. Entry requires pointers to source
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1109) * and destination DMA attributes and a count.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1110) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1111) * Please note, the attributes supported as source and destinations for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1112) * transfers are hardware dependent.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1113) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1114) * Return: Zero on success, -EINVAL if operation is not supported on this
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1115) * device or if the link list has already been submitted for execution.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1116) * Hardware specific errors also possible.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1117) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1118) int vme_dma_list_add(struct vme_dma_list *list, struct vme_dma_attr *src,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1119) struct vme_dma_attr *dest, size_t count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1120) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1121) struct vme_bridge *bridge = list->parent->parent;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1122) int retval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1123)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1124) if (!bridge->dma_list_add) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1125) printk(KERN_WARNING "Link List DMA generation not supported\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1126) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1127) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1128)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1129) if (!mutex_trylock(&list->mtx)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1130) printk(KERN_ERR "Link List already submitted\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1131) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1132) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1133)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1134) retval = bridge->dma_list_add(list, src, dest, count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1135)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1136) mutex_unlock(&list->mtx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1137)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1138) return retval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1139) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1140) EXPORT_SYMBOL(vme_dma_list_add);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1141)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1142) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1143) * vme_dma_list_exec - Queue a VME DMA list for execution.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1144) * @list: Pointer to VME list.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1145) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1146) * Queue the provided VME DMA list for execution. The call will return once the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1147) * list has been executed.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1148) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1149) * Return: Zero on success, -EINVAL if operation is not supported on this
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1150) * device. Hardware specific errors also possible.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1151) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1152) int vme_dma_list_exec(struct vme_dma_list *list)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1153) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1154) struct vme_bridge *bridge = list->parent->parent;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1155) int retval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1156)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1157) if (!bridge->dma_list_exec) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1158) printk(KERN_ERR "Link List DMA execution not supported\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1159) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1160) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1161)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1162) mutex_lock(&list->mtx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1163)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1164) retval = bridge->dma_list_exec(list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1165)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1166) mutex_unlock(&list->mtx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1167)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1168) return retval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1169) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1170) EXPORT_SYMBOL(vme_dma_list_exec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1171)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1172) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1173) * vme_dma_list_free - Free a VME DMA list.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1174) * @list: Pointer to VME list.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1175) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1176) * Free the provided DMA list and all its entries.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1177) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1178) * Return: Zero on success, -EINVAL on invalid VME resource, -EBUSY if resource
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1179) * is still in use. Hardware specific errors also possible.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1180) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1181) int vme_dma_list_free(struct vme_dma_list *list)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1182) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1183) struct vme_bridge *bridge = list->parent->parent;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1184) int retval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1185)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1186) if (!bridge->dma_list_empty) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1187) printk(KERN_WARNING "Emptying of Link Lists not supported\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1188) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1189) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1190)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1191) if (!mutex_trylock(&list->mtx)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1192) printk(KERN_ERR "Link List in use\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1193) return -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1194) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1195)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1196) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1197) * Empty out all of the entries from the DMA list. We need to go to the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1198) * low level driver as DMA entries are driver specific.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1199) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1200) retval = bridge->dma_list_empty(list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1201) if (retval) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1202) printk(KERN_ERR "Unable to empty link-list entries\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1203) mutex_unlock(&list->mtx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1204) return retval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1205) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1206) mutex_unlock(&list->mtx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1207) kfree(list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1208)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1209) return retval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1210) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1211) EXPORT_SYMBOL(vme_dma_list_free);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1212)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1213) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1214) * vme_dma_free - Free a VME DMA resource.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1215) * @resource: Pointer to VME DMA resource.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1216) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1217) * Free the provided DMA resource so that it may be reallocated.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1218) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1219) * Return: Zero on success, -EINVAL on invalid VME resource, -EBUSY if resource
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1220) * is still active.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1221) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1222) int vme_dma_free(struct vme_resource *resource)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1223) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1224) struct vme_dma_resource *ctrlr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1225)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1226) if (resource->type != VME_DMA) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1227) printk(KERN_ERR "Not a DMA resource\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1228) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1229) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1230)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1231) ctrlr = list_entry(resource->entry, struct vme_dma_resource, list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1232)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1233) if (!mutex_trylock(&ctrlr->mtx)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1234) printk(KERN_ERR "Resource busy, can't free\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1235) return -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1236) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1237)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1238) if (!(list_empty(&ctrlr->pending) && list_empty(&ctrlr->running))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1239) printk(KERN_WARNING "Resource still processing transfers\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1240) mutex_unlock(&ctrlr->mtx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1241) return -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1242) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1243)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1244) ctrlr->locked = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1245)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1246) mutex_unlock(&ctrlr->mtx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1247)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1248) kfree(resource);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1249)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1250) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1251) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1252) EXPORT_SYMBOL(vme_dma_free);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1253)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1254) void vme_bus_error_handler(struct vme_bridge *bridge,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1255) unsigned long long address, int am)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1256) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1257) struct list_head *handler_pos = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1258) struct vme_error_handler *handler;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1259) int handler_triggered = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1260) u32 aspace = vme_get_aspace(am);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1261)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1262) list_for_each(handler_pos, &bridge->vme_error_handlers) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1263) handler = list_entry(handler_pos, struct vme_error_handler,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1264) list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1265) if ((aspace == handler->aspace) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1266) (address >= handler->start) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1267) (address < handler->end)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1268) if (!handler->num_errors)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1269) handler->first_error = address;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1270) if (handler->num_errors != UINT_MAX)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1271) handler->num_errors++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1272) handler_triggered = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1273) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1274) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1275)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1276) if (!handler_triggered)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1277) dev_err(bridge->parent,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1278) "Unhandled VME access error at address 0x%llx\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1279) address);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1280) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1281) EXPORT_SYMBOL(vme_bus_error_handler);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1282)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1283) struct vme_error_handler *vme_register_error_handler(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1284) struct vme_bridge *bridge, u32 aspace,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1285) unsigned long long address, size_t len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1286) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1287) struct vme_error_handler *handler;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1288)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1289) handler = kmalloc(sizeof(*handler), GFP_ATOMIC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1290) if (!handler)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1291) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1292)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1293) handler->aspace = aspace;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1294) handler->start = address;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1295) handler->end = address + len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1296) handler->num_errors = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1297) handler->first_error = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1298) list_add_tail(&handler->list, &bridge->vme_error_handlers);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1299)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1300) return handler;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1301) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1302) EXPORT_SYMBOL(vme_register_error_handler);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1303)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1304) void vme_unregister_error_handler(struct vme_error_handler *handler)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1305) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1306) list_del(&handler->list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1307) kfree(handler);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1308) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1309) EXPORT_SYMBOL(vme_unregister_error_handler);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1310)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1311) void vme_irq_handler(struct vme_bridge *bridge, int level, int statid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1312) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1313) void (*call)(int, int, void *);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1314) void *priv_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1315)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1316) call = bridge->irq[level - 1].callback[statid].func;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1317) priv_data = bridge->irq[level - 1].callback[statid].priv_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1318) if (call)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1319) call(level, statid, priv_data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1320) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1321) printk(KERN_WARNING "Spurious VME interrupt, level:%x, vector:%x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1322) level, statid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1323) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1324) EXPORT_SYMBOL(vme_irq_handler);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1325)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1326) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1327) * vme_irq_request - Request a specific VME interrupt.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1328) * @vdev: Pointer to VME device struct vme_dev assigned to driver instance.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1329) * @level: Interrupt priority being requested.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1330) * @statid: Interrupt vector being requested.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1331) * @callback: Pointer to callback function called when VME interrupt/vector
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1332) * received.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1333) * @priv_data: Generic pointer that will be passed to the callback function.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1334) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1335) * Request callback to be attached as a handler for VME interrupts with provided
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1336) * level and statid.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1337) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1338) * Return: Zero on success, -EINVAL on invalid vme device, level or if the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1339) * function is not supported, -EBUSY if the level/statid combination is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1340) * already in use. Hardware specific errors also possible.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1341) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1342) int vme_irq_request(struct vme_dev *vdev, int level, int statid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1343) void (*callback)(int, int, void *),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1344) void *priv_data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1345) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1346) struct vme_bridge *bridge;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1347)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1348) bridge = vdev->bridge;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1349) if (!bridge) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1350) printk(KERN_ERR "Can't find VME bus\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1351) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1352) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1353)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1354) if ((level < 1) || (level > 7)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1355) printk(KERN_ERR "Invalid interrupt level\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1356) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1357) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1358)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1359) if (!bridge->irq_set) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1360) printk(KERN_ERR "Configuring interrupts not supported\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1361) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1362) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1363)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1364) mutex_lock(&bridge->irq_mtx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1365)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1366) if (bridge->irq[level - 1].callback[statid].func) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1367) mutex_unlock(&bridge->irq_mtx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1368) printk(KERN_WARNING "VME Interrupt already taken\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1369) return -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1370) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1371)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1372) bridge->irq[level - 1].count++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1373) bridge->irq[level - 1].callback[statid].priv_data = priv_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1374) bridge->irq[level - 1].callback[statid].func = callback;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1375)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1376) /* Enable IRQ level */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1377) bridge->irq_set(bridge, level, 1, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1378)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1379) mutex_unlock(&bridge->irq_mtx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1380)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1381) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1382) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1383) EXPORT_SYMBOL(vme_irq_request);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1384)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1385) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1386) * vme_irq_free - Free a VME interrupt.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1387) * @vdev: Pointer to VME device struct vme_dev assigned to driver instance.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1388) * @level: Interrupt priority of interrupt being freed.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1389) * @statid: Interrupt vector of interrupt being freed.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1390) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1391) * Remove previously attached callback from VME interrupt priority/vector.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1392) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1393) void vme_irq_free(struct vme_dev *vdev, int level, int statid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1394) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1395) struct vme_bridge *bridge;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1396)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1397) bridge = vdev->bridge;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1398) if (!bridge) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1399) printk(KERN_ERR "Can't find VME bus\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1400) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1401) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1402)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1403) if ((level < 1) || (level > 7)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1404) printk(KERN_ERR "Invalid interrupt level\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1405) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1406) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1407)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1408) if (!bridge->irq_set) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1409) printk(KERN_ERR "Configuring interrupts not supported\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1410) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1411) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1412)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1413) mutex_lock(&bridge->irq_mtx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1414)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1415) bridge->irq[level - 1].count--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1416)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1417) /* Disable IRQ level if no more interrupts attached at this level*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1418) if (bridge->irq[level - 1].count == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1419) bridge->irq_set(bridge, level, 0, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1420)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1421) bridge->irq[level - 1].callback[statid].func = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1422) bridge->irq[level - 1].callback[statid].priv_data = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1423)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1424) mutex_unlock(&bridge->irq_mtx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1425) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1426) EXPORT_SYMBOL(vme_irq_free);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1427)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1428) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1429) * vme_irq_generate - Generate VME interrupt.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1430) * @vdev: Pointer to VME device struct vme_dev assigned to driver instance.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1431) * @level: Interrupt priority at which to assert the interrupt.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1432) * @statid: Interrupt vector to associate with the interrupt.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1433) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1434) * Generate a VME interrupt of the provided level and with the provided
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1435) * statid.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1436) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1437) * Return: Zero on success, -EINVAL on invalid vme device, level or if the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1438) * function is not supported. Hardware specific errors also possible.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1439) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1440) int vme_irq_generate(struct vme_dev *vdev, int level, int statid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1441) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1442) struct vme_bridge *bridge;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1443)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1444) bridge = vdev->bridge;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1445) if (!bridge) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1446) printk(KERN_ERR "Can't find VME bus\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1447) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1448) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1449)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1450) if ((level < 1) || (level > 7)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1451) printk(KERN_WARNING "Invalid interrupt level\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1452) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1453) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1454)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1455) if (!bridge->irq_generate) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1456) printk(KERN_WARNING "Interrupt generation not supported\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1457) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1458) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1459)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1460) return bridge->irq_generate(bridge, level, statid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1461) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1462) EXPORT_SYMBOL(vme_irq_generate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1463)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1464) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1465) * vme_lm_request - Request a VME location monitor
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1466) * @vdev: Pointer to VME device struct vme_dev assigned to driver instance.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1467) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1468) * Allocate a location monitor resource to the driver. A location monitor
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1469) * allows the driver to monitor accesses to a contiguous number of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1470) * addresses on the VME bus.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1471) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1472) * Return: Pointer to a VME resource on success or NULL on failure.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1473) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1474) struct vme_resource *vme_lm_request(struct vme_dev *vdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1475) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1476) struct vme_bridge *bridge;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1477) struct list_head *lm_pos = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1478) struct vme_lm_resource *allocated_lm = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1479) struct vme_lm_resource *lm = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1480) struct vme_resource *resource = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1481)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1482) bridge = vdev->bridge;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1483) if (!bridge) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1484) printk(KERN_ERR "Can't find VME bus\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1485) goto err_bus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1486) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1487)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1488) /* Loop through LM resources */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1489) list_for_each(lm_pos, &bridge->lm_resources) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1490) lm = list_entry(lm_pos,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1491) struct vme_lm_resource, list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1492) if (!lm) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1493) printk(KERN_ERR "Registered NULL Location Monitor resource\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1494) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1495) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1496)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1497) /* Find an unlocked controller */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1498) mutex_lock(&lm->mtx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1499) if (lm->locked == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1500) lm->locked = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1501) mutex_unlock(&lm->mtx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1502) allocated_lm = lm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1503) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1504) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1505) mutex_unlock(&lm->mtx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1506) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1507)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1508) /* Check to see if we found a resource */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1509) if (!allocated_lm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1510) goto err_lm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1511)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1512) resource = kmalloc(sizeof(*resource), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1513) if (!resource)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1514) goto err_alloc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1515)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1516) resource->type = VME_LM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1517) resource->entry = &allocated_lm->list;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1518)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1519) return resource;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1520)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1521) err_alloc:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1522) /* Unlock image */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1523) mutex_lock(&lm->mtx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1524) lm->locked = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1525) mutex_unlock(&lm->mtx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1526) err_lm:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1527) err_bus:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1528) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1529) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1530) EXPORT_SYMBOL(vme_lm_request);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1531)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1532) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1533) * vme_lm_count - Determine number of VME Addresses monitored
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1534) * @resource: Pointer to VME location monitor resource.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1535) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1536) * The number of contiguous addresses monitored is hardware dependent.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1537) * Return the number of contiguous addresses monitored by the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1538) * location monitor.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1539) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1540) * Return: Count of addresses monitored or -EINVAL when provided with an
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1541) * invalid location monitor resource.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1542) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1543) int vme_lm_count(struct vme_resource *resource)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1544) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1545) struct vme_lm_resource *lm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1546)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1547) if (resource->type != VME_LM) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1548) printk(KERN_ERR "Not a Location Monitor resource\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1549) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1550) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1551)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1552) lm = list_entry(resource->entry, struct vme_lm_resource, list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1553)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1554) return lm->monitors;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1555) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1556) EXPORT_SYMBOL(vme_lm_count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1557)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1558) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1559) * vme_lm_set - Configure location monitor
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1560) * @resource: Pointer to VME location monitor resource.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1561) * @lm_base: Base address to monitor.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1562) * @aspace: VME address space to monitor.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1563) * @cycle: VME bus cycle type to monitor.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1564) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1565) * Set the base address, address space and cycle type of accesses to be
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1566) * monitored by the location monitor.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1567) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1568) * Return: Zero on success, -EINVAL when provided with an invalid location
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1569) * monitor resource or function is not supported. Hardware specific
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1570) * errors may also be returned.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1571) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1572) int vme_lm_set(struct vme_resource *resource, unsigned long long lm_base,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1573) u32 aspace, u32 cycle)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1574) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1575) struct vme_bridge *bridge = find_bridge(resource);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1576) struct vme_lm_resource *lm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1577)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1578) if (resource->type != VME_LM) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1579) printk(KERN_ERR "Not a Location Monitor resource\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1580) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1581) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1582)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1583) lm = list_entry(resource->entry, struct vme_lm_resource, list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1584)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1585) if (!bridge->lm_set) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1586) printk(KERN_ERR "vme_lm_set not supported\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1587) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1588) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1589)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1590) return bridge->lm_set(lm, lm_base, aspace, cycle);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1591) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1592) EXPORT_SYMBOL(vme_lm_set);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1593)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1594) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1595) * vme_lm_get - Retrieve location monitor settings
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1596) * @resource: Pointer to VME location monitor resource.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1597) * @lm_base: Pointer used to output the base address monitored.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1598) * @aspace: Pointer used to output the address space monitored.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1599) * @cycle: Pointer used to output the VME bus cycle type monitored.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1600) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1601) * Retrieve the base address, address space and cycle type of accesses to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1602) * be monitored by the location monitor.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1603) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1604) * Return: Zero on success, -EINVAL when provided with an invalid location
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1605) * monitor resource or function is not supported. Hardware specific
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1606) * errors may also be returned.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1607) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1608) int vme_lm_get(struct vme_resource *resource, unsigned long long *lm_base,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1609) u32 *aspace, u32 *cycle)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1610) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1611) struct vme_bridge *bridge = find_bridge(resource);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1612) struct vme_lm_resource *lm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1613)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1614) if (resource->type != VME_LM) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1615) printk(KERN_ERR "Not a Location Monitor resource\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1616) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1617) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1618)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1619) lm = list_entry(resource->entry, struct vme_lm_resource, list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1620)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1621) if (!bridge->lm_get) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1622) printk(KERN_ERR "vme_lm_get not supported\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1623) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1624) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1625)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1626) return bridge->lm_get(lm, lm_base, aspace, cycle);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1627) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1628) EXPORT_SYMBOL(vme_lm_get);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1629)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1630) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1631) * vme_lm_attach - Provide callback for location monitor address
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1632) * @resource: Pointer to VME location monitor resource.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1633) * @monitor: Offset to which callback should be attached.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1634) * @callback: Pointer to callback function called when triggered.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1635) * @data: Generic pointer that will be passed to the callback function.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1636) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1637) * Attach a callback to the specificed offset into the location monitors
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1638) * monitored addresses. A generic pointer is provided to allow data to be
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1639) * passed to the callback when called.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1640) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1641) * Return: Zero on success, -EINVAL when provided with an invalid location
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1642) * monitor resource or function is not supported. Hardware specific
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1643) * errors may also be returned.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1644) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1645) int vme_lm_attach(struct vme_resource *resource, int monitor,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1646) void (*callback)(void *), void *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1647) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1648) struct vme_bridge *bridge = find_bridge(resource);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1649) struct vme_lm_resource *lm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1650)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1651) if (resource->type != VME_LM) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1652) printk(KERN_ERR "Not a Location Monitor resource\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1653) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1654) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1655)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1656) lm = list_entry(resource->entry, struct vme_lm_resource, list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1657)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1658) if (!bridge->lm_attach) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1659) printk(KERN_ERR "vme_lm_attach not supported\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1660) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1661) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1662)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1663) return bridge->lm_attach(lm, monitor, callback, data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1664) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1665) EXPORT_SYMBOL(vme_lm_attach);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1666)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1667) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1668) * vme_lm_detach - Remove callback for location monitor address
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1669) * @resource: Pointer to VME location monitor resource.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1670) * @monitor: Offset to which callback should be removed.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1671) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1672) * Remove the callback associated with the specificed offset into the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1673) * location monitors monitored addresses.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1674) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1675) * Return: Zero on success, -EINVAL when provided with an invalid location
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1676) * monitor resource or function is not supported. Hardware specific
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1677) * errors may also be returned.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1678) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1679) int vme_lm_detach(struct vme_resource *resource, int monitor)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1680) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1681) struct vme_bridge *bridge = find_bridge(resource);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1682) struct vme_lm_resource *lm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1683)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1684) if (resource->type != VME_LM) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1685) printk(KERN_ERR "Not a Location Monitor resource\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1686) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1687) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1688)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1689) lm = list_entry(resource->entry, struct vme_lm_resource, list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1690)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1691) if (!bridge->lm_detach) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1692) printk(KERN_ERR "vme_lm_detach not supported\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1693) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1694) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1695)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1696) return bridge->lm_detach(lm, monitor);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1697) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1698) EXPORT_SYMBOL(vme_lm_detach);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1699)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1700) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1701) * vme_lm_free - Free allocated VME location monitor
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1702) * @resource: Pointer to VME location monitor resource.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1703) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1704) * Free allocation of a VME location monitor.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1705) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1706) * WARNING: This function currently expects that any callbacks that have
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1707) * been attached to the location monitor have been removed.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1708) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1709) * Return: Zero on success, -EINVAL when provided with an invalid location
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1710) * monitor resource.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1711) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1712) void vme_lm_free(struct vme_resource *resource)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1713) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1714) struct vme_lm_resource *lm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1715)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1716) if (resource->type != VME_LM) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1717) printk(KERN_ERR "Not a Location Monitor resource\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1718) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1719) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1720)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1721) lm = list_entry(resource->entry, struct vme_lm_resource, list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1722)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1723) mutex_lock(&lm->mtx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1724)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1725) /* XXX
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1726) * Check to see that there aren't any callbacks still attached, if
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1727) * there are we should probably be detaching them!
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1728) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1729)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1730) lm->locked = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1731)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1732) mutex_unlock(&lm->mtx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1733)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1734) kfree(resource);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1735) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1736) EXPORT_SYMBOL(vme_lm_free);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1737)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1738) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1739) * vme_slot_num - Retrieve slot ID
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1740) * @vdev: Pointer to VME device struct vme_dev assigned to driver instance.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1741) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1742) * Retrieve the slot ID associated with the provided VME device.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1743) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1744) * Return: The slot ID on success, -EINVAL if VME bridge cannot be determined
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1745) * or the function is not supported. Hardware specific errors may also
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1746) * be returned.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1747) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1748) int vme_slot_num(struct vme_dev *vdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1749) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1750) struct vme_bridge *bridge;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1751)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1752) bridge = vdev->bridge;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1753) if (!bridge) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1754) printk(KERN_ERR "Can't find VME bus\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1755) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1756) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1757)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1758) if (!bridge->slot_get) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1759) printk(KERN_WARNING "vme_slot_num not supported\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1760) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1761) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1762)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1763) return bridge->slot_get(bridge);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1764) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1765) EXPORT_SYMBOL(vme_slot_num);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1766)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1767) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1768) * vme_bus_num - Retrieve bus number
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1769) * @vdev: Pointer to VME device struct vme_dev assigned to driver instance.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1770) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1771) * Retrieve the bus enumeration associated with the provided VME device.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1772) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1773) * Return: The bus number on success, -EINVAL if VME bridge cannot be
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1774) * determined.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1775) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1776) int vme_bus_num(struct vme_dev *vdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1777) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1778) struct vme_bridge *bridge;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1779)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1780) bridge = vdev->bridge;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1781) if (!bridge) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1782) pr_err("Can't find VME bus\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1783) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1784) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1785)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1786) return bridge->num;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1787) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1788) EXPORT_SYMBOL(vme_bus_num);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1789)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1790) /* - Bridge Registration --------------------------------------------------- */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1791)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1792) static void vme_dev_release(struct device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1793) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1794) kfree(dev_to_vme_dev(dev));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1795) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1796)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1797) /* Common bridge initialization */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1798) struct vme_bridge *vme_init_bridge(struct vme_bridge *bridge)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1799) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1800) INIT_LIST_HEAD(&bridge->vme_error_handlers);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1801) INIT_LIST_HEAD(&bridge->master_resources);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1802) INIT_LIST_HEAD(&bridge->slave_resources);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1803) INIT_LIST_HEAD(&bridge->dma_resources);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1804) INIT_LIST_HEAD(&bridge->lm_resources);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1805) mutex_init(&bridge->irq_mtx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1806)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1807) return bridge;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1808) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1809) EXPORT_SYMBOL(vme_init_bridge);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1810)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1811) int vme_register_bridge(struct vme_bridge *bridge)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1812) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1813) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1814) int ret = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1815)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1816) mutex_lock(&vme_buses_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1817) for (i = 0; i < sizeof(vme_bus_numbers) * 8; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1818) if ((vme_bus_numbers & (1 << i)) == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1819) vme_bus_numbers |= (1 << i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1820) bridge->num = i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1821) INIT_LIST_HEAD(&bridge->devices);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1822) list_add_tail(&bridge->bus_list, &vme_bus_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1823) ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1824) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1825) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1826) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1827) mutex_unlock(&vme_buses_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1828)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1829) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1830) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1831) EXPORT_SYMBOL(vme_register_bridge);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1832)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1833) void vme_unregister_bridge(struct vme_bridge *bridge)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1834) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1835) struct vme_dev *vdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1836) struct vme_dev *tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1837)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1838) mutex_lock(&vme_buses_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1839) vme_bus_numbers &= ~(1 << bridge->num);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1840) list_for_each_entry_safe(vdev, tmp, &bridge->devices, bridge_list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1841) list_del(&vdev->drv_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1842) list_del(&vdev->bridge_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1843) device_unregister(&vdev->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1844) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1845) list_del(&bridge->bus_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1846) mutex_unlock(&vme_buses_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1847) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1848) EXPORT_SYMBOL(vme_unregister_bridge);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1849)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1850) /* - Driver Registration --------------------------------------------------- */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1851)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1852) static int __vme_register_driver_bus(struct vme_driver *drv,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1853) struct vme_bridge *bridge, unsigned int ndevs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1854) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1855) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1856) unsigned int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1857) struct vme_dev *vdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1858) struct vme_dev *tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1859)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1860) for (i = 0; i < ndevs; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1861) vdev = kzalloc(sizeof(*vdev), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1862) if (!vdev) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1863) err = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1864) goto err_devalloc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1865) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1866) vdev->num = i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1867) vdev->bridge = bridge;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1868) vdev->dev.platform_data = drv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1869) vdev->dev.release = vme_dev_release;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1870) vdev->dev.parent = bridge->parent;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1871) vdev->dev.bus = &vme_bus_type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1872) dev_set_name(&vdev->dev, "%s.%u-%u", drv->name, bridge->num,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1873) vdev->num);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1874)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1875) err = device_register(&vdev->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1876) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1877) goto err_reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1878)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1879) if (vdev->dev.platform_data) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1880) list_add_tail(&vdev->drv_list, &drv->devices);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1881) list_add_tail(&vdev->bridge_list, &bridge->devices);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1882) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1883) device_unregister(&vdev->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1884) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1885) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1886)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1887) err_reg:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1888) put_device(&vdev->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1889) err_devalloc:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1890) list_for_each_entry_safe(vdev, tmp, &drv->devices, drv_list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1891) list_del(&vdev->drv_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1892) list_del(&vdev->bridge_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1893) device_unregister(&vdev->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1894) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1895) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1896) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1897)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1898) static int __vme_register_driver(struct vme_driver *drv, unsigned int ndevs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1899) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1900) struct vme_bridge *bridge;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1901) int err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1902)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1903) mutex_lock(&vme_buses_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1904) list_for_each_entry(bridge, &vme_bus_list, bus_list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1905) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1906) * This cannot cause trouble as we already have vme_buses_lock
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1907) * and if the bridge is removed, it will have to go through
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1908) * vme_unregister_bridge() to do it (which calls remove() on
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1909) * the bridge which in turn tries to acquire vme_buses_lock and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1910) * will have to wait).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1911) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1912) err = __vme_register_driver_bus(drv, bridge, ndevs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1913) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1914) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1915) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1916) mutex_unlock(&vme_buses_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1917) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1918) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1919)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1920) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1921) * vme_register_driver - Register a VME driver
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1922) * @drv: Pointer to VME driver structure to register.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1923) * @ndevs: Maximum number of devices to allow to be enumerated.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1924) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1925) * Register a VME device driver with the VME subsystem.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1926) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1927) * Return: Zero on success, error value on registration failure.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1928) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1929) int vme_register_driver(struct vme_driver *drv, unsigned int ndevs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1930) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1931) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1932)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1933) drv->driver.name = drv->name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1934) drv->driver.bus = &vme_bus_type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1935) INIT_LIST_HEAD(&drv->devices);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1936)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1937) err = driver_register(&drv->driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1938) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1939) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1940)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1941) err = __vme_register_driver(drv, ndevs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1942) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1943) driver_unregister(&drv->driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1944)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1945) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1946) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1947) EXPORT_SYMBOL(vme_register_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1948)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1949) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1950) * vme_unregister_driver - Unregister a VME driver
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1951) * @drv: Pointer to VME driver structure to unregister.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1952) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1953) * Unregister a VME device driver from the VME subsystem.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1954) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1955) void vme_unregister_driver(struct vme_driver *drv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1956) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1957) struct vme_dev *dev, *dev_tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1958)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1959) mutex_lock(&vme_buses_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1960) list_for_each_entry_safe(dev, dev_tmp, &drv->devices, drv_list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1961) list_del(&dev->drv_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1962) list_del(&dev->bridge_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1963) device_unregister(&dev->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1964) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1965) mutex_unlock(&vme_buses_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1966)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1967) driver_unregister(&drv->driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1968) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1969) EXPORT_SYMBOL(vme_unregister_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1970)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1971) /* - Bus Registration ------------------------------------------------------ */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1972)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1973) static int vme_bus_match(struct device *dev, struct device_driver *drv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1974) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1975) struct vme_driver *vme_drv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1976)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1977) vme_drv = container_of(drv, struct vme_driver, driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1978)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1979) if (dev->platform_data == vme_drv) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1980) struct vme_dev *vdev = dev_to_vme_dev(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1981)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1982) if (vme_drv->match && vme_drv->match(vdev))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1983) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1984)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1985) dev->platform_data = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1986) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1987) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1988) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1989)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1990) static int vme_bus_probe(struct device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1991) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1992) struct vme_driver *driver;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1993) struct vme_dev *vdev = dev_to_vme_dev(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1994)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1995) driver = dev->platform_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1996) if (driver->probe)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1997) return driver->probe(vdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1998)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1999) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2000) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2001)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2002) static int vme_bus_remove(struct device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2003) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2004) struct vme_driver *driver;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2005) struct vme_dev *vdev = dev_to_vme_dev(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2006)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2007) driver = dev->platform_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2008) if (driver->remove)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2009) return driver->remove(vdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2010)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2011) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2012) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2013)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2014) struct bus_type vme_bus_type = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2015) .name = "vme",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2016) .match = vme_bus_match,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2017) .probe = vme_bus_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2018) .remove = vme_bus_remove,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2019) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2020) EXPORT_SYMBOL(vme_bus_type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2021)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2022) static int __init vme_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2023) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2024) return bus_register(&vme_bus_type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2025) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2026) subsys_initcall(vme_init);