vme.c revision 6af04b065b048e47bbd5a6f2d9776c08206ef26c
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; 1566af04b065b048e47bbd5a6f2d9776c08206ef26cMartyn Welch u32 aspace, cycle, dwidth; 157a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 158a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch switch (resource->type) { 159a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch case VME_MASTER: 160a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch retval = vme_master_get(resource, &enabled, &base, &size, 161a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch &aspace, &cycle, &dwidth); 162a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 163a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch return size; 164a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch break; 165a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch case VME_SLAVE: 166a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch retval = vme_slave_get(resource, &enabled, &base, &size, 167a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch &buf_base, &aspace, &cycle); 168a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 169a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch return size; 170a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch break; 171a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch case VME_DMA: 172a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch return 0; 173a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch break; 174a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch default: 175a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch printk(KERN_ERR "Unknown resource type\n"); 176a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch return 0; 177a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch break; 178a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch } 179a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch} 180a17a75e2666f7175baac838bc4b6d11324dca3efMartyn WelchEXPORT_SYMBOL(vme_get_size); 181a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 1826af04b065b048e47bbd5a6f2d9776c08206ef26cMartyn Welchstatic int vme_check_window(u32 aspace, unsigned long long vme_base, 183a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch unsigned long long size) 184a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch{ 185a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch int retval = 0; 186a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 187a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch switch (aspace) { 188a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch case VME_A16: 189a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch if (((vme_base + size) > VME_A16_MAX) || 190a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch (vme_base > VME_A16_MAX)) 191a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch retval = -EFAULT; 192a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch break; 193a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch case VME_A24: 194a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch if (((vme_base + size) > VME_A24_MAX) || 195a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch (vme_base > VME_A24_MAX)) 196a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch retval = -EFAULT; 197a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch break; 198a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch case VME_A32: 199a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch if (((vme_base + size) > VME_A32_MAX) || 200a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch (vme_base > VME_A32_MAX)) 201a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch retval = -EFAULT; 202a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch break; 203a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch case VME_A64: 204a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch /* 205a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch * Any value held in an unsigned long long can be used as the 206a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch * base 207a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch */ 208a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch break; 209a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch case VME_CRCSR: 210a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch if (((vme_base + size) > VME_CRCSR_MAX) || 211a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch (vme_base > VME_CRCSR_MAX)) 212a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch retval = -EFAULT; 213a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch break; 214a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch case VME_USER1: 215a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch case VME_USER2: 216a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch case VME_USER3: 217a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch case VME_USER4: 218a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch /* User Defined */ 219a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch break; 220a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch default: 221ead1f3e301e2d886ef89f8d0c82b4d495f2a81c2Martyn Welch printk(KERN_ERR "Invalid address space\n"); 222a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch retval = -EINVAL; 223a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch break; 224a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch } 225a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 226a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch return retval; 227a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch} 228a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 229a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch/* 230a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch * Request a slave image with specific attributes, return some unique 231a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch * identifier. 232a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch */ 2336af04b065b048e47bbd5a6f2d9776c08206ef26cMartyn Welchstruct vme_resource *vme_slave_request(struct vme_dev *vdev, u32 address, 2346af04b065b048e47bbd5a6f2d9776c08206ef26cMartyn Welch u32 cycle) 235a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch{ 236a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch struct vme_bridge *bridge; 237a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch struct list_head *slave_pos = NULL; 238a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch struct vme_slave_resource *allocated_image = NULL; 239a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch struct vme_slave_resource *slave_image = NULL; 240a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch struct vme_resource *resource = NULL; 241a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 2428f966dc444b11adff6011a1d1fce424abdd876d8Manohar Vanga bridge = vdev->bridge; 243a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch if (bridge == NULL) { 244a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch printk(KERN_ERR "Can't find VME bus\n"); 245a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch goto err_bus; 246a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch } 247a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 248a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch /* Loop through slave resources */ 249886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota list_for_each(slave_pos, &bridge->slave_resources) { 250a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch slave_image = list_entry(slave_pos, 251a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch struct vme_slave_resource, list); 252a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 253a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch if (slave_image == NULL) { 254ead1f3e301e2d886ef89f8d0c82b4d495f2a81c2Martyn Welch printk(KERN_ERR "Registered NULL Slave resource\n"); 255a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch continue; 256a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch } 257a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 258a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch /* Find an unlocked and compatible image */ 259886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota mutex_lock(&slave_image->mtx); 260ead1f3e301e2d886ef89f8d0c82b4d495f2a81c2Martyn Welch if (((slave_image->address_attr & address) == address) && 261a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch ((slave_image->cycle_attr & cycle) == cycle) && 262a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch (slave_image->locked == 0)) { 263a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 264a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch slave_image->locked = 1; 265886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota mutex_unlock(&slave_image->mtx); 266a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch allocated_image = slave_image; 267a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch break; 268a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch } 269886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota mutex_unlock(&slave_image->mtx); 270a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch } 271a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 272a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch /* No free image */ 273a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch if (allocated_image == NULL) 274a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch goto err_image; 275a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 276a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch resource = kmalloc(sizeof(struct vme_resource), GFP_KERNEL); 277a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch if (resource == NULL) { 278a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch printk(KERN_WARNING "Unable to allocate resource structure\n"); 279a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch goto err_alloc; 280a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch } 281a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch resource->type = VME_SLAVE; 282886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota resource->entry = &allocated_image->list; 283a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 284a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch return resource; 285a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 286a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welcherr_alloc: 287a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch /* Unlock image */ 288886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota mutex_lock(&slave_image->mtx); 289a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch slave_image->locked = 0; 290886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota mutex_unlock(&slave_image->mtx); 291a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welcherr_image: 292a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welcherr_bus: 293a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch return NULL; 294a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch} 295a17a75e2666f7175baac838bc4b6d11324dca3efMartyn WelchEXPORT_SYMBOL(vme_slave_request); 296a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 297ead1f3e301e2d886ef89f8d0c82b4d495f2a81c2Martyn Welchint vme_slave_set(struct vme_resource *resource, int enabled, 298a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch unsigned long long vme_base, unsigned long long size, 2996af04b065b048e47bbd5a6f2d9776c08206ef26cMartyn Welch dma_addr_t buf_base, u32 aspace, u32 cycle) 300a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch{ 301a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch struct vme_bridge *bridge = find_bridge(resource); 302a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch struct vme_slave_resource *image; 303a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch int retval; 304a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 305a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch if (resource->type != VME_SLAVE) { 306ead1f3e301e2d886ef89f8d0c82b4d495f2a81c2Martyn Welch printk(KERN_ERR "Not a slave resource\n"); 307a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch return -EINVAL; 308a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch } 309a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 310a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch image = list_entry(resource->entry, struct vme_slave_resource, list); 311a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 312a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch if (bridge->slave_set == NULL) { 313ead1f3e301e2d886ef89f8d0c82b4d495f2a81c2Martyn Welch printk(KERN_ERR "Function not supported\n"); 314a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch return -ENOSYS; 315a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch } 316a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 317ead1f3e301e2d886ef89f8d0c82b4d495f2a81c2Martyn Welch if (!(((image->address_attr & aspace) == aspace) && 318a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch ((image->cycle_attr & cycle) == cycle))) { 319ead1f3e301e2d886ef89f8d0c82b4d495f2a81c2Martyn Welch printk(KERN_ERR "Invalid attributes\n"); 320a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch return -EINVAL; 321a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch } 322a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 323a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch retval = vme_check_window(aspace, vme_base, size); 324ead1f3e301e2d886ef89f8d0c82b4d495f2a81c2Martyn Welch if (retval) 325a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch return retval; 326a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 327a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch return bridge->slave_set(image, enabled, vme_base, size, buf_base, 328a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch aspace, cycle); 329a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch} 330a17a75e2666f7175baac838bc4b6d11324dca3efMartyn WelchEXPORT_SYMBOL(vme_slave_set); 331a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 332ead1f3e301e2d886ef89f8d0c82b4d495f2a81c2Martyn Welchint vme_slave_get(struct vme_resource *resource, int *enabled, 333a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch unsigned long long *vme_base, unsigned long long *size, 3346af04b065b048e47bbd5a6f2d9776c08206ef26cMartyn Welch dma_addr_t *buf_base, u32 *aspace, u32 *cycle) 335a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch{ 336a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch struct vme_bridge *bridge = find_bridge(resource); 337a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch struct vme_slave_resource *image; 338a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 339a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch if (resource->type != VME_SLAVE) { 340ead1f3e301e2d886ef89f8d0c82b4d495f2a81c2Martyn Welch printk(KERN_ERR "Not a slave resource\n"); 341a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch return -EINVAL; 342a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch } 343a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 344a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch image = list_entry(resource->entry, struct vme_slave_resource, list); 345a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 34651a569f757f233bcffbffcdfeeff510916991a55Emilio G. Cota if (bridge->slave_get == NULL) { 347ead1f3e301e2d886ef89f8d0c82b4d495f2a81c2Martyn Welch printk(KERN_ERR "vme_slave_get not supported\n"); 348a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch return -EINVAL; 349a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch } 350a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 351a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch return bridge->slave_get(image, enabled, vme_base, size, buf_base, 352a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch aspace, cycle); 353a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch} 354a17a75e2666f7175baac838bc4b6d11324dca3efMartyn WelchEXPORT_SYMBOL(vme_slave_get); 355a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 356a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welchvoid vme_slave_free(struct vme_resource *resource) 357a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch{ 358a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch struct vme_slave_resource *slave_image; 359a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 360a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch if (resource->type != VME_SLAVE) { 361ead1f3e301e2d886ef89f8d0c82b4d495f2a81c2Martyn Welch printk(KERN_ERR "Not a slave resource\n"); 362a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch return; 363a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch } 364a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 365a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch slave_image = list_entry(resource->entry, struct vme_slave_resource, 366a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch list); 367a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch if (slave_image == NULL) { 368ead1f3e301e2d886ef89f8d0c82b4d495f2a81c2Martyn Welch printk(KERN_ERR "Can't find slave resource\n"); 369a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch return; 370a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch } 371a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 372a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch /* Unlock image */ 373886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota mutex_lock(&slave_image->mtx); 374a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch if (slave_image->locked == 0) 375a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch printk(KERN_ERR "Image is already free\n"); 376a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 377a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch slave_image->locked = 0; 378886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota mutex_unlock(&slave_image->mtx); 379a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 380a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch /* Free up resource memory */ 381a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch kfree(resource); 382a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch} 383a17a75e2666f7175baac838bc4b6d11324dca3efMartyn WelchEXPORT_SYMBOL(vme_slave_free); 384a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 385a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch/* 386a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch * Request a master image with specific attributes, return some unique 387a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch * identifier. 388a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch */ 3896af04b065b048e47bbd5a6f2d9776c08206ef26cMartyn Welchstruct vme_resource *vme_master_request(struct vme_dev *vdev, u32 address, 3906af04b065b048e47bbd5a6f2d9776c08206ef26cMartyn Welch u32 cycle, u32 dwidth) 391a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch{ 392a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch struct vme_bridge *bridge; 393a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch struct list_head *master_pos = NULL; 394a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch struct vme_master_resource *allocated_image = NULL; 395a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch struct vme_master_resource *master_image = NULL; 396a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch struct vme_resource *resource = NULL; 397a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 3988f966dc444b11adff6011a1d1fce424abdd876d8Manohar Vanga bridge = vdev->bridge; 399a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch if (bridge == NULL) { 400a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch printk(KERN_ERR "Can't find VME bus\n"); 401a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch goto err_bus; 402a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch } 403a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 404a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch /* Loop through master resources */ 405886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota list_for_each(master_pos, &bridge->master_resources) { 406a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch master_image = list_entry(master_pos, 407a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch struct vme_master_resource, list); 408a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 409a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch if (master_image == NULL) { 410a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch printk(KERN_WARNING "Registered NULL master resource\n"); 411a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch continue; 412a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch } 413a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 414a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch /* Find an unlocked and compatible image */ 415886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota spin_lock(&master_image->lock); 416ead1f3e301e2d886ef89f8d0c82b4d495f2a81c2Martyn Welch if (((master_image->address_attr & address) == address) && 417a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch ((master_image->cycle_attr & cycle) == cycle) && 418a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch ((master_image->width_attr & dwidth) == dwidth) && 419a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch (master_image->locked == 0)) { 420a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 421a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch master_image->locked = 1; 422886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota spin_unlock(&master_image->lock); 423a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch allocated_image = master_image; 424a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch break; 425a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch } 426886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota spin_unlock(&master_image->lock); 427a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch } 428a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 429a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch /* Check to see if we found a resource */ 430a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch if (allocated_image == NULL) { 431a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch printk(KERN_ERR "Can't find a suitable resource\n"); 432a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch goto err_image; 433a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch } 434a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 435a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch resource = kmalloc(sizeof(struct vme_resource), GFP_KERNEL); 436a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch if (resource == NULL) { 437a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch printk(KERN_ERR "Unable to allocate resource structure\n"); 438a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch goto err_alloc; 439a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch } 440a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch resource->type = VME_MASTER; 441886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota resource->entry = &allocated_image->list; 442a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 443a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch return resource; 444a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 445a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welcherr_alloc: 446a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch /* Unlock image */ 447886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota spin_lock(&master_image->lock); 448a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch master_image->locked = 0; 449886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota spin_unlock(&master_image->lock); 450a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welcherr_image: 451a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welcherr_bus: 452a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch return NULL; 453a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch} 454a17a75e2666f7175baac838bc4b6d11324dca3efMartyn WelchEXPORT_SYMBOL(vme_master_request); 455a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 456ead1f3e301e2d886ef89f8d0c82b4d495f2a81c2Martyn Welchint vme_master_set(struct vme_resource *resource, int enabled, 4576af04b065b048e47bbd5a6f2d9776c08206ef26cMartyn Welch unsigned long long vme_base, unsigned long long size, u32 aspace, 4586af04b065b048e47bbd5a6f2d9776c08206ef26cMartyn Welch u32 cycle, u32 dwidth) 459a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch{ 460a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch struct vme_bridge *bridge = find_bridge(resource); 461a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch struct vme_master_resource *image; 462a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch int retval; 463a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 464a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch if (resource->type != VME_MASTER) { 465ead1f3e301e2d886ef89f8d0c82b4d495f2a81c2Martyn Welch printk(KERN_ERR "Not a master resource\n"); 466a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch return -EINVAL; 467a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch } 468a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 469a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch image = list_entry(resource->entry, struct vme_master_resource, list); 470a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 471a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch if (bridge->master_set == NULL) { 472ead1f3e301e2d886ef89f8d0c82b4d495f2a81c2Martyn Welch printk(KERN_WARNING "vme_master_set not supported\n"); 473a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch return -EINVAL; 474a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch } 475a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 476ead1f3e301e2d886ef89f8d0c82b4d495f2a81c2Martyn Welch if (!(((image->address_attr & aspace) == aspace) && 477a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch ((image->cycle_attr & cycle) == cycle) && 478a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch ((image->width_attr & dwidth) == dwidth))) { 479ead1f3e301e2d886ef89f8d0c82b4d495f2a81c2Martyn Welch printk(KERN_WARNING "Invalid attributes\n"); 480a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch return -EINVAL; 481a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch } 482a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 483a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch retval = vme_check_window(aspace, vme_base, size); 484ead1f3e301e2d886ef89f8d0c82b4d495f2a81c2Martyn Welch if (retval) 485a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch return retval; 486a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 487a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch return bridge->master_set(image, enabled, vme_base, size, aspace, 488a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch cycle, dwidth); 489a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch} 490a17a75e2666f7175baac838bc4b6d11324dca3efMartyn WelchEXPORT_SYMBOL(vme_master_set); 491a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 492ead1f3e301e2d886ef89f8d0c82b4d495f2a81c2Martyn Welchint vme_master_get(struct vme_resource *resource, int *enabled, 4936af04b065b048e47bbd5a6f2d9776c08206ef26cMartyn Welch unsigned long long *vme_base, unsigned long long *size, u32 *aspace, 4946af04b065b048e47bbd5a6f2d9776c08206ef26cMartyn Welch u32 *cycle, u32 *dwidth) 495a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch{ 496a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch struct vme_bridge *bridge = find_bridge(resource); 497a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch struct vme_master_resource *image; 498a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 499a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch if (resource->type != VME_MASTER) { 500ead1f3e301e2d886ef89f8d0c82b4d495f2a81c2Martyn Welch printk(KERN_ERR "Not a master resource\n"); 501a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch return -EINVAL; 502a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch } 503a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 504a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch image = list_entry(resource->entry, struct vme_master_resource, list); 505a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 50651a569f757f233bcffbffcdfeeff510916991a55Emilio G. Cota if (bridge->master_get == NULL) { 507ead1f3e301e2d886ef89f8d0c82b4d495f2a81c2Martyn Welch printk(KERN_WARNING "vme_master_set not supported\n"); 508a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch return -EINVAL; 509a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch } 510a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 511a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch return bridge->master_get(image, enabled, vme_base, size, aspace, 512a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch cycle, dwidth); 513a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch} 514a17a75e2666f7175baac838bc4b6d11324dca3efMartyn WelchEXPORT_SYMBOL(vme_master_get); 515a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 516a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch/* 517a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch * Read data out of VME space into a buffer. 518a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch */ 519ead1f3e301e2d886ef89f8d0c82b4d495f2a81c2Martyn Welchssize_t vme_master_read(struct vme_resource *resource, void *buf, size_t count, 520a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch loff_t offset) 521a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch{ 522a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch struct vme_bridge *bridge = find_bridge(resource); 523a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch struct vme_master_resource *image; 524a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch size_t length; 525a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 526a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch if (bridge->master_read == NULL) { 527ead1f3e301e2d886ef89f8d0c82b4d495f2a81c2Martyn Welch printk(KERN_WARNING "Reading from resource not supported\n"); 528a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch return -EINVAL; 529a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch } 530a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 531a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch if (resource->type != VME_MASTER) { 532ead1f3e301e2d886ef89f8d0c82b4d495f2a81c2Martyn Welch printk(KERN_ERR "Not a master resource\n"); 533a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch return -EINVAL; 534a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch } 535a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 536a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch image = list_entry(resource->entry, struct vme_master_resource, list); 537a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 538a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch length = vme_get_size(resource); 539a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 540a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch if (offset > length) { 541ead1f3e301e2d886ef89f8d0c82b4d495f2a81c2Martyn Welch printk(KERN_WARNING "Invalid Offset\n"); 542a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch return -EFAULT; 543a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch } 544a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 545a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch if ((offset + count) > length) 546a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch count = length - offset; 547a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 548a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch return bridge->master_read(image, buf, count, offset); 549a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 550a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch} 551a17a75e2666f7175baac838bc4b6d11324dca3efMartyn WelchEXPORT_SYMBOL(vme_master_read); 552a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 553a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch/* 554a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch * Write data out to VME space from a buffer. 555a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch */ 556ead1f3e301e2d886ef89f8d0c82b4d495f2a81c2Martyn Welchssize_t vme_master_write(struct vme_resource *resource, void *buf, 557a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch size_t count, loff_t offset) 558a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch{ 559a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch struct vme_bridge *bridge = find_bridge(resource); 560a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch struct vme_master_resource *image; 561a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch size_t length; 562a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 563a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch if (bridge->master_write == NULL) { 564ead1f3e301e2d886ef89f8d0c82b4d495f2a81c2Martyn Welch printk(KERN_WARNING "Writing to resource not supported\n"); 565a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch return -EINVAL; 566a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch } 567a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 568a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch if (resource->type != VME_MASTER) { 569ead1f3e301e2d886ef89f8d0c82b4d495f2a81c2Martyn Welch printk(KERN_ERR "Not a master resource\n"); 570a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch return -EINVAL; 571a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch } 572a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 573a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch image = list_entry(resource->entry, struct vme_master_resource, list); 574a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 575a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch length = vme_get_size(resource); 576a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 577a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch if (offset > length) { 578ead1f3e301e2d886ef89f8d0c82b4d495f2a81c2Martyn Welch printk(KERN_WARNING "Invalid Offset\n"); 579a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch return -EFAULT; 580a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch } 581a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 582a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch if ((offset + count) > length) 583a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch count = length - offset; 584a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 585a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch return bridge->master_write(image, buf, count, offset); 586a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch} 587a17a75e2666f7175baac838bc4b6d11324dca3efMartyn WelchEXPORT_SYMBOL(vme_master_write); 588a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 589a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch/* 590a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch * Perform RMW cycle to provided location. 591a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch */ 592ead1f3e301e2d886ef89f8d0c82b4d495f2a81c2Martyn Welchunsigned int vme_master_rmw(struct vme_resource *resource, unsigned int mask, 593a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch unsigned int compare, unsigned int swap, loff_t offset) 594a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch{ 595a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch struct vme_bridge *bridge = find_bridge(resource); 596a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch struct vme_master_resource *image; 597a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 598a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch if (bridge->master_rmw == NULL) { 599ead1f3e301e2d886ef89f8d0c82b4d495f2a81c2Martyn Welch printk(KERN_WARNING "Writing to resource not supported\n"); 600a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch return -EINVAL; 601a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch } 602a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 603a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch if (resource->type != VME_MASTER) { 604ead1f3e301e2d886ef89f8d0c82b4d495f2a81c2Martyn Welch printk(KERN_ERR "Not a master resource\n"); 605a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch return -EINVAL; 606a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch } 607a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 608a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch image = list_entry(resource->entry, struct vme_master_resource, list); 609a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 610a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch return bridge->master_rmw(image, mask, compare, swap, offset); 611a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch} 612a17a75e2666f7175baac838bc4b6d11324dca3efMartyn WelchEXPORT_SYMBOL(vme_master_rmw); 613a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 614a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welchvoid vme_master_free(struct vme_resource *resource) 615a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch{ 616a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch struct vme_master_resource *master_image; 617a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 618a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch if (resource->type != VME_MASTER) { 619ead1f3e301e2d886ef89f8d0c82b4d495f2a81c2Martyn Welch printk(KERN_ERR "Not a master resource\n"); 620a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch return; 621a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch } 622a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 623a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch master_image = list_entry(resource->entry, struct vme_master_resource, 624a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch list); 625a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch if (master_image == NULL) { 626ead1f3e301e2d886ef89f8d0c82b4d495f2a81c2Martyn Welch printk(KERN_ERR "Can't find master resource\n"); 627a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch return; 628a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch } 629a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 630a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch /* Unlock image */ 631886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota spin_lock(&master_image->lock); 632a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch if (master_image->locked == 0) 633a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch printk(KERN_ERR "Image is already free\n"); 634a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 635a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch master_image->locked = 0; 636886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota spin_unlock(&master_image->lock); 637a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 638a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch /* Free up resource memory */ 639a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch kfree(resource); 640a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch} 641a17a75e2666f7175baac838bc4b6d11324dca3efMartyn WelchEXPORT_SYMBOL(vme_master_free); 642a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 643a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch/* 644a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch * Request a DMA controller with specific attributes, return some unique 645a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch * identifier. 646a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch */ 6476af04b065b048e47bbd5a6f2d9776c08206ef26cMartyn Welchstruct vme_resource *vme_dma_request(struct vme_dev *vdev, u32 route) 648a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch{ 649a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch struct vme_bridge *bridge; 650a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch struct list_head *dma_pos = NULL; 651a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch struct vme_dma_resource *allocated_ctrlr = NULL; 652a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch struct vme_dma_resource *dma_ctrlr = NULL; 653a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch struct vme_resource *resource = NULL; 654a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 655a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch /* XXX Not checking resource attributes */ 656a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch printk(KERN_ERR "No VME resource Attribute tests done\n"); 657a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 6588f966dc444b11adff6011a1d1fce424abdd876d8Manohar Vanga bridge = vdev->bridge; 659a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch if (bridge == NULL) { 660a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch printk(KERN_ERR "Can't find VME bus\n"); 661a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch goto err_bus; 662a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch } 663a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 664a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch /* Loop through DMA resources */ 665886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota list_for_each(dma_pos, &bridge->dma_resources) { 666a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch dma_ctrlr = list_entry(dma_pos, 667a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch struct vme_dma_resource, list); 668a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 669a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch if (dma_ctrlr == NULL) { 670ead1f3e301e2d886ef89f8d0c82b4d495f2a81c2Martyn Welch printk(KERN_ERR "Registered NULL DMA resource\n"); 671a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch continue; 672a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch } 673a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 6744f723df45d3952c485ee0125fb6797ad615901c3Martyn Welch /* Find an unlocked and compatible controller */ 675886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota mutex_lock(&dma_ctrlr->mtx); 6764f723df45d3952c485ee0125fb6797ad615901c3Martyn Welch if (((dma_ctrlr->route_attr & route) == route) && 6774f723df45d3952c485ee0125fb6797ad615901c3Martyn Welch (dma_ctrlr->locked == 0)) { 6784f723df45d3952c485ee0125fb6797ad615901c3Martyn Welch 679a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch dma_ctrlr->locked = 1; 680886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota mutex_unlock(&dma_ctrlr->mtx); 681a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch allocated_ctrlr = dma_ctrlr; 682a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch break; 683a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch } 684886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota mutex_unlock(&dma_ctrlr->mtx); 685a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch } 686a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 687a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch /* Check to see if we found a resource */ 688a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch if (allocated_ctrlr == NULL) 689a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch goto err_ctrlr; 690a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 691a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch resource = kmalloc(sizeof(struct vme_resource), GFP_KERNEL); 692a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch if (resource == NULL) { 693a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch printk(KERN_WARNING "Unable to allocate resource structure\n"); 694a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch goto err_alloc; 695a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch } 696a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch resource->type = VME_DMA; 697886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota resource->entry = &allocated_ctrlr->list; 698a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 699a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch return resource; 700a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 701a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welcherr_alloc: 702a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch /* Unlock image */ 703886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota mutex_lock(&dma_ctrlr->mtx); 704a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch dma_ctrlr->locked = 0; 705886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota mutex_unlock(&dma_ctrlr->mtx); 706a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welcherr_ctrlr: 707a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welcherr_bus: 708a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch return NULL; 709a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch} 71058e507987b285f3df99f839c79da3985555ac220Martyn WelchEXPORT_SYMBOL(vme_dma_request); 711a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 712a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch/* 713a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch * Start new list 714a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch */ 715a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welchstruct vme_dma_list *vme_new_dma_list(struct vme_resource *resource) 716a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch{ 717a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch struct vme_dma_resource *ctrlr; 718a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch struct vme_dma_list *dma_list; 719a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 720a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch if (resource->type != VME_DMA) { 721ead1f3e301e2d886ef89f8d0c82b4d495f2a81c2Martyn Welch printk(KERN_ERR "Not a DMA resource\n"); 722a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch return NULL; 723a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch } 724a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 725a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch ctrlr = list_entry(resource->entry, struct vme_dma_resource, list); 726a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 727ead1f3e301e2d886ef89f8d0c82b4d495f2a81c2Martyn Welch dma_list = kmalloc(sizeof(struct vme_dma_list), GFP_KERNEL); 728ead1f3e301e2d886ef89f8d0c82b4d495f2a81c2Martyn Welch if (dma_list == NULL) { 729ead1f3e301e2d886ef89f8d0c82b4d495f2a81c2Martyn Welch printk(KERN_ERR "Unable to allocate memory for new dma list\n"); 730a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch return NULL; 731a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch } 732886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota INIT_LIST_HEAD(&dma_list->entries); 733a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch dma_list->parent = ctrlr; 734886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota mutex_init(&dma_list->mtx); 735a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 736a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch return dma_list; 737a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch} 738a17a75e2666f7175baac838bc4b6d11324dca3efMartyn WelchEXPORT_SYMBOL(vme_new_dma_list); 739a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 740a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch/* 741a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch * Create "Pattern" type attributes 742a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch */ 7436af04b065b048e47bbd5a6f2d9776c08206ef26cMartyn Welchstruct vme_dma_attr *vme_dma_pattern_attribute(u32 pattern, u32 type) 744a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch{ 745a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch struct vme_dma_attr *attributes; 746a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch struct vme_dma_pattern *pattern_attr; 747a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 748ead1f3e301e2d886ef89f8d0c82b4d495f2a81c2Martyn Welch attributes = kmalloc(sizeof(struct vme_dma_attr), GFP_KERNEL); 749ead1f3e301e2d886ef89f8d0c82b4d495f2a81c2Martyn Welch if (attributes == NULL) { 750ead1f3e301e2d886ef89f8d0c82b4d495f2a81c2Martyn Welch printk(KERN_ERR "Unable to allocate memory for attributes " 751ead1f3e301e2d886ef89f8d0c82b4d495f2a81c2Martyn Welch "structure\n"); 752a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch goto err_attr; 753a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch } 754a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 755ead1f3e301e2d886ef89f8d0c82b4d495f2a81c2Martyn Welch pattern_attr = kmalloc(sizeof(struct vme_dma_pattern), GFP_KERNEL); 756ead1f3e301e2d886ef89f8d0c82b4d495f2a81c2Martyn Welch if (pattern_attr == NULL) { 757ead1f3e301e2d886ef89f8d0c82b4d495f2a81c2Martyn Welch printk(KERN_ERR "Unable to allocate memory for pattern " 758ead1f3e301e2d886ef89f8d0c82b4d495f2a81c2Martyn Welch "attributes\n"); 759a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch goto err_pat; 760a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch } 761a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 762a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch attributes->type = VME_DMA_PATTERN; 763a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch attributes->private = (void *)pattern_attr; 764a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 765a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch pattern_attr->pattern = pattern; 766a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch pattern_attr->type = type; 767a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 768a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch return attributes; 769a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 770a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welcherr_pat: 771a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch kfree(attributes); 772a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welcherr_attr: 773a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch return NULL; 774a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch} 775a17a75e2666f7175baac838bc4b6d11324dca3efMartyn WelchEXPORT_SYMBOL(vme_dma_pattern_attribute); 776a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 777a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch/* 778a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch * Create "PCI" type attributes 779a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch */ 780a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welchstruct vme_dma_attr *vme_dma_pci_attribute(dma_addr_t address) 781a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch{ 782a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch struct vme_dma_attr *attributes; 783a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch struct vme_dma_pci *pci_attr; 784a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 785a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch /* XXX Run some sanity checks here */ 786a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 787ead1f3e301e2d886ef89f8d0c82b4d495f2a81c2Martyn Welch attributes = kmalloc(sizeof(struct vme_dma_attr), GFP_KERNEL); 788ead1f3e301e2d886ef89f8d0c82b4d495f2a81c2Martyn Welch if (attributes == NULL) { 789ead1f3e301e2d886ef89f8d0c82b4d495f2a81c2Martyn Welch printk(KERN_ERR "Unable to allocate memory for attributes " 790ead1f3e301e2d886ef89f8d0c82b4d495f2a81c2Martyn Welch "structure\n"); 791a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch goto err_attr; 792a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch } 793a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 794ead1f3e301e2d886ef89f8d0c82b4d495f2a81c2Martyn Welch pci_attr = kmalloc(sizeof(struct vme_dma_pci), GFP_KERNEL); 795ead1f3e301e2d886ef89f8d0c82b4d495f2a81c2Martyn Welch if (pci_attr == NULL) { 796ead1f3e301e2d886ef89f8d0c82b4d495f2a81c2Martyn Welch printk(KERN_ERR "Unable to allocate memory for pci " 797ead1f3e301e2d886ef89f8d0c82b4d495f2a81c2Martyn Welch "attributes\n"); 798a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch goto err_pci; 799a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch } 800a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 801a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 802a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 803a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch attributes->type = VME_DMA_PCI; 804a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch attributes->private = (void *)pci_attr; 805a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 806a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch pci_attr->address = address; 807a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 808a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch return attributes; 809a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 810a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welcherr_pci: 811a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch kfree(attributes); 812a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welcherr_attr: 813a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch return NULL; 814a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch} 815a17a75e2666f7175baac838bc4b6d11324dca3efMartyn WelchEXPORT_SYMBOL(vme_dma_pci_attribute); 816a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 817a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch/* 818a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch * Create "VME" type attributes 819a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch */ 820a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welchstruct vme_dma_attr *vme_dma_vme_attribute(unsigned long long address, 8216af04b065b048e47bbd5a6f2d9776c08206ef26cMartyn Welch u32 aspace, u32 cycle, u32 dwidth) 822a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch{ 823a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch struct vme_dma_attr *attributes; 824a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch struct vme_dma_vme *vme_attr; 825a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 826ead1f3e301e2d886ef89f8d0c82b4d495f2a81c2Martyn Welch attributes = kmalloc( 827a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch sizeof(struct vme_dma_attr), GFP_KERNEL); 828ead1f3e301e2d886ef89f8d0c82b4d495f2a81c2Martyn Welch if (attributes == NULL) { 829ead1f3e301e2d886ef89f8d0c82b4d495f2a81c2Martyn Welch printk(KERN_ERR "Unable to allocate memory for attributes " 830ead1f3e301e2d886ef89f8d0c82b4d495f2a81c2Martyn Welch "structure\n"); 831a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch goto err_attr; 832a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch } 833a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 834ead1f3e301e2d886ef89f8d0c82b4d495f2a81c2Martyn Welch vme_attr = kmalloc(sizeof(struct vme_dma_vme), GFP_KERNEL); 835ead1f3e301e2d886ef89f8d0c82b4d495f2a81c2Martyn Welch if (vme_attr == NULL) { 836ead1f3e301e2d886ef89f8d0c82b4d495f2a81c2Martyn Welch printk(KERN_ERR "Unable to allocate memory for vme " 837ead1f3e301e2d886ef89f8d0c82b4d495f2a81c2Martyn Welch "attributes\n"); 838a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch goto err_vme; 839a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch } 840a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 841a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch attributes->type = VME_DMA_VME; 842a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch attributes->private = (void *)vme_attr; 843a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 844a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch vme_attr->address = address; 845a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch vme_attr->aspace = aspace; 846a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch vme_attr->cycle = cycle; 847a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch vme_attr->dwidth = dwidth; 848a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 849a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch return attributes; 850a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 851a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welcherr_vme: 852a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch kfree(attributes); 853a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welcherr_attr: 854a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch return NULL; 855a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch} 856a17a75e2666f7175baac838bc4b6d11324dca3efMartyn WelchEXPORT_SYMBOL(vme_dma_vme_attribute); 857a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 858a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch/* 859a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch * Free attribute 860a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch */ 861a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welchvoid vme_dma_free_attribute(struct vme_dma_attr *attributes) 862a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch{ 863a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch kfree(attributes->private); 864a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch kfree(attributes); 865a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch} 866a17a75e2666f7175baac838bc4b6d11324dca3efMartyn WelchEXPORT_SYMBOL(vme_dma_free_attribute); 867a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 868a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welchint vme_dma_list_add(struct vme_dma_list *list, struct vme_dma_attr *src, 869a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch struct vme_dma_attr *dest, size_t count) 870a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch{ 871a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch struct vme_bridge *bridge = list->parent->parent; 872a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch int retval; 873a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 874a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch if (bridge->dma_list_add == NULL) { 875ead1f3e301e2d886ef89f8d0c82b4d495f2a81c2Martyn Welch printk(KERN_WARNING "Link List DMA generation not supported\n"); 876a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch return -EINVAL; 877a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch } 878a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 879886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota if (!mutex_trylock(&list->mtx)) { 880ead1f3e301e2d886ef89f8d0c82b4d495f2a81c2Martyn Welch printk(KERN_ERR "Link List already submitted\n"); 881a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch return -EINVAL; 882a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch } 883a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 884a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch retval = bridge->dma_list_add(list, src, dest, count); 885a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 886886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota mutex_unlock(&list->mtx); 887a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 888a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch return retval; 889a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch} 890a17a75e2666f7175baac838bc4b6d11324dca3efMartyn WelchEXPORT_SYMBOL(vme_dma_list_add); 891a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 892a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welchint vme_dma_list_exec(struct vme_dma_list *list) 893a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch{ 894a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch struct vme_bridge *bridge = list->parent->parent; 895a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch int retval; 896a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 897a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch if (bridge->dma_list_exec == NULL) { 898ead1f3e301e2d886ef89f8d0c82b4d495f2a81c2Martyn Welch printk(KERN_ERR "Link List DMA execution not supported\n"); 899a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch return -EINVAL; 900a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch } 901a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 902886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota mutex_lock(&list->mtx); 903a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 904a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch retval = bridge->dma_list_exec(list); 905a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 906886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota mutex_unlock(&list->mtx); 907a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 908a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch return retval; 909a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch} 910a17a75e2666f7175baac838bc4b6d11324dca3efMartyn WelchEXPORT_SYMBOL(vme_dma_list_exec); 911a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 912a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welchint vme_dma_list_free(struct vme_dma_list *list) 913a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch{ 914a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch struct vme_bridge *bridge = list->parent->parent; 915a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch int retval; 916a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 917a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch if (bridge->dma_list_empty == NULL) { 918ead1f3e301e2d886ef89f8d0c82b4d495f2a81c2Martyn Welch printk(KERN_WARNING "Emptying of Link Lists not supported\n"); 919a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch return -EINVAL; 920a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch } 921a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 922886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota if (!mutex_trylock(&list->mtx)) { 923ead1f3e301e2d886ef89f8d0c82b4d495f2a81c2Martyn Welch printk(KERN_ERR "Link List in use\n"); 924a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch return -EINVAL; 925a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch } 926a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 927a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch /* 928a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch * Empty out all of the entries from the dma list. We need to go to the 929a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch * low level driver as dma entries are driver specific. 930a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch */ 931a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch retval = bridge->dma_list_empty(list); 932a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch if (retval) { 933ead1f3e301e2d886ef89f8d0c82b4d495f2a81c2Martyn Welch printk(KERN_ERR "Unable to empty link-list entries\n"); 934886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota mutex_unlock(&list->mtx); 935a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch return retval; 936a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch } 937886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota mutex_unlock(&list->mtx); 938a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch kfree(list); 939a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 940a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch return retval; 941a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch} 942a17a75e2666f7175baac838bc4b6d11324dca3efMartyn WelchEXPORT_SYMBOL(vme_dma_list_free); 943a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 944a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welchint vme_dma_free(struct vme_resource *resource) 945a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch{ 946a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch struct vme_dma_resource *ctrlr; 947a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 948a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch if (resource->type != VME_DMA) { 949ead1f3e301e2d886ef89f8d0c82b4d495f2a81c2Martyn Welch printk(KERN_ERR "Not a DMA resource\n"); 950a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch return -EINVAL; 951a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch } 952a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 953a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch ctrlr = list_entry(resource->entry, struct vme_dma_resource, list); 954a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 955886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota if (!mutex_trylock(&ctrlr->mtx)) { 956ead1f3e301e2d886ef89f8d0c82b4d495f2a81c2Martyn Welch printk(KERN_ERR "Resource busy, can't free\n"); 957a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch return -EBUSY; 958a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch } 959a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 960886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota if (!(list_empty(&ctrlr->pending) && list_empty(&ctrlr->running))) { 961ead1f3e301e2d886ef89f8d0c82b4d495f2a81c2Martyn Welch printk(KERN_WARNING "Resource still processing transfers\n"); 962886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota mutex_unlock(&ctrlr->mtx); 963a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch return -EBUSY; 964a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch } 965a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 966a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch ctrlr->locked = 0; 967a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 968886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota mutex_unlock(&ctrlr->mtx); 969a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 970a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch return 0; 971a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch} 972a17a75e2666f7175baac838bc4b6d11324dca3efMartyn WelchEXPORT_SYMBOL(vme_dma_free); 973a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 974c813f592a5e65cfd9321f51c95a6977e9518dde6Martyn Welchvoid vme_irq_handler(struct vme_bridge *bridge, int level, int statid) 975c813f592a5e65cfd9321f51c95a6977e9518dde6Martyn Welch{ 976c813f592a5e65cfd9321f51c95a6977e9518dde6Martyn Welch void (*call)(int, int, void *); 977c813f592a5e65cfd9321f51c95a6977e9518dde6Martyn Welch void *priv_data; 978c813f592a5e65cfd9321f51c95a6977e9518dde6Martyn Welch 979c813f592a5e65cfd9321f51c95a6977e9518dde6Martyn Welch call = bridge->irq[level - 1].callback[statid].func; 980c813f592a5e65cfd9321f51c95a6977e9518dde6Martyn Welch priv_data = bridge->irq[level - 1].callback[statid].priv_data; 981c813f592a5e65cfd9321f51c95a6977e9518dde6Martyn Welch 982c813f592a5e65cfd9321f51c95a6977e9518dde6Martyn Welch if (call != NULL) 983c813f592a5e65cfd9321f51c95a6977e9518dde6Martyn Welch call(level, statid, priv_data); 984c813f592a5e65cfd9321f51c95a6977e9518dde6Martyn Welch else 985c813f592a5e65cfd9321f51c95a6977e9518dde6Martyn Welch printk(KERN_WARNING "Spurilous VME interrupt, level:%x, " 986c813f592a5e65cfd9321f51c95a6977e9518dde6Martyn Welch "vector:%x\n", level, statid); 987c813f592a5e65cfd9321f51c95a6977e9518dde6Martyn Welch} 988c813f592a5e65cfd9321f51c95a6977e9518dde6Martyn WelchEXPORT_SYMBOL(vme_irq_handler); 989c813f592a5e65cfd9321f51c95a6977e9518dde6Martyn Welch 9908f966dc444b11adff6011a1d1fce424abdd876d8Manohar Vangaint vme_irq_request(struct vme_dev *vdev, int level, int statid, 99129848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch void (*callback)(int, int, void *), 992a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch void *priv_data) 993a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch{ 994a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch struct vme_bridge *bridge; 995a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 9968f966dc444b11adff6011a1d1fce424abdd876d8Manohar Vanga bridge = vdev->bridge; 997a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch if (bridge == NULL) { 998a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch printk(KERN_ERR "Can't find VME bus\n"); 999a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch return -EINVAL; 1000a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch } 1001a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 1002ead1f3e301e2d886ef89f8d0c82b4d495f2a81c2Martyn Welch if ((level < 1) || (level > 7)) { 1003c813f592a5e65cfd9321f51c95a6977e9518dde6Martyn Welch printk(KERN_ERR "Invalid interrupt level\n"); 1004a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch return -EINVAL; 1005a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch } 1006a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 1007c813f592a5e65cfd9321f51c95a6977e9518dde6Martyn Welch if (bridge->irq_set == NULL) { 1008c813f592a5e65cfd9321f51c95a6977e9518dde6Martyn Welch printk(KERN_ERR "Configuring interrupts not supported\n"); 1009a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch return -EINVAL; 1010a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch } 1011a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 1012886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota mutex_lock(&bridge->irq_mtx); 1013c813f592a5e65cfd9321f51c95a6977e9518dde6Martyn Welch 1014c813f592a5e65cfd9321f51c95a6977e9518dde6Martyn Welch if (bridge->irq[level - 1].callback[statid].func) { 1015886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota mutex_unlock(&bridge->irq_mtx); 1016c813f592a5e65cfd9321f51c95a6977e9518dde6Martyn Welch printk(KERN_WARNING "VME Interrupt already taken\n"); 1017c813f592a5e65cfd9321f51c95a6977e9518dde6Martyn Welch return -EBUSY; 1018c813f592a5e65cfd9321f51c95a6977e9518dde6Martyn Welch } 1019c813f592a5e65cfd9321f51c95a6977e9518dde6Martyn Welch 1020c813f592a5e65cfd9321f51c95a6977e9518dde6Martyn Welch bridge->irq[level - 1].count++; 1021c813f592a5e65cfd9321f51c95a6977e9518dde6Martyn Welch bridge->irq[level - 1].callback[statid].priv_data = priv_data; 1022c813f592a5e65cfd9321f51c95a6977e9518dde6Martyn Welch bridge->irq[level - 1].callback[statid].func = callback; 1023c813f592a5e65cfd9321f51c95a6977e9518dde6Martyn Welch 1024c813f592a5e65cfd9321f51c95a6977e9518dde6Martyn Welch /* Enable IRQ level */ 102529848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch bridge->irq_set(bridge, level, 1, 1); 1026c813f592a5e65cfd9321f51c95a6977e9518dde6Martyn Welch 1027886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota mutex_unlock(&bridge->irq_mtx); 1028c813f592a5e65cfd9321f51c95a6977e9518dde6Martyn Welch 1029c813f592a5e65cfd9321f51c95a6977e9518dde6Martyn Welch return 0; 1030a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch} 1031c813f592a5e65cfd9321f51c95a6977e9518dde6Martyn WelchEXPORT_SYMBOL(vme_irq_request); 1032a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 10338f966dc444b11adff6011a1d1fce424abdd876d8Manohar Vangavoid vme_irq_free(struct vme_dev *vdev, int level, int statid) 1034a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch{ 1035a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch struct vme_bridge *bridge; 1036a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 10378f966dc444b11adff6011a1d1fce424abdd876d8Manohar Vanga bridge = vdev->bridge; 1038a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch if (bridge == NULL) { 1039a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch printk(KERN_ERR "Can't find VME bus\n"); 1040a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch return; 1041a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch } 1042a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 1043ead1f3e301e2d886ef89f8d0c82b4d495f2a81c2Martyn Welch if ((level < 1) || (level > 7)) { 1044c813f592a5e65cfd9321f51c95a6977e9518dde6Martyn Welch printk(KERN_ERR "Invalid interrupt level\n"); 1045a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch return; 1046a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch } 1047a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 1048c813f592a5e65cfd9321f51c95a6977e9518dde6Martyn Welch if (bridge->irq_set == NULL) { 1049c813f592a5e65cfd9321f51c95a6977e9518dde6Martyn Welch printk(KERN_ERR "Configuring interrupts not supported\n"); 1050a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch return; 1051a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch } 1052a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 1053886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota mutex_lock(&bridge->irq_mtx); 1054c813f592a5e65cfd9321f51c95a6977e9518dde6Martyn Welch 1055c813f592a5e65cfd9321f51c95a6977e9518dde6Martyn Welch bridge->irq[level - 1].count--; 1056c813f592a5e65cfd9321f51c95a6977e9518dde6Martyn Welch 1057c813f592a5e65cfd9321f51c95a6977e9518dde6Martyn Welch /* Disable IRQ level if no more interrupts attached at this level*/ 1058c813f592a5e65cfd9321f51c95a6977e9518dde6Martyn Welch if (bridge->irq[level - 1].count == 0) 105929848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch bridge->irq_set(bridge, level, 0, 1); 1060c813f592a5e65cfd9321f51c95a6977e9518dde6Martyn Welch 1061c813f592a5e65cfd9321f51c95a6977e9518dde6Martyn Welch bridge->irq[level - 1].callback[statid].func = NULL; 1062c813f592a5e65cfd9321f51c95a6977e9518dde6Martyn Welch bridge->irq[level - 1].callback[statid].priv_data = NULL; 1063c813f592a5e65cfd9321f51c95a6977e9518dde6Martyn Welch 1064886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota mutex_unlock(&bridge->irq_mtx); 1065a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch} 1066c813f592a5e65cfd9321f51c95a6977e9518dde6Martyn WelchEXPORT_SYMBOL(vme_irq_free); 1067a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 10688f966dc444b11adff6011a1d1fce424abdd876d8Manohar Vangaint vme_irq_generate(struct vme_dev *vdev, int level, int statid) 1069a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch{ 1070a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch struct vme_bridge *bridge; 1071a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 10728f966dc444b11adff6011a1d1fce424abdd876d8Manohar Vanga bridge = vdev->bridge; 1073a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch if (bridge == NULL) { 1074a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch printk(KERN_ERR "Can't find VME bus\n"); 1075a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch return -EINVAL; 1076a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch } 1077a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 1078ead1f3e301e2d886ef89f8d0c82b4d495f2a81c2Martyn Welch if ((level < 1) || (level > 7)) { 1079a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch printk(KERN_WARNING "Invalid interrupt level\n"); 1080a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch return -EINVAL; 1081a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch } 1082a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 1083c813f592a5e65cfd9321f51c95a6977e9518dde6Martyn Welch if (bridge->irq_generate == NULL) { 1084ead1f3e301e2d886ef89f8d0c82b4d495f2a81c2Martyn Welch printk(KERN_WARNING "Interrupt generation not supported\n"); 1085a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch return -EINVAL; 1086a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch } 1087a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 108829848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch return bridge->irq_generate(bridge, level, statid); 1089a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch} 1090c813f592a5e65cfd9321f51c95a6977e9518dde6Martyn WelchEXPORT_SYMBOL(vme_irq_generate); 1091a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 109242fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welch/* 109342fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welch * Request the location monitor, return resource or NULL 109442fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welch */ 10958f966dc444b11adff6011a1d1fce424abdd876d8Manohar Vangastruct vme_resource *vme_lm_request(struct vme_dev *vdev) 1096a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch{ 1097a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch struct vme_bridge *bridge; 109842fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welch struct list_head *lm_pos = NULL; 109942fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welch struct vme_lm_resource *allocated_lm = NULL; 110042fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welch struct vme_lm_resource *lm = NULL; 110142fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welch struct vme_resource *resource = NULL; 1102a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 11038f966dc444b11adff6011a1d1fce424abdd876d8Manohar Vanga bridge = vdev->bridge; 1104a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch if (bridge == NULL) { 1105a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch printk(KERN_ERR "Can't find VME bus\n"); 110642fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welch goto err_bus; 110742fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welch } 110842fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welch 110942fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welch /* Loop through DMA resources */ 1110886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota list_for_each(lm_pos, &bridge->lm_resources) { 111142fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welch lm = list_entry(lm_pos, 111242fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welch struct vme_lm_resource, list); 111342fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welch 111442fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welch if (lm == NULL) { 111542fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welch printk(KERN_ERR "Registered NULL Location Monitor " 111642fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welch "resource\n"); 111742fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welch continue; 111842fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welch } 111942fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welch 112042fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welch /* Find an unlocked controller */ 1121886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota mutex_lock(&lm->mtx); 112242fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welch if (lm->locked == 0) { 112342fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welch lm->locked = 1; 1124886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota mutex_unlock(&lm->mtx); 112542fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welch allocated_lm = lm; 112642fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welch break; 112742fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welch } 1128886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota mutex_unlock(&lm->mtx); 112942fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welch } 113042fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welch 113142fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welch /* Check to see if we found a resource */ 113242fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welch if (allocated_lm == NULL) 113342fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welch goto err_lm; 113442fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welch 113542fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welch resource = kmalloc(sizeof(struct vme_resource), GFP_KERNEL); 113642fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welch if (resource == NULL) { 113742fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welch printk(KERN_ERR "Unable to allocate resource structure\n"); 113842fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welch goto err_alloc; 113942fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welch } 114042fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welch resource->type = VME_LM; 1141886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota resource->entry = &allocated_lm->list; 114242fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welch 114342fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welch return resource; 114442fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welch 114542fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welcherr_alloc: 114642fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welch /* Unlock image */ 1147886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota mutex_lock(&lm->mtx); 114842fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welch lm->locked = 0; 1149886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota mutex_unlock(&lm->mtx); 115042fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welcherr_lm: 115142fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welcherr_bus: 115242fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welch return NULL; 115342fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welch} 115442fb503122d8cd428b5b1078bd473847ca2b206cMartyn WelchEXPORT_SYMBOL(vme_lm_request); 115542fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welch 115642fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welchint vme_lm_count(struct vme_resource *resource) 115742fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welch{ 115842fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welch struct vme_lm_resource *lm; 115942fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welch 116042fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welch if (resource->type != VME_LM) { 116142fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welch printk(KERN_ERR "Not a Location Monitor resource\n"); 116242fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welch return -EINVAL; 116342fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welch } 116442fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welch 116542fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welch lm = list_entry(resource->entry, struct vme_lm_resource, list); 116642fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welch 116742fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welch return lm->monitors; 116842fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welch} 116942fb503122d8cd428b5b1078bd473847ca2b206cMartyn WelchEXPORT_SYMBOL(vme_lm_count); 117042fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welch 117142fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welchint vme_lm_set(struct vme_resource *resource, unsigned long long lm_base, 11726af04b065b048e47bbd5a6f2d9776c08206ef26cMartyn Welch u32 aspace, u32 cycle) 117342fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welch{ 117442fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welch struct vme_bridge *bridge = find_bridge(resource); 117542fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welch struct vme_lm_resource *lm; 117642fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welch 117742fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welch if (resource->type != VME_LM) { 117842fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welch printk(KERN_ERR "Not a Location Monitor resource\n"); 1179a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch return -EINVAL; 1180a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch } 1181a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 118242fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welch lm = list_entry(resource->entry, struct vme_lm_resource, list); 118342fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welch 1184a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch if (bridge->lm_set == NULL) { 118542fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welch printk(KERN_ERR "vme_lm_set not supported\n"); 1186a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch return -EINVAL; 1187a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch } 1188a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 11898be9226c8f686c6dd2bae0a7ed4f5795e89d32d8Martyn Welch return bridge->lm_set(lm, lm_base, aspace, cycle); 1190a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch} 1191a17a75e2666f7175baac838bc4b6d11324dca3efMartyn WelchEXPORT_SYMBOL(vme_lm_set); 1192a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 119342fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welchint vme_lm_get(struct vme_resource *resource, unsigned long long *lm_base, 11946af04b065b048e47bbd5a6f2d9776c08206ef26cMartyn Welch u32 *aspace, u32 *cycle) 1195a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch{ 119642fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welch struct vme_bridge *bridge = find_bridge(resource); 119742fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welch struct vme_lm_resource *lm; 1198a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 119942fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welch if (resource->type != VME_LM) { 120042fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welch printk(KERN_ERR "Not a Location Monitor resource\n"); 1201a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch return -EINVAL; 1202a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch } 1203a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 120442fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welch lm = list_entry(resource->entry, struct vme_lm_resource, list); 120542fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welch 1206a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch if (bridge->lm_get == NULL) { 120742fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welch printk(KERN_ERR "vme_lm_get not supported\n"); 1208a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch return -EINVAL; 1209a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch } 1210a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 121142fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welch return bridge->lm_get(lm, lm_base, aspace, cycle); 1212a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch} 1213a17a75e2666f7175baac838bc4b6d11324dca3efMartyn WelchEXPORT_SYMBOL(vme_lm_get); 1214a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 121542fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welchint vme_lm_attach(struct vme_resource *resource, int monitor, 121642fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welch void (*callback)(int)) 1217a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch{ 121842fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welch struct vme_bridge *bridge = find_bridge(resource); 121942fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welch struct vme_lm_resource *lm; 1220a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 122142fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welch if (resource->type != VME_LM) { 122242fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welch printk(KERN_ERR "Not a Location Monitor resource\n"); 1223a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch return -EINVAL; 1224a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch } 1225a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 122642fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welch lm = list_entry(resource->entry, struct vme_lm_resource, list); 122742fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welch 1228a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch if (bridge->lm_attach == NULL) { 122942fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welch printk(KERN_ERR "vme_lm_attach not supported\n"); 1230a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch return -EINVAL; 1231a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch } 1232a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 123342fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welch return bridge->lm_attach(lm, monitor, callback); 1234a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch} 1235a17a75e2666f7175baac838bc4b6d11324dca3efMartyn WelchEXPORT_SYMBOL(vme_lm_attach); 1236a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 123742fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welchint vme_lm_detach(struct vme_resource *resource, int monitor) 1238a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch{ 123942fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welch struct vme_bridge *bridge = find_bridge(resource); 124042fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welch struct vme_lm_resource *lm; 1241a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 124242fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welch if (resource->type != VME_LM) { 124342fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welch printk(KERN_ERR "Not a Location Monitor resource\n"); 1244a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch return -EINVAL; 1245a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch } 1246a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 124742fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welch lm = list_entry(resource->entry, struct vme_lm_resource, list); 124842fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welch 1249a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch if (bridge->lm_detach == NULL) { 125042fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welch printk(KERN_ERR "vme_lm_detach not supported\n"); 1251a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch return -EINVAL; 1252a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch } 1253a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 125442fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welch return bridge->lm_detach(lm, monitor); 1255a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch} 1256a17a75e2666f7175baac838bc4b6d11324dca3efMartyn WelchEXPORT_SYMBOL(vme_lm_detach); 1257a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 125842fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welchvoid vme_lm_free(struct vme_resource *resource) 125942fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welch{ 126042fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welch struct vme_lm_resource *lm; 126142fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welch 126242fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welch if (resource->type != VME_LM) { 126342fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welch printk(KERN_ERR "Not a Location Monitor resource\n"); 126442fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welch return; 126542fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welch } 126642fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welch 126742fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welch lm = list_entry(resource->entry, struct vme_lm_resource, list); 126842fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welch 1269886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota mutex_lock(&lm->mtx); 127042fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welch 12718be9226c8f686c6dd2bae0a7ed4f5795e89d32d8Martyn Welch /* XXX 12728be9226c8f686c6dd2bae0a7ed4f5795e89d32d8Martyn Welch * Check to see that there aren't any callbacks still attached, if 12738be9226c8f686c6dd2bae0a7ed4f5795e89d32d8Martyn Welch * there are we should probably be detaching them! 12748be9226c8f686c6dd2bae0a7ed4f5795e89d32d8Martyn Welch */ 127542fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welch 127642fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welch lm->locked = 0; 127742fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welch 1278886953e9b70bcb6913716b49bdf21b69450a7cd6Emilio G. Cota mutex_unlock(&lm->mtx); 12798be9226c8f686c6dd2bae0a7ed4f5795e89d32d8Martyn Welch 12808be9226c8f686c6dd2bae0a7ed4f5795e89d32d8Martyn Welch kfree(resource); 128142fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welch} 128242fb503122d8cd428b5b1078bd473847ca2b206cMartyn WelchEXPORT_SYMBOL(vme_lm_free); 128342fb503122d8cd428b5b1078bd473847ca2b206cMartyn Welch 12848f966dc444b11adff6011a1d1fce424abdd876d8Manohar Vangaint vme_slot_get(struct vme_dev *vdev) 1285a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch{ 1286a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch struct vme_bridge *bridge; 1287a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 12888f966dc444b11adff6011a1d1fce424abdd876d8Manohar Vanga bridge = vdev->bridge; 1289a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch if (bridge == NULL) { 1290a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch printk(KERN_ERR "Can't find VME bus\n"); 1291a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch return -EINVAL; 1292a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch } 1293a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 1294a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch if (bridge->slot_get == NULL) { 1295ead1f3e301e2d886ef89f8d0c82b4d495f2a81c2Martyn Welch printk(KERN_WARNING "vme_slot_get not supported\n"); 1296a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch return -EINVAL; 1297a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch } 1298a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 129929848ac9f3b33bf171439ae2d66d40e6a71446c4Martyn Welch return bridge->slot_get(bridge); 1300a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch} 1301a17a75e2666f7175baac838bc4b6d11324dca3efMartyn WelchEXPORT_SYMBOL(vme_slot_get); 1302a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 1303a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 1304a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch/* - Bridge Registration --------------------------------------------------- */ 1305a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 13065b93c2a2f1d560463cbcd6e3fca5366b75e99b4bManohar Vangastatic void vme_dev_release(struct device *dev) 13075b93c2a2f1d560463cbcd6e3fca5366b75e99b4bManohar Vanga{ 13085b93c2a2f1d560463cbcd6e3fca5366b75e99b4bManohar Vanga kfree(dev_to_vme_dev(dev)); 13095b93c2a2f1d560463cbcd6e3fca5366b75e99b4bManohar Vanga} 13105b93c2a2f1d560463cbcd6e3fca5366b75e99b4bManohar Vanga 13115b93c2a2f1d560463cbcd6e3fca5366b75e99b4bManohar Vangaint vme_register_bridge(struct vme_bridge *bridge) 1312a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch{ 1313a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch int i; 1314733e3ef0d364b7e6757a897e7f1862a70c89305aManohar Vanga int ret = -1; 1315a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 1316733e3ef0d364b7e6757a897e7f1862a70c89305aManohar Vanga mutex_lock(&vme_buses_lock); 1317a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch for (i = 0; i < sizeof(vme_bus_numbers) * 8; i++) { 1318733e3ef0d364b7e6757a897e7f1862a70c89305aManohar Vanga if ((vme_bus_numbers & (1 << i)) == 0) { 1319733e3ef0d364b7e6757a897e7f1862a70c89305aManohar Vanga vme_bus_numbers |= (1 << i); 1320733e3ef0d364b7e6757a897e7f1862a70c89305aManohar Vanga bridge->num = i; 13215d6abf379d73efe390488e8edba972af4e93cb1cManohar Vanga INIT_LIST_HEAD(&bridge->devices); 1322733e3ef0d364b7e6757a897e7f1862a70c89305aManohar Vanga list_add_tail(&bridge->bus_list, &vme_bus_list); 1323733e3ef0d364b7e6757a897e7f1862a70c89305aManohar Vanga ret = 0; 1324a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch break; 1325a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch } 1326a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch } 1327733e3ef0d364b7e6757a897e7f1862a70c89305aManohar Vanga mutex_unlock(&vme_buses_lock); 1328a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 1329733e3ef0d364b7e6757a897e7f1862a70c89305aManohar Vanga return ret; 1330a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch} 13315b93c2a2f1d560463cbcd6e3fca5366b75e99b4bManohar VangaEXPORT_SYMBOL(vme_register_bridge); 1332a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 13335b93c2a2f1d560463cbcd6e3fca5366b75e99b4bManohar Vangavoid vme_unregister_bridge(struct vme_bridge *bridge) 1334a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch{ 13355d6abf379d73efe390488e8edba972af4e93cb1cManohar Vanga struct vme_dev *vdev; 13365d6abf379d73efe390488e8edba972af4e93cb1cManohar Vanga struct vme_dev *tmp; 13375d6abf379d73efe390488e8edba972af4e93cb1cManohar Vanga 1338733e3ef0d364b7e6757a897e7f1862a70c89305aManohar Vanga mutex_lock(&vme_buses_lock); 1339733e3ef0d364b7e6757a897e7f1862a70c89305aManohar Vanga vme_bus_numbers &= ~(1 << bridge->num); 13405d6abf379d73efe390488e8edba972af4e93cb1cManohar Vanga list_for_each_entry_safe(vdev, tmp, &bridge->devices, bridge_list) { 13415d6abf379d73efe390488e8edba972af4e93cb1cManohar Vanga list_del(&vdev->drv_list); 13425d6abf379d73efe390488e8edba972af4e93cb1cManohar Vanga list_del(&vdev->bridge_list); 13435d6abf379d73efe390488e8edba972af4e93cb1cManohar Vanga device_unregister(&vdev->dev); 13445d6abf379d73efe390488e8edba972af4e93cb1cManohar Vanga } 1345733e3ef0d364b7e6757a897e7f1862a70c89305aManohar Vanga list_del(&bridge->bus_list); 1346733e3ef0d364b7e6757a897e7f1862a70c89305aManohar Vanga mutex_unlock(&vme_buses_lock); 1347a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch} 13485d6abf379d73efe390488e8edba972af4e93cb1cManohar VangaEXPORT_SYMBOL(vme_unregister_bridge); 1349a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 13505d6abf379d73efe390488e8edba972af4e93cb1cManohar Vanga/* - Driver Registration --------------------------------------------------- */ 13515d6abf379d73efe390488e8edba972af4e93cb1cManohar Vanga 13525d6abf379d73efe390488e8edba972af4e93cb1cManohar Vangastatic int __vme_register_driver_bus(struct vme_driver *drv, 13535d6abf379d73efe390488e8edba972af4e93cb1cManohar Vanga struct vme_bridge *bridge, unsigned int ndevs) 13545d6abf379d73efe390488e8edba972af4e93cb1cManohar Vanga{ 13555d6abf379d73efe390488e8edba972af4e93cb1cManohar Vanga int err; 13565d6abf379d73efe390488e8edba972af4e93cb1cManohar Vanga unsigned int i; 13575d6abf379d73efe390488e8edba972af4e93cb1cManohar Vanga struct vme_dev *vdev; 13585d6abf379d73efe390488e8edba972af4e93cb1cManohar Vanga struct vme_dev *tmp; 13595d6abf379d73efe390488e8edba972af4e93cb1cManohar Vanga 13605d6abf379d73efe390488e8edba972af4e93cb1cManohar Vanga for (i = 0; i < ndevs; i++) { 13615d6abf379d73efe390488e8edba972af4e93cb1cManohar Vanga vdev = kzalloc(sizeof(struct vme_dev), GFP_KERNEL); 13625d6abf379d73efe390488e8edba972af4e93cb1cManohar Vanga if (!vdev) { 13635d6abf379d73efe390488e8edba972af4e93cb1cManohar Vanga err = -ENOMEM; 1364f6c39d4f2d350df049a844b658eb6b08c5833e51Manohar Vanga goto err_devalloc; 1365f6c39d4f2d350df049a844b658eb6b08c5833e51Manohar Vanga } 1366a916a391d3e19593a104a8c3c4779a3084f1ca5bManohar Vanga vdev->num = i; 13678f966dc444b11adff6011a1d1fce424abdd876d8Manohar Vanga vdev->bridge = bridge; 13685d6abf379d73efe390488e8edba972af4e93cb1cManohar Vanga vdev->dev.platform_data = drv; 13695d6abf379d73efe390488e8edba972af4e93cb1cManohar Vanga vdev->dev.release = vme_dev_release; 13708f966dc444b11adff6011a1d1fce424abdd876d8Manohar Vanga vdev->dev.parent = bridge->parent; 13718f966dc444b11adff6011a1d1fce424abdd876d8Manohar Vanga vdev->dev.bus = &vme_bus_type; 1372a916a391d3e19593a104a8c3c4779a3084f1ca5bManohar Vanga dev_set_name(&vdev->dev, "%s.%u-%u", drv->name, bridge->num, 1373a916a391d3e19593a104a8c3c4779a3084f1ca5bManohar Vanga vdev->num); 1374a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 13755d6abf379d73efe390488e8edba972af4e93cb1cManohar Vanga err = device_register(&vdev->dev); 13765d6abf379d73efe390488e8edba972af4e93cb1cManohar Vanga if (err) 1377a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch goto err_reg; 1378a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 13795d6abf379d73efe390488e8edba972af4e93cb1cManohar Vanga if (vdev->dev.platform_data) { 13805d6abf379d73efe390488e8edba972af4e93cb1cManohar Vanga list_add_tail(&vdev->drv_list, &drv->devices); 13815d6abf379d73efe390488e8edba972af4e93cb1cManohar Vanga list_add_tail(&vdev->bridge_list, &bridge->devices); 13825d6abf379d73efe390488e8edba972af4e93cb1cManohar Vanga } else 13835d6abf379d73efe390488e8edba972af4e93cb1cManohar Vanga device_unregister(&vdev->dev); 13845d6abf379d73efe390488e8edba972af4e93cb1cManohar Vanga } 13855d6abf379d73efe390488e8edba972af4e93cb1cManohar Vanga return 0; 1386a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 1387a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welcherr_reg: 13888f966dc444b11adff6011a1d1fce424abdd876d8Manohar Vanga kfree(vdev); 1389f6c39d4f2d350df049a844b658eb6b08c5833e51Manohar Vangaerr_devalloc: 13905d6abf379d73efe390488e8edba972af4e93cb1cManohar Vanga list_for_each_entry_safe(vdev, tmp, &drv->devices, drv_list) { 13915d6abf379d73efe390488e8edba972af4e93cb1cManohar Vanga list_del(&vdev->drv_list); 13925d6abf379d73efe390488e8edba972af4e93cb1cManohar Vanga list_del(&vdev->bridge_list); 13938f966dc444b11adff6011a1d1fce424abdd876d8Manohar Vanga device_unregister(&vdev->dev); 1394a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch } 13955d6abf379d73efe390488e8edba972af4e93cb1cManohar Vanga return err; 1396a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch} 1397a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 13985d6abf379d73efe390488e8edba972af4e93cb1cManohar Vangastatic int __vme_register_driver(struct vme_driver *drv, unsigned int ndevs) 1399a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch{ 14005d6abf379d73efe390488e8edba972af4e93cb1cManohar Vanga struct vme_bridge *bridge; 14015d6abf379d73efe390488e8edba972af4e93cb1cManohar Vanga int err = 0; 1402a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 14035d6abf379d73efe390488e8edba972af4e93cb1cManohar Vanga mutex_lock(&vme_buses_lock); 14045d6abf379d73efe390488e8edba972af4e93cb1cManohar Vanga list_for_each_entry(bridge, &vme_bus_list, bus_list) { 14055d6abf379d73efe390488e8edba972af4e93cb1cManohar Vanga /* 14065d6abf379d73efe390488e8edba972af4e93cb1cManohar Vanga * This cannot cause trouble as we already have vme_buses_lock 14075d6abf379d73efe390488e8edba972af4e93cb1cManohar Vanga * and if the bridge is removed, it will have to go through 14085d6abf379d73efe390488e8edba972af4e93cb1cManohar Vanga * vme_unregister_bridge() to do it (which calls remove() on 14095d6abf379d73efe390488e8edba972af4e93cb1cManohar Vanga * the bridge which in turn tries to acquire vme_buses_lock and 1410c26f6112990b90977db429596ed0640d153b3a32Manohar Vanga * will have to wait). 14115d6abf379d73efe390488e8edba972af4e93cb1cManohar Vanga */ 14125d6abf379d73efe390488e8edba972af4e93cb1cManohar Vanga err = __vme_register_driver_bus(drv, bridge, ndevs); 14135d6abf379d73efe390488e8edba972af4e93cb1cManohar Vanga if (err) 14145d6abf379d73efe390488e8edba972af4e93cb1cManohar Vanga break; 1415a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch } 14165d6abf379d73efe390488e8edba972af4e93cb1cManohar Vanga mutex_unlock(&vme_buses_lock); 14175d6abf379d73efe390488e8edba972af4e93cb1cManohar Vanga return err; 1418a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch} 1419a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 14205d6abf379d73efe390488e8edba972af4e93cb1cManohar Vangaint vme_register_driver(struct vme_driver *drv, unsigned int ndevs) 1421a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch{ 14225d6abf379d73efe390488e8edba972af4e93cb1cManohar Vanga int err; 14235d6abf379d73efe390488e8edba972af4e93cb1cManohar Vanga 1424a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch drv->driver.name = drv->name; 1425a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch drv->driver.bus = &vme_bus_type; 14265d6abf379d73efe390488e8edba972af4e93cb1cManohar Vanga INIT_LIST_HEAD(&drv->devices); 14275d6abf379d73efe390488e8edba972af4e93cb1cManohar Vanga 14285d6abf379d73efe390488e8edba972af4e93cb1cManohar Vanga err = driver_register(&drv->driver); 14295d6abf379d73efe390488e8edba972af4e93cb1cManohar Vanga if (err) 14305d6abf379d73efe390488e8edba972af4e93cb1cManohar Vanga return err; 1431a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 14325d6abf379d73efe390488e8edba972af4e93cb1cManohar Vanga err = __vme_register_driver(drv, ndevs); 14335d6abf379d73efe390488e8edba972af4e93cb1cManohar Vanga if (err) 14345d6abf379d73efe390488e8edba972af4e93cb1cManohar Vanga driver_unregister(&drv->driver); 14355d6abf379d73efe390488e8edba972af4e93cb1cManohar Vanga 14365d6abf379d73efe390488e8edba972af4e93cb1cManohar Vanga return err; 1437a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch} 1438a17a75e2666f7175baac838bc4b6d11324dca3efMartyn WelchEXPORT_SYMBOL(vme_register_driver); 1439a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 1440ead1f3e301e2d886ef89f8d0c82b4d495f2a81c2Martyn Welchvoid vme_unregister_driver(struct vme_driver *drv) 1441a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch{ 14425d6abf379d73efe390488e8edba972af4e93cb1cManohar Vanga struct vme_dev *dev, *dev_tmp; 14435d6abf379d73efe390488e8edba972af4e93cb1cManohar Vanga 14445d6abf379d73efe390488e8edba972af4e93cb1cManohar Vanga mutex_lock(&vme_buses_lock); 14455d6abf379d73efe390488e8edba972af4e93cb1cManohar Vanga list_for_each_entry_safe(dev, dev_tmp, &drv->devices, drv_list) { 14465d6abf379d73efe390488e8edba972af4e93cb1cManohar Vanga list_del(&dev->drv_list); 14475d6abf379d73efe390488e8edba972af4e93cb1cManohar Vanga list_del(&dev->bridge_list); 14485d6abf379d73efe390488e8edba972af4e93cb1cManohar Vanga device_unregister(&dev->dev); 14495d6abf379d73efe390488e8edba972af4e93cb1cManohar Vanga } 14505d6abf379d73efe390488e8edba972af4e93cb1cManohar Vanga mutex_unlock(&vme_buses_lock); 14515d6abf379d73efe390488e8edba972af4e93cb1cManohar Vanga 1452a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch driver_unregister(&drv->driver); 1453a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch} 1454a17a75e2666f7175baac838bc4b6d11324dca3efMartyn WelchEXPORT_SYMBOL(vme_unregister_driver); 1455a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 1456a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch/* - Bus Registration ------------------------------------------------------ */ 1457a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 1458a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welchstatic int vme_bus_match(struct device *dev, struct device_driver *drv) 1459a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch{ 14605d6abf379d73efe390488e8edba972af4e93cb1cManohar Vanga struct vme_driver *vme_drv; 1461a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 14625d6abf379d73efe390488e8edba972af4e93cb1cManohar Vanga vme_drv = container_of(drv, struct vme_driver, driver); 1463a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 14645d6abf379d73efe390488e8edba972af4e93cb1cManohar Vanga if (dev->platform_data == vme_drv) { 14655d6abf379d73efe390488e8edba972af4e93cb1cManohar Vanga struct vme_dev *vdev = dev_to_vme_dev(dev); 1466a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 14675d6abf379d73efe390488e8edba972af4e93cb1cManohar Vanga if (vme_drv->match && vme_drv->match(vdev)) 14685d6abf379d73efe390488e8edba972af4e93cb1cManohar Vanga return 1; 1469a37b0dad8b3d278fa64482ccd2381c947f432bf7Martyn Welch 14705d6abf379d73efe390488e8edba972af4e93cb1cManohar Vanga dev->platform_data = NULL; 1471a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch } 1472a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch return 0; 1473a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch} 1474a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 1475a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welchstatic int vme_bus_probe(struct device *dev) 1476a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch{ 1477a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch int retval = -ENODEV; 14785d6abf379d73efe390488e8edba972af4e93cb1cManohar Vanga struct vme_driver *driver; 14795d6abf379d73efe390488e8edba972af4e93cb1cManohar Vanga struct vme_dev *vdev = dev_to_vme_dev(dev); 1480a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 14815d6abf379d73efe390488e8edba972af4e93cb1cManohar Vanga driver = dev->platform_data; 1482a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 1483ead1f3e301e2d886ef89f8d0c82b4d495f2a81c2Martyn Welch if (driver->probe != NULL) 14848f966dc444b11adff6011a1d1fce424abdd876d8Manohar Vanga retval = driver->probe(vdev); 1485a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 1486a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch return retval; 1487a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch} 1488a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 1489a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welchstatic int vme_bus_remove(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->remove != NULL) 14988f966dc444b11adff6011a1d1fce424abdd876d8Manohar Vanga retval = driver->remove(vdev); 1499a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 1500a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch return retval; 1501a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch} 1502a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 1503a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welchstruct bus_type vme_bus_type = { 1504a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch .name = "vme", 1505a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch .match = vme_bus_match, 1506a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch .probe = vme_bus_probe, 1507a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch .remove = vme_bus_remove, 1508a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch}; 1509a17a75e2666f7175baac838bc4b6d11324dca3efMartyn WelchEXPORT_SYMBOL(vme_bus_type); 1510a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 1511ead1f3e301e2d886ef89f8d0c82b4d495f2a81c2Martyn Welchstatic int __init vme_init(void) 1512a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch{ 1513a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch return bus_register(&vme_bus_type); 1514a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch} 1515a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 1516ead1f3e301e2d886ef89f8d0c82b4d495f2a81c2Martyn Welchstatic void __exit vme_exit(void) 1517a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch{ 1518a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch bus_unregister(&vme_bus_type); 1519a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch} 1520a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 1521a17a75e2666f7175baac838bc4b6d11324dca3efMartyn WelchMODULE_DESCRIPTION("VME bridge driver framework"); 152266bd8db52ab48e7189e02d4bf1f23109cc1ede70Martyn WelchMODULE_AUTHOR("Martyn Welch <martyn.welch@ge.com"); 1523a17a75e2666f7175baac838bc4b6d11324dca3efMartyn WelchMODULE_LICENSE("GPL"); 1524a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welch 1525a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welchmodule_init(vme_init); 1526a17a75e2666f7175baac838bc4b6d11324dca3efMartyn Welchmodule_exit(vme_exit); 1527