vme.c revision c26f6112990b90977db429596ed0640d153b3a32
1a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch/* 2a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch * VME Bridge Framework 3a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch * 466bd8db52ab48e7189e02d4bf1f23109cc1ede70Martyn Welch * Author: Martyn Welch <martyn.welch@ge.com> 566bd8db52ab48e7189e02d4bf1f23109cc1ede70Martyn Welch * Copyright 2008 GE Intelligent Platforms Embedded Systems, Inc. 6a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch * 7a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch * Based on work by Tom Armistead and Ajit Prem 8a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch * Copyright 2004 Motorola Inc. 9a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch * 10a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch * This program is free software; you can redistribute it and/or modify it 11a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch * under the terms of the GNU General Public License as published by the 12a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch * Free Software Foundation; either version 2 of the License, or (at your 13a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch * option) any later version. 14a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch */ 15a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 16a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch#include <linux/module.h> 17a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch#include <linux/moduleparam.h> 18a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch#include <linux/mm.h> 19a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch#include <linux/types.h> 20a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch#include <linux/kernel.h> 21a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch#include <linux/errno.h> 22a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch#include <linux/pci.h> 23a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch#include <linux/poll.h> 24a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch#include <linux/highmem.h> 25a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch#include <linux/interrupt.h> 26a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch#include <linux/pagemap.h> 27a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch#include <linux/device.h> 28a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch#include <linux/dma-mapping.h> 29a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch#include <linux/syscalls.h> 30400822fec46ce69d2ba7692689a1689653f7b847Martyn Welch#include <linux/mutex.h> 31a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch#include <linux/spinlock.h> 325a0e3ad6af8660be21ca98a971cd00f331318c05Tejun Heo#include <linux/slab.h> 33a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 34a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch#include "vme.h" 35a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch#include "vme_bridge.h" 36a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 37733e3ef0d364b7e6757a897e7f1862a70c89305aManohar Vanga/* Bitmask and list of registered buses both protected by common mutex */ 38a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welchstatic unsigned int vme_bus_numbers; 39733e3ef0d364b7e6757a897e7f1862a70c89305aManohar Vangastatic LIST_HEAD(vme_bus_list); 40733e3ef0d364b7e6757a897e7f1862a70c89305aManohar Vangastatic DEFINE_MUTEX(vme_buses_lock); 41a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 42ead1f3e301e2d886ef89f8d0c82b4d495f2a81c2Martyn Welchstatic void __exit vme_exit(void); 43ead1f3e301e2d886ef89f8d0c82b4d495f2a81c2Martyn Welchstatic int __init vme_init(void); 44a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 458f966dc444b11adff6011a1d1fce424abdd876d8Manohar Vangastatic struct vme_dev *dev_to_vme_dev(struct device *dev) 46a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch{ 478f966dc444b11adff6011a1d1fce424abdd876d8Manohar Vanga return container_of(dev, struct vme_dev, dev); 48a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch} 49a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 50a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch/* 51a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch * Find the bridge that the resource is associated with. 52a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch */ 53a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welchstatic struct vme_bridge *find_bridge(struct vme_resource *resource) 54a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch{ 55a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch /* Get list to search */ 56a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch switch (resource->type) { 57a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch case VME_MASTER: 58a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch return list_entry(resource->entry, struct vme_master_resource, 59a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch list)->parent; 60a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch break; 61a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch case VME_SLAVE: 62a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch return list_entry(resource->entry, struct vme_slave_resource, 63a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch list)->parent; 64a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch break; 65a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch case VME_DMA: 66a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch return list_entry(resource->entry, struct vme_dma_resource, 67a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch list)->parent; 68a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch break; 6942fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welch case VME_LM: 7042fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welch return list_entry(resource->entry, struct vme_lm_resource, 7142fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welch list)->parent; 7242fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welch break; 73a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch default: 74a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch printk(KERN_ERR "Unknown resource type\n"); 75a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch return NULL; 76a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch break; 77a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch } 78a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch} 79a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 80a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch/* 81a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch * Allocate a contiguous block of memory for use by the driver. This is used to 82a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch * create the buffers for the slave windows. 83a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch */ 84ead1f3e301e2d886ef89f8d0c82b4d495f2a81c2Martyn Welchvoid *vme_alloc_consistent(struct vme_resource *resource, size_t size, 85a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch dma_addr_t *dma) 86a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch{ 87a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch struct vme_bridge *bridge; 88a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 89ead1f3e301e2d886ef89f8d0c82b4d495f2a81c2Martyn Welch if (resource == NULL) { 90ead1f3e301e2d886ef89f8d0c82b4d495f2a81c2Martyn Welch printk(KERN_ERR "No resource\n"); 91a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch return NULL; 92a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch } 93a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 94a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch bridge = find_bridge(resource); 95ead1f3e301e2d886ef89f8d0c82b4d495f2a81c2Martyn Welch if (bridge == NULL) { 96ead1f3e301e2d886ef89f8d0c82b4d495f2a81c2Martyn Welch printk(KERN_ERR "Can't find bridge\n"); 97a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch return NULL; 98a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch } 99a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 100a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch if (bridge->parent == NULL) { 1017f58f0255aec0b933e0b26ef64d3d533c362a3d3Manohar Vanga printk(KERN_ERR "Dev entry NULL for" 1027f58f0255aec0b933e0b26ef64d3d533c362a3d3Manohar Vanga " bridge %s\n", bridge->name); 1037f58f0255aec0b933e0b26ef64d3d533c362a3d3Manohar Vanga return NULL; 1047f58f0255aec0b933e0b26ef64d3d533c362a3d3Manohar Vanga } 1057f58f0255aec0b933e0b26ef64d3d533c362a3d3Manohar Vanga 1067f58f0255aec0b933e0b26ef64d3d533c362a3d3Manohar Vanga if (bridge->alloc_consistent == NULL) { 1077f58f0255aec0b933e0b26ef64d3d533c362a3d3Manohar Vanga printk(KERN_ERR "alloc_consistent not supported by" 1087f58f0255aec0b933e0b26ef64d3d533c362a3d3Manohar Vanga " bridge %s\n", bridge->name); 109a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch return NULL; 110a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch } 111a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 1127f58f0255aec0b933e0b26ef64d3d533c362a3d3Manohar Vanga return bridge->alloc_consistent(bridge->parent, size, dma); 113a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch} 114a17a75e2666f7175baac838bc4b6d11324dca3efMartyn WelchEXPORT_SYMBOL(vme_alloc_consistent); 115a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 116a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch/* 117a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch * Free previously allocated contiguous block of memory. 118a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch */ 119a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welchvoid vme_free_consistent(struct vme_resource *resource, size_t size, 120a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch void *vaddr, dma_addr_t dma) 121a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch{ 122a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch struct vme_bridge *bridge; 123a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 124ead1f3e301e2d886ef89f8d0c82b4d495f2a81c2Martyn Welch if (resource == NULL) { 125ead1f3e301e2d886ef89f8d0c82b4d495f2a81c2Martyn Welch printk(KERN_ERR "No resource\n"); 126a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch return; 127a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch } 128a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 129a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch bridge = find_bridge(resource); 130ead1f3e301e2d886ef89f8d0c82b4d495f2a81c2Martyn Welch if (bridge == NULL) { 131ead1f3e301e2d886ef89f8d0c82b4d495f2a81c2Martyn Welch printk(KERN_ERR "Can't find bridge\n"); 132a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch return; 133a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch } 134a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 1357f58f0255aec0b933e0b26ef64d3d533c362a3d3Manohar Vanga if (bridge->parent == NULL) { 1367f58f0255aec0b933e0b26ef64d3d533c362a3d3Manohar Vanga printk(KERN_ERR "Dev entry NULL for" 1377f58f0255aec0b933e0b26ef64d3d533c362a3d3Manohar Vanga " bridge %s\n", bridge->name); 1387f58f0255aec0b933e0b26ef64d3d533c362a3d3Manohar Vanga return; 1397f58f0255aec0b933e0b26ef64d3d533c362a3d3Manohar Vanga } 1407f58f0255aec0b933e0b26ef64d3d533c362a3d3Manohar Vanga 1417f58f0255aec0b933e0b26ef64d3d533c362a3d3Manohar Vanga if (bridge->free_consistent == NULL) { 1427f58f0255aec0b933e0b26ef64d3d533c362a3d3Manohar Vanga printk(KERN_ERR "free_consistent not supported by" 1437f58f0255aec0b933e0b26ef64d3d533c362a3d3Manohar Vanga " bridge %s\n", bridge->name); 1447f58f0255aec0b933e0b26ef64d3d533c362a3d3Manohar Vanga return; 1457f58f0255aec0b933e0b26ef64d3d533c362a3d3Manohar Vanga } 146a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 1477f58f0255aec0b933e0b26ef64d3d533c362a3d3Manohar Vanga bridge->free_consistent(bridge->parent, size, vaddr, dma); 148a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch} 149a17a75e2666f7175baac838bc4b6d11324dca3efMartyn WelchEXPORT_SYMBOL(vme_free_consistent); 150a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 151a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welchsize_t vme_get_size(struct vme_resource *resource) 152a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch{ 153a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch int enabled, retval; 154a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch unsigned long long base, size; 155a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch dma_addr_t buf_base; 156a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch vme_address_t aspace; 157a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch vme_cycle_t cycle; 158a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch vme_width_t dwidth; 159a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 160a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch switch (resource->type) { 161a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch case VME_MASTER: 162a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch retval = vme_master_get(resource, &enabled, &base, &size, 163a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch &aspace, &cycle, &dwidth); 164a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 165a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch return size; 166a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch break; 167a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch case VME_SLAVE: 168a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch retval = vme_slave_get(resource, &enabled, &base, &size, 169a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch &buf_base, &aspace, &cycle); 170a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 171a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch return size; 172a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch break; 173a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch case VME_DMA: 174a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch return 0; 175a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch break; 176a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch default: 177a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch printk(KERN_ERR "Unknown resource type\n"); 178a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch return 0; 179a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch break; 180a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch } 181a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch} 182a17a75e2666f7175baac838bc4b6d11324dca3efMartyn WelchEXPORT_SYMBOL(vme_get_size); 183a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 184a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welchstatic int vme_check_window(vme_address_t aspace, unsigned long long vme_base, 185a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch unsigned long long size) 186a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch{ 187a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch int retval = 0; 188a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 189a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch switch (aspace) { 190a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch case VME_A16: 191a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch if (((vme_base + size) > VME_A16_MAX) || 192a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch (vme_base > VME_A16_MAX)) 193a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch retval = -EFAULT; 194a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch break; 195a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch case VME_A24: 196a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch if (((vme_base + size) > VME_A24_MAX) || 197a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch (vme_base > VME_A24_MAX)) 198a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch retval = -EFAULT; 199a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch break; 200a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch case VME_A32: 201a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch if (((vme_base + size) > VME_A32_MAX) || 202a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch (vme_base > VME_A32_MAX)) 203a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch retval = -EFAULT; 204a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch break; 205a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch case VME_A64: 206a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch /* 207a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch * Any value held in an unsigned long long can be used as the 208a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch * base 209a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch */ 210a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch break; 211a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch case VME_CRCSR: 212a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch if (((vme_base + size) > VME_CRCSR_MAX) || 213a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch (vme_base > VME_CRCSR_MAX)) 214a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch retval = -EFAULT; 215a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch break; 216a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch case VME_USER1: 217a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch case VME_USER2: 218a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch case VME_USER3: 219a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch case VME_USER4: 220a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch /* User Defined */ 221a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch break; 222a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch default: 223ead1f3e301e2d886ef89f8d0c82b4d495f2a81c2Martyn Welch printk(KERN_ERR "Invalid address space\n"); 224a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch retval = -EINVAL; 225a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch break; 226a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch } 227a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 228a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch return retval; 229a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch} 230a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 231a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch/* 232a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch * Request a slave image with specific attributes, return some unique 233a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch * identifier. 234a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch */ 2358f966dc444b11adff6011a1d1fce424abdd876d8Manohar Vangastruct vme_resource *vme_slave_request(struct vme_dev *vdev, 236a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch vme_address_t address, vme_cycle_t cycle) 237a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch{ 238a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch struct vme_bridge *bridge; 239a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch struct list_head *slave_pos = NULL; 240a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch struct vme_slave_resource *allocated_image = NULL; 241a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch struct vme_slave_resource *slave_image = NULL; 242a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch struct vme_resource *resource = NULL; 243a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 2448f966dc444b11adff6011a1d1fce424abdd876d8Manohar Vanga bridge = vdev->bridge; 245a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch if (bridge == NULL) { 246a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch printk(KERN_ERR "Can't find VME bus\n"); 247a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch goto err_bus; 248a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch } 249a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 250a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch /* Loop through slave resources */ 251886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota list_for_each(slave_pos, &bridge->slave_resources) { 252a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch slave_image = list_entry(slave_pos, 253a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch struct vme_slave_resource, list); 254a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 255a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch if (slave_image == NULL) { 256ead1f3e301e2d886ef89f8d0c82b4d495f2a81c2Martyn Welch printk(KERN_ERR "Registered NULL Slave resource\n"); 257a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch continue; 258a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch } 259a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 260a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch /* Find an unlocked and compatible image */ 261886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota mutex_lock(&slave_image->mtx); 262ead1f3e301e2d886ef89f8d0c82b4d495f2a81c2Martyn Welch if (((slave_image->address_attr & address) == address) && 263a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch ((slave_image->cycle_attr & cycle) == cycle) && 264a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch (slave_image->locked == 0)) { 265a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 266a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch slave_image->locked = 1; 267886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota mutex_unlock(&slave_image->mtx); 268a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch allocated_image = slave_image; 269a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch break; 270a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch } 271886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota mutex_unlock(&slave_image->mtx); 272a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch } 273a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 274a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch /* No free image */ 275a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch if (allocated_image == NULL) 276a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch goto err_image; 277a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 278a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch resource = kmalloc(sizeof(struct vme_resource), GFP_KERNEL); 279a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch if (resource == NULL) { 280a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch printk(KERN_WARNING "Unable to allocate resource structure\n"); 281a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch goto err_alloc; 282a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch } 283a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch resource->type = VME_SLAVE; 284886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota resource->entry = &allocated_image->list; 285a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 286a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch return resource; 287a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 288a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welcherr_alloc: 289a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch /* Unlock image */ 290886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota mutex_lock(&slave_image->mtx); 291a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch slave_image->locked = 0; 292886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota mutex_unlock(&slave_image->mtx); 293a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welcherr_image: 294a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welcherr_bus: 295a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch return NULL; 296a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch} 297a17a75e2666f7175baac838bc4b6d11324dca3efMartyn WelchEXPORT_SYMBOL(vme_slave_request); 298a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 299ead1f3e301e2d886ef89f8d0c82b4d495f2a81c2Martyn Welchint vme_slave_set(struct vme_resource *resource, int enabled, 300a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch unsigned long long vme_base, unsigned long long size, 301a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch dma_addr_t buf_base, vme_address_t aspace, vme_cycle_t cycle) 302a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch{ 303a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch struct vme_bridge *bridge = find_bridge(resource); 304a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch struct vme_slave_resource *image; 305a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch int retval; 306a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 307a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch if (resource->type != VME_SLAVE) { 308ead1f3e301e2d886ef89f8d0c82b4d495f2a81c2Martyn Welch printk(KERN_ERR "Not a slave resource\n"); 309a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch return -EINVAL; 310a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch } 311a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 312a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch image = list_entry(resource->entry, struct vme_slave_resource, list); 313a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 314a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch if (bridge->slave_set == NULL) { 315ead1f3e301e2d886ef89f8d0c82b4d495f2a81c2Martyn Welch printk(KERN_ERR "Function not supported\n"); 316a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch return -ENOSYS; 317a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch } 318a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 319ead1f3e301e2d886ef89f8d0c82b4d495f2a81c2Martyn Welch if (!(((image->address_attr & aspace) == aspace) && 320a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch ((image->cycle_attr & cycle) == cycle))) { 321ead1f3e301e2d886ef89f8d0c82b4d495f2a81c2Martyn Welch printk(KERN_ERR "Invalid attributes\n"); 322a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch return -EINVAL; 323a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch } 324a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 325a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch retval = vme_check_window(aspace, vme_base, size); 326ead1f3e301e2d886ef89f8d0c82b4d495f2a81c2Martyn Welch if (retval) 327a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch return retval; 328a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 329a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch return bridge->slave_set(image, enabled, vme_base, size, buf_base, 330a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch aspace, cycle); 331a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch} 332a17a75e2666f7175baac838bc4b6d11324dca3efMartyn WelchEXPORT_SYMBOL(vme_slave_set); 333a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 334ead1f3e301e2d886ef89f8d0c82b4d495f2a81c2Martyn Welchint vme_slave_get(struct vme_resource *resource, int *enabled, 335a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch unsigned long long *vme_base, unsigned long long *size, 336a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch dma_addr_t *buf_base, vme_address_t *aspace, vme_cycle_t *cycle) 337a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch{ 338a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch struct vme_bridge *bridge = find_bridge(resource); 339a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch struct vme_slave_resource *image; 340a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 341a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch if (resource->type != VME_SLAVE) { 342ead1f3e301e2d886ef89f8d0c82b4d495f2a81c2Martyn Welch printk(KERN_ERR "Not a slave resource\n"); 343a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch return -EINVAL; 344a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch } 345a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 346a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch image = list_entry(resource->entry, struct vme_slave_resource, list); 347a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 34851a569f757f233bcffbffcdfeeff510916991a55Emilio G. Cota if (bridge->slave_get == NULL) { 349ead1f3e301e2d886ef89f8d0c82b4d495f2a81c2Martyn Welch printk(KERN_ERR "vme_slave_get not supported\n"); 350a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch return -EINVAL; 351a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch } 352a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 353a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch return bridge->slave_get(image, enabled, vme_base, size, buf_base, 354a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch aspace, cycle); 355a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch} 356a17a75e2666f7175baac838bc4b6d11324dca3efMartyn WelchEXPORT_SYMBOL(vme_slave_get); 357a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 358a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welchvoid vme_slave_free(struct vme_resource *resource) 359a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch{ 360a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch struct vme_slave_resource *slave_image; 361a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 362a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch if (resource->type != VME_SLAVE) { 363ead1f3e301e2d886ef89f8d0c82b4d495f2a81c2Martyn Welch printk(KERN_ERR "Not a slave resource\n"); 364a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch return; 365a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch } 366a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 367a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch slave_image = list_entry(resource->entry, struct vme_slave_resource, 368a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch list); 369a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch if (slave_image == NULL) { 370ead1f3e301e2d886ef89f8d0c82b4d495f2a81c2Martyn Welch printk(KERN_ERR "Can't find slave resource\n"); 371a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch return; 372a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch } 373a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 374a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch /* Unlock image */ 375886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota mutex_lock(&slave_image->mtx); 376a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch if (slave_image->locked == 0) 377a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch printk(KERN_ERR "Image is already free\n"); 378a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 379a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch slave_image->locked = 0; 380886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota mutex_unlock(&slave_image->mtx); 381a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 382a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch /* Free up resource memory */ 383a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch kfree(resource); 384a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch} 385a17a75e2666f7175baac838bc4b6d11324dca3efMartyn WelchEXPORT_SYMBOL(vme_slave_free); 386a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 387a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch/* 388a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch * Request a master image with specific attributes, return some unique 389a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch * identifier. 390a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch */ 3918f966dc444b11adff6011a1d1fce424abdd876d8Manohar Vangastruct vme_resource *vme_master_request(struct vme_dev *vdev, 392a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch vme_address_t address, vme_cycle_t cycle, vme_width_t dwidth) 393a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch{ 394a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch struct vme_bridge *bridge; 395a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch struct list_head *master_pos = NULL; 396a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch struct vme_master_resource *allocated_image = NULL; 397a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch struct vme_master_resource *master_image = NULL; 398a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch struct vme_resource *resource = NULL; 399a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 4008f966dc444b11adff6011a1d1fce424abdd876d8Manohar Vanga bridge = vdev->bridge; 401a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch if (bridge == NULL) { 402a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch printk(KERN_ERR "Can't find VME bus\n"); 403a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch goto err_bus; 404a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch } 405a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 406a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch /* Loop through master resources */ 407886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota list_for_each(master_pos, &bridge->master_resources) { 408a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch master_image = list_entry(master_pos, 409a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch struct vme_master_resource, list); 410a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 411a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch if (master_image == NULL) { 412a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch printk(KERN_WARNING "Registered NULL master resource\n"); 413a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch continue; 414a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch } 415a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 416a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch /* Find an unlocked and compatible image */ 417886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota spin_lock(&master_image->lock); 418ead1f3e301e2d886ef89f8d0c82b4d495f2a81c2Martyn Welch if (((master_image->address_attr & address) == address) && 419a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch ((master_image->cycle_attr & cycle) == cycle) && 420a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch ((master_image->width_attr & dwidth) == dwidth) && 421a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch (master_image->locked == 0)) { 422a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 423a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch master_image->locked = 1; 424886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota spin_unlock(&master_image->lock); 425a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch allocated_image = master_image; 426a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch break; 427a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch } 428886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota spin_unlock(&master_image->lock); 429a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch } 430a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 431a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch /* Check to see if we found a resource */ 432a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch if (allocated_image == NULL) { 433a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch printk(KERN_ERR "Can't find a suitable resource\n"); 434a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch goto err_image; 435a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch } 436a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 437a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch resource = kmalloc(sizeof(struct vme_resource), GFP_KERNEL); 438a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch if (resource == NULL) { 439a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch printk(KERN_ERR "Unable to allocate resource structure\n"); 440a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch goto err_alloc; 441a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch } 442a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch resource->type = VME_MASTER; 443886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota resource->entry = &allocated_image->list; 444a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 445a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch return resource; 446a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 447a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welcherr_alloc: 448a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch /* Unlock image */ 449886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota spin_lock(&master_image->lock); 450a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch master_image->locked = 0; 451886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota spin_unlock(&master_image->lock); 452a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welcherr_image: 453a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welcherr_bus: 454a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch return NULL; 455a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch} 456a17a75e2666f7175baac838bc4b6d11324dca3efMartyn WelchEXPORT_SYMBOL(vme_master_request); 457a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 458ead1f3e301e2d886ef89f8d0c82b4d495f2a81c2Martyn Welchint vme_master_set(struct vme_resource *resource, int enabled, 459a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch unsigned long long vme_base, unsigned long long size, 460a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch vme_address_t aspace, vme_cycle_t cycle, vme_width_t dwidth) 461a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch{ 462a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch struct vme_bridge *bridge = find_bridge(resource); 463a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch struct vme_master_resource *image; 464a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch int retval; 465a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 466a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch if (resource->type != VME_MASTER) { 467ead1f3e301e2d886ef89f8d0c82b4d495f2a81c2Martyn Welch printk(KERN_ERR "Not a master resource\n"); 468a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch return -EINVAL; 469a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch } 470a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 471a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch image = list_entry(resource->entry, struct vme_master_resource, list); 472a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 473a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch if (bridge->master_set == NULL) { 474ead1f3e301e2d886ef89f8d0c82b4d495f2a81c2Martyn Welch printk(KERN_WARNING "vme_master_set not supported\n"); 475a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch return -EINVAL; 476a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch } 477a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 478ead1f3e301e2d886ef89f8d0c82b4d495f2a81c2Martyn Welch if (!(((image->address_attr & aspace) == aspace) && 479a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch ((image->cycle_attr & cycle) == cycle) && 480a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch ((image->width_attr & dwidth) == dwidth))) { 481ead1f3e301e2d886ef89f8d0c82b4d495f2a81c2Martyn Welch printk(KERN_WARNING "Invalid attributes\n"); 482a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch return -EINVAL; 483a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch } 484a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 485a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch retval = vme_check_window(aspace, vme_base, size); 486ead1f3e301e2d886ef89f8d0c82b4d495f2a81c2Martyn Welch if (retval) 487a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch return retval; 488a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 489a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch return bridge->master_set(image, enabled, vme_base, size, aspace, 490a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch cycle, dwidth); 491a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch} 492a17a75e2666f7175baac838bc4b6d11324dca3efMartyn WelchEXPORT_SYMBOL(vme_master_set); 493a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 494ead1f3e301e2d886ef89f8d0c82b4d495f2a81c2Martyn Welchint vme_master_get(struct vme_resource *resource, int *enabled, 495a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch unsigned long long *vme_base, unsigned long long *size, 496a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch vme_address_t *aspace, vme_cycle_t *cycle, vme_width_t *dwidth) 497a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch{ 498a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch struct vme_bridge *bridge = find_bridge(resource); 499a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch struct vme_master_resource *image; 500a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 501a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch if (resource->type != VME_MASTER) { 502ead1f3e301e2d886ef89f8d0c82b4d495f2a81c2Martyn Welch printk(KERN_ERR "Not a master resource\n"); 503a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch return -EINVAL; 504a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch } 505a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 506a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch image = list_entry(resource->entry, struct vme_master_resource, list); 507a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 50851a569f757f233bcffbffcdfeeff510916991a55Emilio G. Cota if (bridge->master_get == NULL) { 509ead1f3e301e2d886ef89f8d0c82b4d495f2a81c2Martyn Welch printk(KERN_WARNING "vme_master_set not supported\n"); 510a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch return -EINVAL; 511a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch } 512a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 513a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch return bridge->master_get(image, enabled, vme_base, size, aspace, 514a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch cycle, dwidth); 515a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch} 516a17a75e2666f7175baac838bc4b6d11324dca3efMartyn WelchEXPORT_SYMBOL(vme_master_get); 517a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 518a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch/* 519a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch * Read data out of VME space into a buffer. 520a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch */ 521ead1f3e301e2d886ef89f8d0c82b4d495f2a81c2Martyn Welchssize_t vme_master_read(struct vme_resource *resource, void *buf, size_t count, 522a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch loff_t offset) 523a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch{ 524a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch struct vme_bridge *bridge = find_bridge(resource); 525a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch struct vme_master_resource *image; 526a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch size_t length; 527a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 528a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch if (bridge->master_read == NULL) { 529ead1f3e301e2d886ef89f8d0c82b4d495f2a81c2Martyn Welch printk(KERN_WARNING "Reading from resource not supported\n"); 530a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch return -EINVAL; 531a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch } 532a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 533a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch if (resource->type != VME_MASTER) { 534ead1f3e301e2d886ef89f8d0c82b4d495f2a81c2Martyn Welch printk(KERN_ERR "Not a master resource\n"); 535a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch return -EINVAL; 536a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch } 537a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 538a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch image = list_entry(resource->entry, struct vme_master_resource, list); 539a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 540a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch length = vme_get_size(resource); 541a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 542a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch if (offset > length) { 543ead1f3e301e2d886ef89f8d0c82b4d495f2a81c2Martyn Welch printk(KERN_WARNING "Invalid Offset\n"); 544a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch return -EFAULT; 545a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch } 546a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 547a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch if ((offset + count) > length) 548a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch count = length - offset; 549a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 550a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch return bridge->master_read(image, buf, count, offset); 551a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 552a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch} 553a17a75e2666f7175baac838bc4b6d11324dca3efMartyn WelchEXPORT_SYMBOL(vme_master_read); 554a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 555a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch/* 556a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch * Write data out to VME space from a buffer. 557a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch */ 558ead1f3e301e2d886ef89f8d0c82b4d495f2a81c2Martyn Welchssize_t vme_master_write(struct vme_resource *resource, void *buf, 559a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch size_t count, loff_t offset) 560a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch{ 561a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch struct vme_bridge *bridge = find_bridge(resource); 562a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch struct vme_master_resource *image; 563a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch size_t length; 564a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 565a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch if (bridge->master_write == NULL) { 566ead1f3e301e2d886ef89f8d0c82b4d495f2a81c2Martyn Welch printk(KERN_WARNING "Writing to resource not supported\n"); 567a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch return -EINVAL; 568a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch } 569a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 570a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch if (resource->type != VME_MASTER) { 571ead1f3e301e2d886ef89f8d0c82b4d495f2a81c2Martyn Welch printk(KERN_ERR "Not a master resource\n"); 572a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch return -EINVAL; 573a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch } 574a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 575a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch image = list_entry(resource->entry, struct vme_master_resource, list); 576a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 577a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch length = vme_get_size(resource); 578a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 579a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch if (offset > length) { 580ead1f3e301e2d886ef89f8d0c82b4d495f2a81c2Martyn Welch printk(KERN_WARNING "Invalid Offset\n"); 581a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch return -EFAULT; 582a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch } 583a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 584a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch if ((offset + count) > length) 585a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch count = length - offset; 586a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 587a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch return bridge->master_write(image, buf, count, offset); 588a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch} 589a17a75e2666f7175baac838bc4b6d11324dca3efMartyn WelchEXPORT_SYMBOL(vme_master_write); 590a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 591a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch/* 592a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch * Perform RMW cycle to provided location. 593a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch */ 594ead1f3e301e2d886ef89f8d0c82b4d495f2a81c2Martyn Welchunsigned int vme_master_rmw(struct vme_resource *resource, unsigned int mask, 595a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch unsigned int compare, unsigned int swap, loff_t offset) 596a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch{ 597a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch struct vme_bridge *bridge = find_bridge(resource); 598a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch struct vme_master_resource *image; 599a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 600a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch if (bridge->master_rmw == NULL) { 601ead1f3e301e2d886ef89f8d0c82b4d495f2a81c2Martyn Welch printk(KERN_WARNING "Writing to resource not supported\n"); 602a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch return -EINVAL; 603a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch } 604a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 605a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch if (resource->type != VME_MASTER) { 606ead1f3e301e2d886ef89f8d0c82b4d495f2a81c2Martyn Welch printk(KERN_ERR "Not a master resource\n"); 607a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch return -EINVAL; 608a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch } 609a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 610a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch image = list_entry(resource->entry, struct vme_master_resource, list); 611a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 612a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch return bridge->master_rmw(image, mask, compare, swap, offset); 613a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch} 614a17a75e2666f7175baac838bc4b6d11324dca3efMartyn WelchEXPORT_SYMBOL(vme_master_rmw); 615a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 616a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welchvoid vme_master_free(struct vme_resource *resource) 617a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch{ 618a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch struct vme_master_resource *master_image; 619a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 620a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch if (resource->type != VME_MASTER) { 621ead1f3e301e2d886ef89f8d0c82b4d495f2a81c2Martyn Welch printk(KERN_ERR "Not a master resource\n"); 622a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch return; 623a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch } 624a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 625a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch master_image = list_entry(resource->entry, struct vme_master_resource, 626a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch list); 627a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch if (master_image == NULL) { 628ead1f3e301e2d886ef89f8d0c82b4d495f2a81c2Martyn Welch printk(KERN_ERR "Can't find master resource\n"); 629a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch return; 630a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch } 631a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 632a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch /* Unlock image */ 633886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota spin_lock(&master_image->lock); 634a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch if (master_image->locked == 0) 635a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch printk(KERN_ERR "Image is already free\n"); 636a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 637a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch master_image->locked = 0; 638886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota spin_unlock(&master_image->lock); 639a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 640a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch /* Free up resource memory */ 641a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch kfree(resource); 642a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch} 643a17a75e2666f7175baac838bc4b6d11324dca3efMartyn WelchEXPORT_SYMBOL(vme_master_free); 644a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 645a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch/* 646a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch * Request a DMA controller with specific attributes, return some unique 647a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch * identifier. 648a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch */ 6498f966dc444b11adff6011a1d1fce424abdd876d8Manohar Vangastruct vme_resource *vme_dma_request(struct vme_dev *vdev, 6508f966dc444b11adff6011a1d1fce424abdd876d8Manohar Vanga vme_dma_route_t route) 651a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch{ 652a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch struct vme_bridge *bridge; 653a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch struct list_head *dma_pos = NULL; 654a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch struct vme_dma_resource *allocated_ctrlr = NULL; 655a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch struct vme_dma_resource *dma_ctrlr = NULL; 656a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch struct vme_resource *resource = NULL; 657a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 658a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch /* XXX Not checking resource attributes */ 659a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch printk(KERN_ERR "No VME resource Attribute tests done\n"); 660a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 6618f966dc444b11adff6011a1d1fce424abdd876d8Manohar Vanga bridge = vdev->bridge; 662a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch if (bridge == NULL) { 663a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch printk(KERN_ERR "Can't find VME bus\n"); 664a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch goto err_bus; 665a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch } 666a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 667a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch /* Loop through DMA resources */ 668886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota list_for_each(dma_pos, &bridge->dma_resources) { 669a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch dma_ctrlr = list_entry(dma_pos, 670a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch struct vme_dma_resource, list); 671a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 672a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch if (dma_ctrlr == NULL) { 673ead1f3e301e2d886ef89f8d0c82b4d495f2a81c2Martyn Welch printk(KERN_ERR "Registered NULL DMA resource\n"); 674a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch continue; 675a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch } 676a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 6774f723df45d3952c485ee0125fb6797ad615901c3Martyn Welch /* Find an unlocked and compatible controller */ 678886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota mutex_lock(&dma_ctrlr->mtx); 6794f723df45d3952c485ee0125fb6797ad615901c3Martyn Welch if (((dma_ctrlr->route_attr & route) == route) && 6804f723df45d3952c485ee0125fb6797ad615901c3Martyn Welch (dma_ctrlr->locked == 0)) { 6814f723df45d3952c485ee0125fb6797ad615901c3Martyn Welch 682a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch dma_ctrlr->locked = 1; 683886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota mutex_unlock(&dma_ctrlr->mtx); 684a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch allocated_ctrlr = dma_ctrlr; 685a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch break; 686a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch } 687886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota mutex_unlock(&dma_ctrlr->mtx); 688a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch } 689a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 690a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch /* Check to see if we found a resource */ 691a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch if (allocated_ctrlr == NULL) 692a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch goto err_ctrlr; 693a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 694a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch resource = kmalloc(sizeof(struct vme_resource), GFP_KERNEL); 695a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch if (resource == NULL) { 696a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch printk(KERN_WARNING "Unable to allocate resource structure\n"); 697a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch goto err_alloc; 698a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch } 699a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch resource->type = VME_DMA; 700886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota resource->entry = &allocated_ctrlr->list; 701a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 702a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch return resource; 703a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 704a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welcherr_alloc: 705a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch /* Unlock image */ 706886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota mutex_lock(&dma_ctrlr->mtx); 707a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch dma_ctrlr->locked = 0; 708886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota mutex_unlock(&dma_ctrlr->mtx); 709a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welcherr_ctrlr: 710a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welcherr_bus: 711a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch return NULL; 712a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch} 71358e507987b285f3df99f839c79da3985555ac220Martyn WelchEXPORT_SYMBOL(vme_dma_request); 714a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 715a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch/* 716a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch * Start new list 717a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch */ 718a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welchstruct vme_dma_list *vme_new_dma_list(struct vme_resource *resource) 719a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch{ 720a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch struct vme_dma_resource *ctrlr; 721a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch struct vme_dma_list *dma_list; 722a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 723a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch if (resource->type != VME_DMA) { 724ead1f3e301e2d886ef89f8d0c82b4d495f2a81c2Martyn Welch printk(KERN_ERR "Not a DMA resource\n"); 725a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch return NULL; 726a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch } 727a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 728a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch ctrlr = list_entry(resource->entry, struct vme_dma_resource, list); 729a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 730ead1f3e301e2d886ef89f8d0c82b4d495f2a81c2Martyn Welch dma_list = kmalloc(sizeof(struct vme_dma_list), GFP_KERNEL); 731ead1f3e301e2d886ef89f8d0c82b4d495f2a81c2Martyn Welch if (dma_list == NULL) { 732ead1f3e301e2d886ef89f8d0c82b4d495f2a81c2Martyn Welch printk(KERN_ERR "Unable to allocate memory for new dma list\n"); 733a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch return NULL; 734a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch } 735886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota INIT_LIST_HEAD(&dma_list->entries); 736a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch dma_list->parent = ctrlr; 737886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota mutex_init(&dma_list->mtx); 738a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 739a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch return dma_list; 740a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch} 741a17a75e2666f7175baac838bc4b6d11324dca3efMartyn WelchEXPORT_SYMBOL(vme_new_dma_list); 742a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 743a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch/* 744a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch * Create "Pattern" type attributes 745a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch */ 746a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welchstruct vme_dma_attr *vme_dma_pattern_attribute(u32 pattern, 747a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch vme_pattern_t type) 748a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch{ 749a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch struct vme_dma_attr *attributes; 750a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch struct vme_dma_pattern *pattern_attr; 751a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 752ead1f3e301e2d886ef89f8d0c82b4d495f2a81c2Martyn Welch attributes = kmalloc(sizeof(struct vme_dma_attr), GFP_KERNEL); 753ead1f3e301e2d886ef89f8d0c82b4d495f2a81c2Martyn Welch if (attributes == NULL) { 754ead1f3e301e2d886ef89f8d0c82b4d495f2a81c2Martyn Welch printk(KERN_ERR "Unable to allocate memory for attributes " 755ead1f3e301e2d886ef89f8d0c82b4d495f2a81c2Martyn Welch "structure\n"); 756a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch goto err_attr; 757a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch } 758a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 759ead1f3e301e2d886ef89f8d0c82b4d495f2a81c2Martyn Welch pattern_attr = kmalloc(sizeof(struct vme_dma_pattern), GFP_KERNEL); 760ead1f3e301e2d886ef89f8d0c82b4d495f2a81c2Martyn Welch if (pattern_attr == NULL) { 761ead1f3e301e2d886ef89f8d0c82b4d495f2a81c2Martyn Welch printk(KERN_ERR "Unable to allocate memory for pattern " 762ead1f3e301e2d886ef89f8d0c82b4d495f2a81c2Martyn Welch "attributes\n"); 763a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch goto err_pat; 764a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch } 765a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 766a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch attributes->type = VME_DMA_PATTERN; 767a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch attributes->private = (void *)pattern_attr; 768a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 769a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch pattern_attr->pattern = pattern; 770a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch pattern_attr->type = type; 771a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 772a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch return attributes; 773a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 774a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welcherr_pat: 775a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch kfree(attributes); 776a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welcherr_attr: 777a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch return NULL; 778a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch} 779a17a75e2666f7175baac838bc4b6d11324dca3efMartyn WelchEXPORT_SYMBOL(vme_dma_pattern_attribute); 780a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 781a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch/* 782a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch * Create "PCI" type attributes 783a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch */ 784a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welchstruct vme_dma_attr *vme_dma_pci_attribute(dma_addr_t address) 785a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch{ 786a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch struct vme_dma_attr *attributes; 787a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch struct vme_dma_pci *pci_attr; 788a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 789a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch /* XXX Run some sanity checks here */ 790a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 791ead1f3e301e2d886ef89f8d0c82b4d495f2a81c2Martyn Welch attributes = kmalloc(sizeof(struct vme_dma_attr), GFP_KERNEL); 792ead1f3e301e2d886ef89f8d0c82b4d495f2a81c2Martyn Welch if (attributes == NULL) { 793ead1f3e301e2d886ef89f8d0c82b4d495f2a81c2Martyn Welch printk(KERN_ERR "Unable to allocate memory for attributes " 794ead1f3e301e2d886ef89f8d0c82b4d495f2a81c2Martyn Welch "structure\n"); 795a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch goto err_attr; 796a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch } 797a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 798ead1f3e301e2d886ef89f8d0c82b4d495f2a81c2Martyn Welch pci_attr = kmalloc(sizeof(struct vme_dma_pci), GFP_KERNEL); 799ead1f3e301e2d886ef89f8d0c82b4d495f2a81c2Martyn Welch if (pci_attr == NULL) { 800ead1f3e301e2d886ef89f8d0c82b4d495f2a81c2Martyn Welch printk(KERN_ERR "Unable to allocate memory for pci " 801ead1f3e301e2d886ef89f8d0c82b4d495f2a81c2Martyn Welch "attributes\n"); 802a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch goto err_pci; 803a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch } 804a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 805a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 806a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 807a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch attributes->type = VME_DMA_PCI; 808a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch attributes->private = (void *)pci_attr; 809a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 810a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch pci_attr->address = address; 811a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 812a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch return attributes; 813a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 814a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welcherr_pci: 815a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch kfree(attributes); 816a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welcherr_attr: 817a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch return NULL; 818a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch} 819a17a75e2666f7175baac838bc4b6d11324dca3efMartyn WelchEXPORT_SYMBOL(vme_dma_pci_attribute); 820a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 821a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch/* 822a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch * Create "VME" type attributes 823a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch */ 824a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welchstruct vme_dma_attr *vme_dma_vme_attribute(unsigned long long address, 825a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch vme_address_t aspace, vme_cycle_t cycle, vme_width_t dwidth) 826a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch{ 827a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch struct vme_dma_attr *attributes; 828a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch struct vme_dma_vme *vme_attr; 829a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 830ead1f3e301e2d886ef89f8d0c82b4d495f2a81c2Martyn Welch attributes = kmalloc( 831a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch sizeof(struct vme_dma_attr), GFP_KERNEL); 832ead1f3e301e2d886ef89f8d0c82b4d495f2a81c2Martyn Welch if (attributes == NULL) { 833ead1f3e301e2d886ef89f8d0c82b4d495f2a81c2Martyn Welch printk(KERN_ERR "Unable to allocate memory for attributes " 834ead1f3e301e2d886ef89f8d0c82b4d495f2a81c2Martyn Welch "structure\n"); 835a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch goto err_attr; 836a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch } 837a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 838ead1f3e301e2d886ef89f8d0c82b4d495f2a81c2Martyn Welch vme_attr = kmalloc(sizeof(struct vme_dma_vme), GFP_KERNEL); 839ead1f3e301e2d886ef89f8d0c82b4d495f2a81c2Martyn Welch if (vme_attr == NULL) { 840ead1f3e301e2d886ef89f8d0c82b4d495f2a81c2Martyn Welch printk(KERN_ERR "Unable to allocate memory for vme " 841ead1f3e301e2d886ef89f8d0c82b4d495f2a81c2Martyn Welch "attributes\n"); 842a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch goto err_vme; 843a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch } 844a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 845a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch attributes->type = VME_DMA_VME; 846a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch attributes->private = (void *)vme_attr; 847a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 848a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch vme_attr->address = address; 849a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch vme_attr->aspace = aspace; 850a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch vme_attr->cycle = cycle; 851a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch vme_attr->dwidth = dwidth; 852a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 853a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch return attributes; 854a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 855a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welcherr_vme: 856a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch kfree(attributes); 857a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welcherr_attr: 858a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch return NULL; 859a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch} 860a17a75e2666f7175baac838bc4b6d11324dca3efMartyn WelchEXPORT_SYMBOL(vme_dma_vme_attribute); 861a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 862a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch/* 863a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch * Free attribute 864a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch */ 865a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welchvoid vme_dma_free_attribute(struct vme_dma_attr *attributes) 866a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch{ 867a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch kfree(attributes->private); 868a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch kfree(attributes); 869a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch} 870a17a75e2666f7175baac838bc4b6d11324dca3efMartyn WelchEXPORT_SYMBOL(vme_dma_free_attribute); 871a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 872a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welchint vme_dma_list_add(struct vme_dma_list *list, struct vme_dma_attr *src, 873a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch struct vme_dma_attr *dest, size_t count) 874a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch{ 875a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch struct vme_bridge *bridge = list->parent->parent; 876a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch int retval; 877a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 878a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch if (bridge->dma_list_add == NULL) { 879ead1f3e301e2d886ef89f8d0c82b4d495f2a81c2Martyn Welch printk(KERN_WARNING "Link List DMA generation not supported\n"); 880a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch return -EINVAL; 881a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch } 882a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 883886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota if (!mutex_trylock(&list->mtx)) { 884ead1f3e301e2d886ef89f8d0c82b4d495f2a81c2Martyn Welch printk(KERN_ERR "Link List already submitted\n"); 885a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch return -EINVAL; 886a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch } 887a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 888a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch retval = bridge->dma_list_add(list, src, dest, count); 889a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 890886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota mutex_unlock(&list->mtx); 891a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 892a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch return retval; 893a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch} 894a17a75e2666f7175baac838bc4b6d11324dca3efMartyn WelchEXPORT_SYMBOL(vme_dma_list_add); 895a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 896a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welchint vme_dma_list_exec(struct vme_dma_list *list) 897a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch{ 898a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch struct vme_bridge *bridge = list->parent->parent; 899a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch int retval; 900a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 901a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch if (bridge->dma_list_exec == NULL) { 902ead1f3e301e2d886ef89f8d0c82b4d495f2a81c2Martyn Welch printk(KERN_ERR "Link List DMA execution not supported\n"); 903a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch return -EINVAL; 904a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch } 905a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 906886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota mutex_lock(&list->mtx); 907a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 908a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch retval = bridge->dma_list_exec(list); 909a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 910886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota mutex_unlock(&list->mtx); 911a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 912a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch return retval; 913a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch} 914a17a75e2666f7175baac838bc4b6d11324dca3efMartyn WelchEXPORT_SYMBOL(vme_dma_list_exec); 915a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 916a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welchint vme_dma_list_free(struct vme_dma_list *list) 917a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch{ 918a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch struct vme_bridge *bridge = list->parent->parent; 919a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch int retval; 920a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 921a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch if (bridge->dma_list_empty == NULL) { 922ead1f3e301e2d886ef89f8d0c82b4d495f2a81c2Martyn Welch printk(KERN_WARNING "Emptying of Link Lists not supported\n"); 923a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch return -EINVAL; 924a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch } 925a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 926886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota if (!mutex_trylock(&list->mtx)) { 927ead1f3e301e2d886ef89f8d0c82b4d495f2a81c2Martyn Welch printk(KERN_ERR "Link List in use\n"); 928a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch return -EINVAL; 929a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch } 930a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 931a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch /* 932a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch * Empty out all of the entries from the dma list. We need to go to the 933a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch * low level driver as dma entries are driver specific. 934a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch */ 935a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch retval = bridge->dma_list_empty(list); 936a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch if (retval) { 937ead1f3e301e2d886ef89f8d0c82b4d495f2a81c2Martyn Welch printk(KERN_ERR "Unable to empty link-list entries\n"); 938886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota mutex_unlock(&list->mtx); 939a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch return retval; 940a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch } 941886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota mutex_unlock(&list->mtx); 942a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch kfree(list); 943a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 944a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch return retval; 945a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch} 946a17a75e2666f7175baac838bc4b6d11324dca3efMartyn WelchEXPORT_SYMBOL(vme_dma_list_free); 947a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 948a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welchint vme_dma_free(struct vme_resource *resource) 949a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch{ 950a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch struct vme_dma_resource *ctrlr; 951a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 952a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch if (resource->type != VME_DMA) { 953ead1f3e301e2d886ef89f8d0c82b4d495f2a81c2Martyn Welch printk(KERN_ERR "Not a DMA resource\n"); 954a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch return -EINVAL; 955a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch } 956a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 957a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch ctrlr = list_entry(resource->entry, struct vme_dma_resource, list); 958a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 959886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota if (!mutex_trylock(&ctrlr->mtx)) { 960ead1f3e301e2d886ef89f8d0c82b4d495f2a81c2Martyn Welch printk(KERN_ERR "Resource busy, can't free\n"); 961a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch return -EBUSY; 962a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch } 963a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 964886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota if (!(list_empty(&ctrlr->pending) && list_empty(&ctrlr->running))) { 965ead1f3e301e2d886ef89f8d0c82b4d495f2a81c2Martyn Welch printk(KERN_WARNING "Resource still processing transfers\n"); 966886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota mutex_unlock(&ctrlr->mtx); 967a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch return -EBUSY; 968a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch } 969a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 970a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch ctrlr->locked = 0; 971a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 972886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota mutex_unlock(&ctrlr->mtx); 973a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 974a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch return 0; 975a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch} 976a17a75e2666f7175baac838bc4b6d11324dca3efMartyn WelchEXPORT_SYMBOL(vme_dma_free); 977a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 978c813f592a5e65cfd9321f51c95a6977e9518dde6Martyn Welchvoid vme_irq_handler(struct vme_bridge *bridge, int level, int statid) 979c813f592a5e65cfd9321f51c95a6977e9518dde6Martyn Welch{ 980c813f592a5e65cfd9321f51c95a6977e9518dde6Martyn Welch void (*call)(int, int, void *); 981c813f592a5e65cfd9321f51c95a6977e9518dde6Martyn Welch void *priv_data; 982c813f592a5e65cfd9321f51c95a6977e9518dde6Martyn Welch 983c813f592a5e65cfd9321f51c95a6977e9518dde6Martyn Welch call = bridge->irq[level - 1].callback[statid].func; 984c813f592a5e65cfd9321f51c95a6977e9518dde6Martyn Welch priv_data = bridge->irq[level - 1].callback[statid].priv_data; 985c813f592a5e65cfd9321f51c95a6977e9518dde6Martyn Welch 986c813f592a5e65cfd9321f51c95a6977e9518dde6Martyn Welch if (call != NULL) 987c813f592a5e65cfd9321f51c95a6977e9518dde6Martyn Welch call(level, statid, priv_data); 988c813f592a5e65cfd9321f51c95a6977e9518dde6Martyn Welch else 989c813f592a5e65cfd9321f51c95a6977e9518dde6Martyn Welch printk(KERN_WARNING "Spurilous VME interrupt, level:%x, " 990c813f592a5e65cfd9321f51c95a6977e9518dde6Martyn Welch "vector:%x\n", level, statid); 991c813f592a5e65cfd9321f51c95a6977e9518dde6Martyn Welch} 992c813f592a5e65cfd9321f51c95a6977e9518dde6Martyn WelchEXPORT_SYMBOL(vme_irq_handler); 993c813f592a5e65cfd9321f51c95a6977e9518dde6Martyn Welch 9948f966dc444b11adff6011a1d1fce424abdd876d8Manohar Vangaint vme_irq_request(struct vme_dev *vdev, int level, int statid, 99529848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch void (*callback)(int, int, void *), 996a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch void *priv_data) 997a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch{ 998a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch struct vme_bridge *bridge; 999a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 10008f966dc444b11adff6011a1d1fce424abdd876d8Manohar Vanga bridge = vdev->bridge; 1001a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch if (bridge == NULL) { 1002a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch printk(KERN_ERR "Can't find VME bus\n"); 1003a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch return -EINVAL; 1004a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch } 1005a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 1006ead1f3e301e2d886ef89f8d0c82b4d495f2a81c2Martyn Welch if ((level < 1) || (level > 7)) { 1007c813f592a5e65cfd9321f51c95a6977e9518dde6Martyn Welch printk(KERN_ERR "Invalid interrupt level\n"); 1008a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch return -EINVAL; 1009a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch } 1010a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 1011c813f592a5e65cfd9321f51c95a6977e9518dde6Martyn Welch if (bridge->irq_set == NULL) { 1012c813f592a5e65cfd9321f51c95a6977e9518dde6Martyn Welch printk(KERN_ERR "Configuring interrupts not supported\n"); 1013a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch return -EINVAL; 1014a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch } 1015a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 1016886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota mutex_lock(&bridge->irq_mtx); 1017c813f592a5e65cfd9321f51c95a6977e9518dde6Martyn Welch 1018c813f592a5e65cfd9321f51c95a6977e9518dde6Martyn Welch if (bridge->irq[level - 1].callback[statid].func) { 1019886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota mutex_unlock(&bridge->irq_mtx); 1020c813f592a5e65cfd9321f51c95a6977e9518dde6Martyn Welch printk(KERN_WARNING "VME Interrupt already taken\n"); 1021c813f592a5e65cfd9321f51c95a6977e9518dde6Martyn Welch return -EBUSY; 1022c813f592a5e65cfd9321f51c95a6977e9518dde6Martyn Welch } 1023c813f592a5e65cfd9321f51c95a6977e9518dde6Martyn Welch 1024c813f592a5e65cfd9321f51c95a6977e9518dde6Martyn Welch bridge->irq[level - 1].count++; 1025c813f592a5e65cfd9321f51c95a6977e9518dde6Martyn Welch bridge->irq[level - 1].callback[statid].priv_data = priv_data; 1026c813f592a5e65cfd9321f51c95a6977e9518dde6Martyn Welch bridge->irq[level - 1].callback[statid].func = callback; 1027c813f592a5e65cfd9321f51c95a6977e9518dde6Martyn Welch 1028c813f592a5e65cfd9321f51c95a6977e9518dde6Martyn Welch /* Enable IRQ level */ 102929848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch bridge->irq_set(bridge, level, 1, 1); 1030c813f592a5e65cfd9321f51c95a6977e9518dde6Martyn Welch 1031886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota mutex_unlock(&bridge->irq_mtx); 1032c813f592a5e65cfd9321f51c95a6977e9518dde6Martyn Welch 1033c813f592a5e65cfd9321f51c95a6977e9518dde6Martyn Welch return 0; 1034a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch} 1035c813f592a5e65cfd9321f51c95a6977e9518dde6Martyn WelchEXPORT_SYMBOL(vme_irq_request); 1036a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 10378f966dc444b11adff6011a1d1fce424abdd876d8Manohar Vangavoid vme_irq_free(struct vme_dev *vdev, int level, int statid) 1038a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch{ 1039a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch struct vme_bridge *bridge; 1040a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 10418f966dc444b11adff6011a1d1fce424abdd876d8Manohar Vanga bridge = vdev->bridge; 1042a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch if (bridge == NULL) { 1043a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch printk(KERN_ERR "Can't find VME bus\n"); 1044a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch return; 1045a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch } 1046a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 1047ead1f3e301e2d886ef89f8d0c82b4d495f2a81c2Martyn Welch if ((level < 1) || (level > 7)) { 1048c813f592a5e65cfd9321f51c95a6977e9518dde6Martyn Welch printk(KERN_ERR "Invalid interrupt level\n"); 1049a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch return; 1050a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch } 1051a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 1052c813f592a5e65cfd9321f51c95a6977e9518dde6Martyn Welch if (bridge->irq_set == NULL) { 1053c813f592a5e65cfd9321f51c95a6977e9518dde6Martyn Welch printk(KERN_ERR "Configuring interrupts not supported\n"); 1054a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch return; 1055a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch } 1056a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 1057886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota mutex_lock(&bridge->irq_mtx); 1058c813f592a5e65cfd9321f51c95a6977e9518dde6Martyn Welch 1059c813f592a5e65cfd9321f51c95a6977e9518dde6Martyn Welch bridge->irq[level - 1].count--; 1060c813f592a5e65cfd9321f51c95a6977e9518dde6Martyn Welch 1061c813f592a5e65cfd9321f51c95a6977e9518dde6Martyn Welch /* Disable IRQ level if no more interrupts attached at this level*/ 1062c813f592a5e65cfd9321f51c95a6977e9518dde6Martyn Welch if (bridge->irq[level - 1].count == 0) 106329848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch bridge->irq_set(bridge, level, 0, 1); 1064c813f592a5e65cfd9321f51c95a6977e9518dde6Martyn Welch 1065c813f592a5e65cfd9321f51c95a6977e9518dde6Martyn Welch bridge->irq[level - 1].callback[statid].func = NULL; 1066c813f592a5e65cfd9321f51c95a6977e9518dde6Martyn Welch bridge->irq[level - 1].callback[statid].priv_data = NULL; 1067c813f592a5e65cfd9321f51c95a6977e9518dde6Martyn Welch 1068886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota mutex_unlock(&bridge->irq_mtx); 1069a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch} 1070c813f592a5e65cfd9321f51c95a6977e9518dde6Martyn WelchEXPORT_SYMBOL(vme_irq_free); 1071a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 10728f966dc444b11adff6011a1d1fce424abdd876d8Manohar Vangaint vme_irq_generate(struct vme_dev *vdev, int level, int statid) 1073a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch{ 1074a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch struct vme_bridge *bridge; 1075a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 10768f966dc444b11adff6011a1d1fce424abdd876d8Manohar Vanga bridge = vdev->bridge; 1077a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch if (bridge == NULL) { 1078a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch printk(KERN_ERR "Can't find VME bus\n"); 1079a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch return -EINVAL; 1080a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch } 1081a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 1082ead1f3e301e2d886ef89f8d0c82b4d495f2a81c2Martyn Welch if ((level < 1) || (level > 7)) { 1083a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch printk(KERN_WARNING "Invalid interrupt level\n"); 1084a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch return -EINVAL; 1085a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch } 1086a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 1087c813f592a5e65cfd9321f51c95a6977e9518dde6Martyn Welch if (bridge->irq_generate == NULL) { 1088ead1f3e301e2d886ef89f8d0c82b4d495f2a81c2Martyn Welch printk(KERN_WARNING "Interrupt generation not supported\n"); 1089a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch return -EINVAL; 1090a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch } 1091a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 109229848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch return bridge->irq_generate(bridge, level, statid); 1093a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch} 1094c813f592a5e65cfd9321f51c95a6977e9518dde6Martyn WelchEXPORT_SYMBOL(vme_irq_generate); 1095a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 109642fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welch/* 109742fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welch * Request the location monitor, return resource or NULL 109842fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welch */ 10998f966dc444b11adff6011a1d1fce424abdd876d8Manohar Vangastruct vme_resource *vme_lm_request(struct vme_dev *vdev) 1100a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch{ 1101a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch struct vme_bridge *bridge; 110242fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welch struct list_head *lm_pos = NULL; 110342fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welch struct vme_lm_resource *allocated_lm = NULL; 110442fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welch struct vme_lm_resource *lm = NULL; 110542fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welch struct vme_resource *resource = NULL; 1106a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 11078f966dc444b11adff6011a1d1fce424abdd876d8Manohar Vanga bridge = vdev->bridge; 1108a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch if (bridge == NULL) { 1109a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch printk(KERN_ERR "Can't find VME bus\n"); 111042fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welch goto err_bus; 111142fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welch } 111242fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welch 111342fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welch /* Loop through DMA resources */ 1114886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota list_for_each(lm_pos, &bridge->lm_resources) { 111542fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welch lm = list_entry(lm_pos, 111642fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welch struct vme_lm_resource, list); 111742fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welch 111842fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welch if (lm == NULL) { 111942fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welch printk(KERN_ERR "Registered NULL Location Monitor " 112042fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welch "resource\n"); 112142fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welch continue; 112242fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welch } 112342fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welch 112442fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welch /* Find an unlocked controller */ 1125886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota mutex_lock(&lm->mtx); 112642fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welch if (lm->locked == 0) { 112742fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welch lm->locked = 1; 1128886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota mutex_unlock(&lm->mtx); 112942fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welch allocated_lm = lm; 113042fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welch break; 113142fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welch } 1132886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota mutex_unlock(&lm->mtx); 113342fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welch } 113442fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welch 113542fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welch /* Check to see if we found a resource */ 113642fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welch if (allocated_lm == NULL) 113742fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welch goto err_lm; 113842fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welch 113942fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welch resource = kmalloc(sizeof(struct vme_resource), GFP_KERNEL); 114042fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welch if (resource == NULL) { 114142fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welch printk(KERN_ERR "Unable to allocate resource structure\n"); 114242fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welch goto err_alloc; 114342fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welch } 114442fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welch resource->type = VME_LM; 1145886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota resource->entry = &allocated_lm->list; 114642fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welch 114742fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welch return resource; 114842fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welch 114942fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welcherr_alloc: 115042fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welch /* Unlock image */ 1151886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota mutex_lock(&lm->mtx); 115242fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welch lm->locked = 0; 1153886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota mutex_unlock(&lm->mtx); 115442fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welcherr_lm: 115542fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welcherr_bus: 115642fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welch return NULL; 115742fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welch} 115842fb503122d8cd428b5b1078bd473847ca2b206cMartyn WelchEXPORT_SYMBOL(vme_lm_request); 115942fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welch 116042fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welchint vme_lm_count(struct vme_resource *resource) 116142fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welch{ 116242fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welch struct vme_lm_resource *lm; 116342fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welch 116442fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welch if (resource->type != VME_LM) { 116542fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welch printk(KERN_ERR "Not a Location Monitor resource\n"); 116642fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welch return -EINVAL; 116742fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welch } 116842fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welch 116942fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welch lm = list_entry(resource->entry, struct vme_lm_resource, list); 117042fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welch 117142fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welch return lm->monitors; 117242fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welch} 117342fb503122d8cd428b5b1078bd473847ca2b206cMartyn WelchEXPORT_SYMBOL(vme_lm_count); 117442fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welch 117542fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welchint vme_lm_set(struct vme_resource *resource, unsigned long long lm_base, 117642fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welch vme_address_t aspace, vme_cycle_t cycle) 117742fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welch{ 117842fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welch struct vme_bridge *bridge = find_bridge(resource); 117942fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welch struct vme_lm_resource *lm; 118042fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welch 118142fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welch if (resource->type != VME_LM) { 118242fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welch printk(KERN_ERR "Not a Location Monitor resource\n"); 1183a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch return -EINVAL; 1184a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch } 1185a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 118642fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welch lm = list_entry(resource->entry, struct vme_lm_resource, list); 118742fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welch 1188a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch if (bridge->lm_set == NULL) { 118942fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welch printk(KERN_ERR "vme_lm_set not supported\n"); 1190a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch return -EINVAL; 1191a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch } 1192a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 11938be9226c8f686c6dd2bae0a7ed4f5795e89d32d8Martyn Welch return bridge->lm_set(lm, lm_base, aspace, cycle); 1194a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch} 1195a17a75e2666f7175baac838bc4b6d11324dca3efMartyn WelchEXPORT_SYMBOL(vme_lm_set); 1196a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 119742fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welchint vme_lm_get(struct vme_resource *resource, unsigned long long *lm_base, 119842fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welch vme_address_t *aspace, vme_cycle_t *cycle) 1199a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch{ 120042fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welch struct vme_bridge *bridge = find_bridge(resource); 120142fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welch struct vme_lm_resource *lm; 1202a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 120342fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welch if (resource->type != VME_LM) { 120442fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welch printk(KERN_ERR "Not a Location Monitor resource\n"); 1205a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch return -EINVAL; 1206a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch } 1207a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 120842fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welch lm = list_entry(resource->entry, struct vme_lm_resource, list); 120942fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welch 1210a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch if (bridge->lm_get == NULL) { 121142fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welch printk(KERN_ERR "vme_lm_get not supported\n"); 1212a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch return -EINVAL; 1213a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch } 1214a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 121542fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welch return bridge->lm_get(lm, lm_base, aspace, cycle); 1216a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch} 1217a17a75e2666f7175baac838bc4b6d11324dca3efMartyn WelchEXPORT_SYMBOL(vme_lm_get); 1218a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 121942fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welchint vme_lm_attach(struct vme_resource *resource, int monitor, 122042fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welch void (*callback)(int)) 1221a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch{ 122242fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welch struct vme_bridge *bridge = find_bridge(resource); 122342fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welch struct vme_lm_resource *lm; 1224a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 122542fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welch if (resource->type != VME_LM) { 122642fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welch printk(KERN_ERR "Not a Location Monitor resource\n"); 1227a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch return -EINVAL; 1228a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch } 1229a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 123042fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welch lm = list_entry(resource->entry, struct vme_lm_resource, list); 123142fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welch 1232a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch if (bridge->lm_attach == NULL) { 123342fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welch printk(KERN_ERR "vme_lm_attach not supported\n"); 1234a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch return -EINVAL; 1235a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch } 1236a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 123742fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welch return bridge->lm_attach(lm, monitor, callback); 1238a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch} 1239a17a75e2666f7175baac838bc4b6d11324dca3efMartyn WelchEXPORT_SYMBOL(vme_lm_attach); 1240a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 124142fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welchint vme_lm_detach(struct vme_resource *resource, int monitor) 1242a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch{ 124342fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welch struct vme_bridge *bridge = find_bridge(resource); 124442fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welch struct vme_lm_resource *lm; 1245a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 124642fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welch if (resource->type != VME_LM) { 124742fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welch printk(KERN_ERR "Not a Location Monitor resource\n"); 1248a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch return -EINVAL; 1249a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch } 1250a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 125142fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welch lm = list_entry(resource->entry, struct vme_lm_resource, list); 125242fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welch 1253a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch if (bridge->lm_detach == NULL) { 125442fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welch printk(KERN_ERR "vme_lm_detach not supported\n"); 1255a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch return -EINVAL; 1256a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch } 1257a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 125842fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welch return bridge->lm_detach(lm, monitor); 1259a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch} 1260a17a75e2666f7175baac838bc4b6d11324dca3efMartyn WelchEXPORT_SYMBOL(vme_lm_detach); 1261a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 126242fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welchvoid vme_lm_free(struct vme_resource *resource) 126342fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welch{ 126442fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welch struct vme_lm_resource *lm; 126542fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welch 126642fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welch if (resource->type != VME_LM) { 126742fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welch printk(KERN_ERR "Not a Location Monitor resource\n"); 126842fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welch return; 126942fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welch } 127042fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welch 127142fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welch lm = list_entry(resource->entry, struct vme_lm_resource, list); 127242fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welch 1273886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota mutex_lock(&lm->mtx); 127442fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welch 12758be9226c8f686c6dd2bae0a7ed4f5795e89d32d8Martyn Welch /* XXX 12768be9226c8f686c6dd2bae0a7ed4f5795e89d32d8Martyn Welch * Check to see that there aren't any callbacks still attached, if 12778be9226c8f686c6dd2bae0a7ed4f5795e89d32d8Martyn Welch * there are we should probably be detaching them! 12788be9226c8f686c6dd2bae0a7ed4f5795e89d32d8Martyn Welch */ 127942fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welch 128042fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welch lm->locked = 0; 128142fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welch 1282886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota mutex_unlock(&lm->mtx); 12838be9226c8f686c6dd2bae0a7ed4f5795e89d32d8Martyn Welch 12848be9226c8f686c6dd2bae0a7ed4f5795e89d32d8Martyn Welch kfree(resource); 128542fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welch} 128642fb503122d8cd428b5b1078bd473847ca2b206cMartyn WelchEXPORT_SYMBOL(vme_lm_free); 128742fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welch 12888f966dc444b11adff6011a1d1fce424abdd876d8Manohar Vangaint vme_slot_get(struct vme_dev *vdev) 1289a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch{ 1290a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch struct vme_bridge *bridge; 1291a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 12928f966dc444b11adff6011a1d1fce424abdd876d8Manohar Vanga bridge = vdev->bridge; 1293a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch if (bridge == NULL) { 1294a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch printk(KERN_ERR "Can't find VME bus\n"); 1295a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch return -EINVAL; 1296a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch } 1297a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 1298a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch if (bridge->slot_get == NULL) { 1299ead1f3e301e2d886ef89f8d0c82b4d495f2a81c2Martyn Welch printk(KERN_WARNING "vme_slot_get not supported\n"); 1300a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch return -EINVAL; 1301a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch } 1302a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 130329848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch return bridge->slot_get(bridge); 1304a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch} 1305a17a75e2666f7175baac838bc4b6d11324dca3efMartyn WelchEXPORT_SYMBOL(vme_slot_get); 1306a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 1307a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 1308a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch/* - Bridge Registration --------------------------------------------------- */ 1309a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 1310733e3ef0d364b7e6757a897e7f1862a70c89305aManohar Vangastatic int vme_add_bus(struct vme_bridge *bridge) 1311a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch{ 1312a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch int i; 1313733e3ef0d364b7e6757a897e7f1862a70c89305aManohar Vanga int ret = -1; 1314a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 1315733e3ef0d364b7e6757a897e7f1862a70c89305aManohar Vanga mutex_lock(&vme_buses_lock); 1316a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch for (i = 0; i < sizeof(vme_bus_numbers) * 8; i++) { 1317733e3ef0d364b7e6757a897e7f1862a70c89305aManohar Vanga if ((vme_bus_numbers & (1 << i)) == 0) { 1318733e3ef0d364b7e6757a897e7f1862a70c89305aManohar Vanga vme_bus_numbers |= (1 << i); 1319733e3ef0d364b7e6757a897e7f1862a70c89305aManohar Vanga bridge->num = i; 13205d6abf379d73efe390488e8edba972af4e93cb1cManohar Vanga INIT_LIST_HEAD(&bridge->devices); 1321733e3ef0d364b7e6757a897e7f1862a70c89305aManohar Vanga list_add_tail(&bridge->bus_list, &vme_bus_list); 1322733e3ef0d364b7e6757a897e7f1862a70c89305aManohar Vanga ret = 0; 1323a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch break; 1324a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch } 1325a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch } 1326733e3ef0d364b7e6757a897e7f1862a70c89305aManohar Vanga mutex_unlock(&vme_buses_lock); 1327a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 1328733e3ef0d364b7e6757a897e7f1862a70c89305aManohar Vanga return ret; 1329a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch} 1330a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 1331733e3ef0d364b7e6757a897e7f1862a70c89305aManohar Vangastatic void vme_remove_bus(struct vme_bridge *bridge) 1332a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch{ 13335d6abf379d73efe390488e8edba972af4e93cb1cManohar Vanga struct vme_dev *vdev; 13345d6abf379d73efe390488e8edba972af4e93cb1cManohar Vanga struct vme_dev *tmp; 13355d6abf379d73efe390488e8edba972af4e93cb1cManohar Vanga 1336733e3ef0d364b7e6757a897e7f1862a70c89305aManohar Vanga mutex_lock(&vme_buses_lock); 1337733e3ef0d364b7e6757a897e7f1862a70c89305aManohar Vanga vme_bus_numbers &= ~(1 << bridge->num); 13385d6abf379d73efe390488e8edba972af4e93cb1cManohar Vanga list_for_each_entry_safe(vdev, tmp, &bridge->devices, bridge_list) { 13395d6abf379d73efe390488e8edba972af4e93cb1cManohar Vanga list_del(&vdev->drv_list); 13405d6abf379d73efe390488e8edba972af4e93cb1cManohar Vanga list_del(&vdev->bridge_list); 13415d6abf379d73efe390488e8edba972af4e93cb1cManohar Vanga device_unregister(&vdev->dev); 13425d6abf379d73efe390488e8edba972af4e93cb1cManohar Vanga } 1343733e3ef0d364b7e6757a897e7f1862a70c89305aManohar Vanga list_del(&bridge->bus_list); 1344733e3ef0d364b7e6757a897e7f1862a70c89305aManohar Vanga mutex_unlock(&vme_buses_lock); 1345a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch} 1346a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 1347f6c39d4f2d350df049a844b658eb6b08c5833e51Manohar Vangastatic void vme_dev_release(struct device *dev) 1348f6c39d4f2d350df049a844b658eb6b08c5833e51Manohar Vanga{ 13498f966dc444b11adff6011a1d1fce424abdd876d8Manohar Vanga kfree(dev_to_vme_dev(dev)); 1350f6c39d4f2d350df049a844b658eb6b08c5833e51Manohar Vanga} 1351f6c39d4f2d350df049a844b658eb6b08c5833e51Manohar Vanga 1352ead1f3e301e2d886ef89f8d0c82b4d495f2a81c2Martyn Welchint vme_register_bridge(struct vme_bridge *bridge) 1353a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch{ 13545d6abf379d73efe390488e8edba972af4e93cb1cManohar Vanga return vme_add_bus(bridge); 13555d6abf379d73efe390488e8edba972af4e93cb1cManohar Vanga} 13565d6abf379d73efe390488e8edba972af4e93cb1cManohar VangaEXPORT_SYMBOL(vme_register_bridge); 1357a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 13585d6abf379d73efe390488e8edba972af4e93cb1cManohar Vangavoid vme_unregister_bridge(struct vme_bridge *bridge) 13595d6abf379d73efe390488e8edba972af4e93cb1cManohar Vanga{ 13605d6abf379d73efe390488e8edba972af4e93cb1cManohar Vanga vme_remove_bus(bridge); 13615d6abf379d73efe390488e8edba972af4e93cb1cManohar Vanga} 13625d6abf379d73efe390488e8edba972af4e93cb1cManohar VangaEXPORT_SYMBOL(vme_unregister_bridge); 1363a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 13645d6abf379d73efe390488e8edba972af4e93cb1cManohar Vanga/* - Driver Registration --------------------------------------------------- */ 13655d6abf379d73efe390488e8edba972af4e93cb1cManohar Vanga 13665d6abf379d73efe390488e8edba972af4e93cb1cManohar Vangastatic int __vme_register_driver_bus(struct vme_driver *drv, 13675d6abf379d73efe390488e8edba972af4e93cb1cManohar Vanga struct vme_bridge *bridge, unsigned int ndevs) 13685d6abf379d73efe390488e8edba972af4e93cb1cManohar Vanga{ 13695d6abf379d73efe390488e8edba972af4e93cb1cManohar Vanga int err; 13705d6abf379d73efe390488e8edba972af4e93cb1cManohar Vanga unsigned int i; 13715d6abf379d73efe390488e8edba972af4e93cb1cManohar Vanga struct vme_dev *vdev; 13725d6abf379d73efe390488e8edba972af4e93cb1cManohar Vanga struct vme_dev *tmp; 13735d6abf379d73efe390488e8edba972af4e93cb1cManohar Vanga 13745d6abf379d73efe390488e8edba972af4e93cb1cManohar Vanga for (i = 0; i < ndevs; i++) { 13755d6abf379d73efe390488e8edba972af4e93cb1cManohar Vanga vdev = kzalloc(sizeof(struct vme_dev), GFP_KERNEL); 13765d6abf379d73efe390488e8edba972af4e93cb1cManohar Vanga if (!vdev) { 13775d6abf379d73efe390488e8edba972af4e93cb1cManohar Vanga err = -ENOMEM; 1378f6c39d4f2d350df049a844b658eb6b08c5833e51Manohar Vanga goto err_devalloc; 1379f6c39d4f2d350df049a844b658eb6b08c5833e51Manohar Vanga } 1380a916a391d3e19593a104a8c3c4779a3084f1ca5bManohar Vanga vdev->num = i; 13818f966dc444b11adff6011a1d1fce424abdd876d8Manohar Vanga vdev->bridge = bridge; 13825d6abf379d73efe390488e8edba972af4e93cb1cManohar Vanga vdev->dev.platform_data = drv; 13835d6abf379d73efe390488e8edba972af4e93cb1cManohar Vanga vdev->dev.release = vme_dev_release; 13848f966dc444b11adff6011a1d1fce424abdd876d8Manohar Vanga vdev->dev.parent = bridge->parent; 13858f966dc444b11adff6011a1d1fce424abdd876d8Manohar Vanga vdev->dev.bus = &vme_bus_type; 1386a916a391d3e19593a104a8c3c4779a3084f1ca5bManohar Vanga dev_set_name(&vdev->dev, "%s.%u-%u", drv->name, bridge->num, 1387a916a391d3e19593a104a8c3c4779a3084f1ca5bManohar Vanga vdev->num); 1388a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 13895d6abf379d73efe390488e8edba972af4e93cb1cManohar Vanga err = device_register(&vdev->dev); 13905d6abf379d73efe390488e8edba972af4e93cb1cManohar Vanga if (err) 1391a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch goto err_reg; 1392a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 13935d6abf379d73efe390488e8edba972af4e93cb1cManohar Vanga if (vdev->dev.platform_data) { 13945d6abf379d73efe390488e8edba972af4e93cb1cManohar Vanga list_add_tail(&vdev->drv_list, &drv->devices); 13955d6abf379d73efe390488e8edba972af4e93cb1cManohar Vanga list_add_tail(&vdev->bridge_list, &bridge->devices); 13965d6abf379d73efe390488e8edba972af4e93cb1cManohar Vanga } else 13975d6abf379d73efe390488e8edba972af4e93cb1cManohar Vanga device_unregister(&vdev->dev); 13985d6abf379d73efe390488e8edba972af4e93cb1cManohar Vanga } 13995d6abf379d73efe390488e8edba972af4e93cb1cManohar Vanga return 0; 1400a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 1401a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welcherr_reg: 14028f966dc444b11adff6011a1d1fce424abdd876d8Manohar Vanga kfree(vdev); 1403f6c39d4f2d350df049a844b658eb6b08c5833e51Manohar Vangaerr_devalloc: 14045d6abf379d73efe390488e8edba972af4e93cb1cManohar Vanga list_for_each_entry_safe(vdev, tmp, &drv->devices, drv_list) { 14055d6abf379d73efe390488e8edba972af4e93cb1cManohar Vanga list_del(&vdev->drv_list); 14065d6abf379d73efe390488e8edba972af4e93cb1cManohar Vanga list_del(&vdev->bridge_list); 14078f966dc444b11adff6011a1d1fce424abdd876d8Manohar Vanga device_unregister(&vdev->dev); 1408a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch } 14095d6abf379d73efe390488e8edba972af4e93cb1cManohar Vanga return err; 1410a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch} 1411a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 14125d6abf379d73efe390488e8edba972af4e93cb1cManohar Vangastatic int __vme_register_driver(struct vme_driver *drv, unsigned int ndevs) 1413a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch{ 14145d6abf379d73efe390488e8edba972af4e93cb1cManohar Vanga struct vme_bridge *bridge; 14155d6abf379d73efe390488e8edba972af4e93cb1cManohar Vanga int err = 0; 1416a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 14175d6abf379d73efe390488e8edba972af4e93cb1cManohar Vanga mutex_lock(&vme_buses_lock); 14185d6abf379d73efe390488e8edba972af4e93cb1cManohar Vanga list_for_each_entry(bridge, &vme_bus_list, bus_list) { 14195d6abf379d73efe390488e8edba972af4e93cb1cManohar Vanga /* 14205d6abf379d73efe390488e8edba972af4e93cb1cManohar Vanga * This cannot cause trouble as we already have vme_buses_lock 14215d6abf379d73efe390488e8edba972af4e93cb1cManohar Vanga * and if the bridge is removed, it will have to go through 14225d6abf379d73efe390488e8edba972af4e93cb1cManohar Vanga * vme_unregister_bridge() to do it (which calls remove() on 14235d6abf379d73efe390488e8edba972af4e93cb1cManohar Vanga * the bridge which in turn tries to acquire vme_buses_lock and 1424c26f6112990b90977db429596ed0640d153b3a32Manohar Vanga * will have to wait). 14255d6abf379d73efe390488e8edba972af4e93cb1cManohar Vanga */ 14265d6abf379d73efe390488e8edba972af4e93cb1cManohar Vanga err = __vme_register_driver_bus(drv, bridge, ndevs); 14275d6abf379d73efe390488e8edba972af4e93cb1cManohar Vanga if (err) 14285d6abf379d73efe390488e8edba972af4e93cb1cManohar Vanga break; 1429a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch } 14305d6abf379d73efe390488e8edba972af4e93cb1cManohar Vanga mutex_unlock(&vme_buses_lock); 14315d6abf379d73efe390488e8edba972af4e93cb1cManohar Vanga return err; 1432a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch} 1433a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 14345d6abf379d73efe390488e8edba972af4e93cb1cManohar Vangaint vme_register_driver(struct vme_driver *drv, unsigned int ndevs) 1435a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch{ 14365d6abf379d73efe390488e8edba972af4e93cb1cManohar Vanga int err; 14375d6abf379d73efe390488e8edba972af4e93cb1cManohar Vanga 1438a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch drv->driver.name = drv->name; 1439a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch drv->driver.bus = &vme_bus_type; 14405d6abf379d73efe390488e8edba972af4e93cb1cManohar Vanga INIT_LIST_HEAD(&drv->devices); 14415d6abf379d73efe390488e8edba972af4e93cb1cManohar Vanga 14425d6abf379d73efe390488e8edba972af4e93cb1cManohar Vanga err = driver_register(&drv->driver); 14435d6abf379d73efe390488e8edba972af4e93cb1cManohar Vanga if (err) 14445d6abf379d73efe390488e8edba972af4e93cb1cManohar Vanga return err; 1445a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 14465d6abf379d73efe390488e8edba972af4e93cb1cManohar Vanga err = __vme_register_driver(drv, ndevs); 14475d6abf379d73efe390488e8edba972af4e93cb1cManohar Vanga if (err) 14485d6abf379d73efe390488e8edba972af4e93cb1cManohar Vanga driver_unregister(&drv->driver); 14495d6abf379d73efe390488e8edba972af4e93cb1cManohar Vanga 14505d6abf379d73efe390488e8edba972af4e93cb1cManohar Vanga return err; 1451a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch} 1452a17a75e2666f7175baac838bc4b6d11324dca3efMartyn WelchEXPORT_SYMBOL(vme_register_driver); 1453a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 1454ead1f3e301e2d886ef89f8d0c82b4d495f2a81c2Martyn Welchvoid vme_unregister_driver(struct vme_driver *drv) 1455a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch{ 14565d6abf379d73efe390488e8edba972af4e93cb1cManohar Vanga struct vme_dev *dev, *dev_tmp; 14575d6abf379d73efe390488e8edba972af4e93cb1cManohar Vanga 14585d6abf379d73efe390488e8edba972af4e93cb1cManohar Vanga mutex_lock(&vme_buses_lock); 14595d6abf379d73efe390488e8edba972af4e93cb1cManohar Vanga list_for_each_entry_safe(dev, dev_tmp, &drv->devices, drv_list) { 14605d6abf379d73efe390488e8edba972af4e93cb1cManohar Vanga list_del(&dev->drv_list); 14615d6abf379d73efe390488e8edba972af4e93cb1cManohar Vanga list_del(&dev->bridge_list); 14625d6abf379d73efe390488e8edba972af4e93cb1cManohar Vanga device_unregister(&dev->dev); 14635d6abf379d73efe390488e8edba972af4e93cb1cManohar Vanga } 14645d6abf379d73efe390488e8edba972af4e93cb1cManohar Vanga mutex_unlock(&vme_buses_lock); 14655d6abf379d73efe390488e8edba972af4e93cb1cManohar Vanga 1466a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch driver_unregister(&drv->driver); 1467a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch} 1468a17a75e2666f7175baac838bc4b6d11324dca3efMartyn WelchEXPORT_SYMBOL(vme_unregister_driver); 1469a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 1470a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch/* - Bus Registration ------------------------------------------------------ */ 1471a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 1472a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welchstatic int vme_bus_match(struct device *dev, struct device_driver *drv) 1473a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch{ 14745d6abf379d73efe390488e8edba972af4e93cb1cManohar Vanga struct vme_driver *vme_drv; 1475a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 14765d6abf379d73efe390488e8edba972af4e93cb1cManohar Vanga vme_drv = container_of(drv, struct vme_driver, driver); 1477a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 14785d6abf379d73efe390488e8edba972af4e93cb1cManohar Vanga if (dev->platform_data == vme_drv) { 14795d6abf379d73efe390488e8edba972af4e93cb1cManohar Vanga struct vme_dev *vdev = dev_to_vme_dev(dev); 1480a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 14815d6abf379d73efe390488e8edba972af4e93cb1cManohar Vanga if (vme_drv->match && vme_drv->match(vdev)) 14825d6abf379d73efe390488e8edba972af4e93cb1cManohar Vanga return 1; 1483a37b0dad8b3d278fa64482ccd2381c947f432bf7Martyn Welch 14845d6abf379d73efe390488e8edba972af4e93cb1cManohar Vanga dev->platform_data = NULL; 1485a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch } 1486a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch return 0; 1487a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch} 1488a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 1489a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welchstatic int vme_bus_probe(struct device *dev) 1490a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch{ 1491a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch int retval = -ENODEV; 14925d6abf379d73efe390488e8edba972af4e93cb1cManohar Vanga struct vme_driver *driver; 14935d6abf379d73efe390488e8edba972af4e93cb1cManohar Vanga struct vme_dev *vdev = dev_to_vme_dev(dev); 1494a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 14955d6abf379d73efe390488e8edba972af4e93cb1cManohar Vanga driver = dev->platform_data; 1496a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 1497ead1f3e301e2d886ef89f8d0c82b4d495f2a81c2Martyn Welch if (driver->probe != NULL) 14988f966dc444b11adff6011a1d1fce424abdd876d8Manohar Vanga retval = driver->probe(vdev); 1499a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 1500a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch return retval; 1501a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch} 1502a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 1503a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welchstatic int vme_bus_remove(struct device *dev) 1504a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch{ 1505a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch int retval = -ENODEV; 15065d6abf379d73efe390488e8edba972af4e93cb1cManohar Vanga struct vme_driver *driver; 15075d6abf379d73efe390488e8edba972af4e93cb1cManohar Vanga struct vme_dev *vdev = dev_to_vme_dev(dev); 1508a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 15095d6abf379d73efe390488e8edba972af4e93cb1cManohar Vanga driver = dev->platform_data; 1510a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 1511ead1f3e301e2d886ef89f8d0c82b4d495f2a81c2Martyn Welch if (driver->remove != NULL) 15128f966dc444b11adff6011a1d1fce424abdd876d8Manohar Vanga retval = driver->remove(vdev); 1513a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 1514a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch return retval; 1515a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch} 1516a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 1517a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welchstruct bus_type vme_bus_type = { 1518a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch .name = "vme", 1519a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch .match = vme_bus_match, 1520a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch .probe = vme_bus_probe, 1521a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch .remove = vme_bus_remove, 1522a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch}; 1523a17a75e2666f7175baac838bc4b6d11324dca3efMartyn WelchEXPORT_SYMBOL(vme_bus_type); 1524a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 1525ead1f3e301e2d886ef89f8d0c82b4d495f2a81c2Martyn Welchstatic int __init vme_init(void) 1526a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch{ 1527a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch return bus_register(&vme_bus_type); 1528a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch} 1529a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 1530ead1f3e301e2d886ef89f8d0c82b4d495f2a81c2Martyn Welchstatic void __exit vme_exit(void) 1531a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch{ 1532a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch bus_unregister(&vme_bus_type); 1533a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch} 1534a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 1535a17a75e2666f7175baac838bc4b6d11324dca3efMartyn WelchMODULE_DESCRIPTION("VME bridge driver framework"); 153666bd8db52ab48e7189e02d4bf1f23109cc1ede70Martyn WelchMODULE_AUTHOR("Martyn Welch <martyn.welch@ge.com"); 1537a17a75e2666f7175baac838bc4b6d11324dca3efMartyn WelchMODULE_LICENSE("GPL"); 1538a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 1539a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welchmodule_init(vme_init); 1540a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welchmodule_exit(vme_exit); 1541