1eb188d0eSMatt Porter /* 2eb188d0eSMatt Porter * RapidIO enumeration and discovery support 3eb188d0eSMatt Porter * 4eb188d0eSMatt Porter * Copyright 2005 MontaVista Software, Inc. 5eb188d0eSMatt Porter * Matt Porter <mporter@kernel.crashing.org> 6eb188d0eSMatt Porter * 7eb188d0eSMatt Porter * This program is free software; you can redistribute it and/or modify it 8eb188d0eSMatt Porter * under the terms of the GNU General Public License as published by the 9eb188d0eSMatt Porter * Free Software Foundation; either version 2 of the License, or (at your 10eb188d0eSMatt Porter * option) any later version. 11eb188d0eSMatt Porter */ 12eb188d0eSMatt Porter 13eb188d0eSMatt Porter #include <linux/types.h> 14eb188d0eSMatt Porter #include <linux/kernel.h> 15eb188d0eSMatt Porter 16eb188d0eSMatt Porter #include <linux/delay.h> 17fa78cc51SMatt Porter #include <linux/dma-mapping.h> 18eb188d0eSMatt Porter #include <linux/init.h> 19eb188d0eSMatt Porter #include <linux/rio.h> 20eb188d0eSMatt Porter #include <linux/rio_drv.h> 21eb188d0eSMatt Porter #include <linux/rio_ids.h> 22eb188d0eSMatt Porter #include <linux/rio_regs.h> 23eb188d0eSMatt Porter #include <linux/module.h> 24eb188d0eSMatt Porter #include <linux/spinlock.h> 25eb188d0eSMatt Porter #include <linux/timer.h> 26de25968cSTim Schmielau #include <linux/jiffies.h> 27de25968cSTim Schmielau #include <linux/slab.h> 28eb188d0eSMatt Porter 29eb188d0eSMatt Porter #include "rio.h" 30eb188d0eSMatt Porter 31eb188d0eSMatt Porter LIST_HEAD(rio_devices); 32eb188d0eSMatt Porter static LIST_HEAD(rio_switches); 33eb188d0eSMatt Porter 34eb188d0eSMatt Porter #define RIO_ENUM_CMPL_MAGIC 0xdeadbeef 35eb188d0eSMatt Porter 36eb188d0eSMatt Porter static void rio_enum_timeout(unsigned long); 37eb188d0eSMatt Porter 38fa78cc51SMatt Porter DEFINE_SPINLOCK(rio_global_list_lock); 39fa78cc51SMatt Porter 40eb188d0eSMatt Porter static int next_destid = 0; 41eb188d0eSMatt Porter static int next_switchid = 0; 42eb188d0eSMatt Porter static int next_net = 0; 43eb188d0eSMatt Porter 44eb188d0eSMatt Porter static struct timer_list rio_enum_timer = 45eb188d0eSMatt Porter TIMER_INITIALIZER(rio_enum_timeout, 0, 0); 46eb188d0eSMatt Porter 47eb188d0eSMatt Porter static int rio_mport_phys_table[] = { 48eb188d0eSMatt Porter RIO_EFB_PAR_EP_ID, 49eb188d0eSMatt Porter RIO_EFB_PAR_EP_REC_ID, 50eb188d0eSMatt Porter RIO_EFB_SER_EP_ID, 51eb188d0eSMatt Porter RIO_EFB_SER_EP_REC_ID, 52eb188d0eSMatt Porter -1, 53eb188d0eSMatt Porter }; 54eb188d0eSMatt Porter 55eb188d0eSMatt Porter static int rio_sport_phys_table[] = { 56eb188d0eSMatt Porter RIO_EFB_PAR_EP_FREE_ID, 57eb188d0eSMatt Porter RIO_EFB_SER_EP_FREE_ID, 58eb188d0eSMatt Porter -1, 59eb188d0eSMatt Porter }; 60eb188d0eSMatt Porter 61eb188d0eSMatt Porter /** 62eb188d0eSMatt Porter * rio_get_device_id - Get the base/extended device id for a device 63eb188d0eSMatt Porter * @port: RIO master port 64eb188d0eSMatt Porter * @destid: Destination ID of device 65eb188d0eSMatt Porter * @hopcount: Hopcount to device 66eb188d0eSMatt Porter * 67eb188d0eSMatt Porter * Reads the base/extended device id from a device. Returns the 68eb188d0eSMatt Porter * 8/16-bit device ID. 69eb188d0eSMatt Porter */ 70eb188d0eSMatt Porter static u16 rio_get_device_id(struct rio_mport *port, u16 destid, u8 hopcount) 71eb188d0eSMatt Porter { 72eb188d0eSMatt Porter u32 result; 73eb188d0eSMatt Porter 74eb188d0eSMatt Porter rio_mport_read_config_32(port, destid, hopcount, RIO_DID_CSR, &result); 75eb188d0eSMatt Porter 76eb188d0eSMatt Porter return RIO_GET_DID(result); 77eb188d0eSMatt Porter } 78eb188d0eSMatt Porter 79eb188d0eSMatt Porter /** 80eb188d0eSMatt Porter * rio_set_device_id - Set the base/extended device id for a device 81eb188d0eSMatt Porter * @port: RIO master port 82eb188d0eSMatt Porter * @destid: Destination ID of device 83eb188d0eSMatt Porter * @hopcount: Hopcount to device 84eb188d0eSMatt Porter * @did: Device ID value to be written 85eb188d0eSMatt Porter * 86eb188d0eSMatt Porter * Writes the base/extended device id from a device. 87eb188d0eSMatt Porter */ 88fa78cc51SMatt Porter static void rio_set_device_id(struct rio_mport *port, u16 destid, u8 hopcount, u16 did) 89eb188d0eSMatt Porter { 90eb188d0eSMatt Porter rio_mport_write_config_32(port, destid, hopcount, RIO_DID_CSR, 91eb188d0eSMatt Porter RIO_SET_DID(did)); 92eb188d0eSMatt Porter } 93eb188d0eSMatt Porter 94eb188d0eSMatt Porter /** 95eb188d0eSMatt Porter * rio_local_set_device_id - Set the base/extended device id for a port 96eb188d0eSMatt Porter * @port: RIO master port 97eb188d0eSMatt Porter * @did: Device ID value to be written 98eb188d0eSMatt Porter * 99eb188d0eSMatt Porter * Writes the base/extended device id from a device. 100eb188d0eSMatt Porter */ 101eb188d0eSMatt Porter static void rio_local_set_device_id(struct rio_mport *port, u16 did) 102eb188d0eSMatt Porter { 103eb188d0eSMatt Porter rio_local_write_config_32(port, RIO_DID_CSR, RIO_SET_DID(did)); 104eb188d0eSMatt Porter } 105eb188d0eSMatt Porter 106eb188d0eSMatt Porter /** 107eb188d0eSMatt Porter * rio_clear_locks- Release all host locks and signal enumeration complete 108eb188d0eSMatt Porter * @port: Master port to issue transaction 109eb188d0eSMatt Porter * 110eb188d0eSMatt Porter * Marks the component tag CSR on each device with the enumeration 111eb188d0eSMatt Porter * complete flag. When complete, it then release the host locks on 112eb188d0eSMatt Porter * each device. Returns 0 on success or %-EINVAL on failure. 113eb188d0eSMatt Porter */ 114eb188d0eSMatt Porter static int rio_clear_locks(struct rio_mport *port) 115eb188d0eSMatt Porter { 116eb188d0eSMatt Porter struct rio_dev *rdev; 117eb188d0eSMatt Porter u32 result; 118eb188d0eSMatt Porter int ret = 0; 119eb188d0eSMatt Porter 120eb188d0eSMatt Porter /* Write component tag CSR magic complete value */ 121eb188d0eSMatt Porter rio_local_write_config_32(port, RIO_COMPONENT_TAG_CSR, 122eb188d0eSMatt Porter RIO_ENUM_CMPL_MAGIC); 123eb188d0eSMatt Porter list_for_each_entry(rdev, &rio_devices, global_list) 124eb188d0eSMatt Porter rio_write_config_32(rdev, RIO_COMPONENT_TAG_CSR, 125eb188d0eSMatt Porter RIO_ENUM_CMPL_MAGIC); 126eb188d0eSMatt Porter 127eb188d0eSMatt Porter /* Release host device id locks */ 128eb188d0eSMatt Porter rio_local_write_config_32(port, RIO_HOST_DID_LOCK_CSR, 129eb188d0eSMatt Porter port->host_deviceid); 130eb188d0eSMatt Porter rio_local_read_config_32(port, RIO_HOST_DID_LOCK_CSR, &result); 131eb188d0eSMatt Porter if ((result & 0xffff) != 0xffff) { 132eb188d0eSMatt Porter printk(KERN_INFO 133eb188d0eSMatt Porter "RIO: badness when releasing host lock on master port, result %8.8x\n", 134eb188d0eSMatt Porter result); 135eb188d0eSMatt Porter ret = -EINVAL; 136eb188d0eSMatt Porter } 137eb188d0eSMatt Porter list_for_each_entry(rdev, &rio_devices, global_list) { 138eb188d0eSMatt Porter rio_write_config_32(rdev, RIO_HOST_DID_LOCK_CSR, 139eb188d0eSMatt Porter port->host_deviceid); 140eb188d0eSMatt Porter rio_read_config_32(rdev, RIO_HOST_DID_LOCK_CSR, &result); 141eb188d0eSMatt Porter if ((result & 0xffff) != 0xffff) { 142eb188d0eSMatt Porter printk(KERN_INFO 143eb188d0eSMatt Porter "RIO: badness when releasing host lock on vid %4.4x did %4.4x\n", 144eb188d0eSMatt Porter rdev->vid, rdev->did); 145eb188d0eSMatt Porter ret = -EINVAL; 146eb188d0eSMatt Porter } 147eb188d0eSMatt Porter } 148eb188d0eSMatt Porter 149eb188d0eSMatt Porter return ret; 150eb188d0eSMatt Porter } 151eb188d0eSMatt Porter 152eb188d0eSMatt Porter /** 153eb188d0eSMatt Porter * rio_enum_host- Set host lock and initialize host destination ID 154eb188d0eSMatt Porter * @port: Master port to issue transaction 155eb188d0eSMatt Porter * 156eb188d0eSMatt Porter * Sets the local host master port lock and destination ID register 157eb188d0eSMatt Porter * with the host device ID value. The host device ID value is provided 158eb188d0eSMatt Porter * by the platform. Returns %0 on success or %-1 on failure. 159eb188d0eSMatt Porter */ 160eb188d0eSMatt Porter static int rio_enum_host(struct rio_mport *port) 161eb188d0eSMatt Porter { 162eb188d0eSMatt Porter u32 result; 163eb188d0eSMatt Porter 164eb188d0eSMatt Porter /* Set master port host device id lock */ 165eb188d0eSMatt Porter rio_local_write_config_32(port, RIO_HOST_DID_LOCK_CSR, 166eb188d0eSMatt Porter port->host_deviceid); 167eb188d0eSMatt Porter 168eb188d0eSMatt Porter rio_local_read_config_32(port, RIO_HOST_DID_LOCK_CSR, &result); 169eb188d0eSMatt Porter if ((result & 0xffff) != port->host_deviceid) 170eb188d0eSMatt Porter return -1; 171eb188d0eSMatt Porter 172eb188d0eSMatt Porter /* Set master port destid and init destid ctr */ 173eb188d0eSMatt Porter rio_local_set_device_id(port, port->host_deviceid); 174eb188d0eSMatt Porter 175eb188d0eSMatt Porter if (next_destid == port->host_deviceid) 176eb188d0eSMatt Porter next_destid++; 177eb188d0eSMatt Porter 178eb188d0eSMatt Porter return 0; 179eb188d0eSMatt Porter } 180eb188d0eSMatt Porter 181eb188d0eSMatt Porter /** 182eb188d0eSMatt Porter * rio_device_has_destid- Test if a device contains a destination ID register 183eb188d0eSMatt Porter * @port: Master port to issue transaction 184eb188d0eSMatt Porter * @src_ops: RIO device source operations 185eb188d0eSMatt Porter * @dst_ops: RIO device destination operations 186eb188d0eSMatt Porter * 187eb188d0eSMatt Porter * Checks the provided @src_ops and @dst_ops for the necessary transaction 188eb188d0eSMatt Porter * capabilities that indicate whether or not a device will implement a 189eb188d0eSMatt Porter * destination ID register. Returns 1 if true or 0 if false. 190eb188d0eSMatt Porter */ 191eb188d0eSMatt Porter static int rio_device_has_destid(struct rio_mport *port, int src_ops, 192eb188d0eSMatt Porter int dst_ops) 193eb188d0eSMatt Porter { 194fa78cc51SMatt Porter u32 mask = RIO_OPS_READ | RIO_OPS_WRITE | RIO_OPS_ATOMIC_TST_SWP | RIO_OPS_ATOMIC_INC | RIO_OPS_ATOMIC_DEC | RIO_OPS_ATOMIC_SET | RIO_OPS_ATOMIC_CLR; 195fa78cc51SMatt Porter 196fa78cc51SMatt Porter return !!((src_ops | dst_ops) & mask); 197eb188d0eSMatt Porter } 198eb188d0eSMatt Porter 199eb188d0eSMatt Porter /** 200eb188d0eSMatt Porter * rio_release_dev- Frees a RIO device struct 201eb188d0eSMatt Porter * @dev: LDM device associated with a RIO device struct 202eb188d0eSMatt Porter * 203eb188d0eSMatt Porter * Gets the RIO device struct associated a RIO device struct. 204eb188d0eSMatt Porter * The RIO device struct is freed. 205eb188d0eSMatt Porter */ 206eb188d0eSMatt Porter static void rio_release_dev(struct device *dev) 207eb188d0eSMatt Porter { 208eb188d0eSMatt Porter struct rio_dev *rdev; 209eb188d0eSMatt Porter 210eb188d0eSMatt Porter rdev = to_rio_dev(dev); 211eb188d0eSMatt Porter kfree(rdev); 212eb188d0eSMatt Porter } 213eb188d0eSMatt Porter 214eb188d0eSMatt Porter /** 215eb188d0eSMatt Porter * rio_is_switch- Tests if a RIO device has switch capabilities 216eb188d0eSMatt Porter * @rdev: RIO device 217eb188d0eSMatt Porter * 218eb188d0eSMatt Porter * Gets the RIO device Processing Element Features register 219eb188d0eSMatt Porter * contents and tests for switch capabilities. Returns 1 if 220eb188d0eSMatt Porter * the device is a switch or 0 if it is not a switch. 221eb188d0eSMatt Porter * The RIO device struct is freed. 222eb188d0eSMatt Porter */ 223eb188d0eSMatt Porter static int rio_is_switch(struct rio_dev *rdev) 224eb188d0eSMatt Porter { 225eb188d0eSMatt Porter if (rdev->pef & RIO_PEF_SWITCH) 226eb188d0eSMatt Porter return 1; 227eb188d0eSMatt Porter return 0; 228eb188d0eSMatt Porter } 229eb188d0eSMatt Porter 230eb188d0eSMatt Porter /** 231eb188d0eSMatt Porter * rio_route_set_ops- Sets routing operations for a particular vendor switch 232eb188d0eSMatt Porter * @rdev: RIO device 233eb188d0eSMatt Porter * 234eb188d0eSMatt Porter * Searches the RIO route ops table for known switch types. If the vid 235eb188d0eSMatt Porter * and did match a switch table entry, then set the add_entry() and 236eb188d0eSMatt Porter * get_entry() ops to the table entry values. 237eb188d0eSMatt Porter */ 238eb188d0eSMatt Porter static void rio_route_set_ops(struct rio_dev *rdev) 239eb188d0eSMatt Porter { 240eb188d0eSMatt Porter struct rio_route_ops *cur = __start_rio_route_ops; 241eb188d0eSMatt Porter struct rio_route_ops *end = __end_rio_route_ops; 242eb188d0eSMatt Porter 243eb188d0eSMatt Porter while (cur < end) { 244eb188d0eSMatt Porter if ((cur->vid == rdev->vid) && (cur->did == rdev->did)) { 245eb188d0eSMatt Porter pr_debug("RIO: adding routing ops for %s\n", rio_name(rdev)); 246eb188d0eSMatt Porter rdev->rswitch->add_entry = cur->add_hook; 247eb188d0eSMatt Porter rdev->rswitch->get_entry = cur->get_hook; 248eb188d0eSMatt Porter } 249eb188d0eSMatt Porter cur++; 250eb188d0eSMatt Porter } 251eb188d0eSMatt Porter 252eb188d0eSMatt Porter if (!rdev->rswitch->add_entry || !rdev->rswitch->get_entry) 253eb188d0eSMatt Porter printk(KERN_ERR "RIO: missing routing ops for %s\n", 254eb188d0eSMatt Porter rio_name(rdev)); 255eb188d0eSMatt Porter } 256eb188d0eSMatt Porter 257eb188d0eSMatt Porter /** 258eb188d0eSMatt Porter * rio_add_device- Adds a RIO device to the device model 259eb188d0eSMatt Porter * @rdev: RIO device 260eb188d0eSMatt Porter * 261eb188d0eSMatt Porter * Adds the RIO device to the global device list and adds the RIO 262eb188d0eSMatt Porter * device to the RIO device list. Creates the generic sysfs nodes 263eb188d0eSMatt Porter * for an RIO device. 264eb188d0eSMatt Porter */ 265eb188d0eSMatt Porter static void __devinit rio_add_device(struct rio_dev *rdev) 266eb188d0eSMatt Porter { 267eb188d0eSMatt Porter device_add(&rdev->dev); 268eb188d0eSMatt Porter 269eb188d0eSMatt Porter spin_lock(&rio_global_list_lock); 270eb188d0eSMatt Porter list_add_tail(&rdev->global_list, &rio_devices); 271eb188d0eSMatt Porter spin_unlock(&rio_global_list_lock); 272eb188d0eSMatt Porter 273eb188d0eSMatt Porter rio_create_sysfs_dev_files(rdev); 274eb188d0eSMatt Porter } 275eb188d0eSMatt Porter 276eb188d0eSMatt Porter /** 277eb188d0eSMatt Porter * rio_setup_device- Allocates and sets up a RIO device 278eb188d0eSMatt Porter * @net: RIO network 279eb188d0eSMatt Porter * @port: Master port to send transactions 280eb188d0eSMatt Porter * @destid: Current destination ID 281eb188d0eSMatt Porter * @hopcount: Current hopcount 282eb188d0eSMatt Porter * @do_enum: Enumeration/Discovery mode flag 283eb188d0eSMatt Porter * 284eb188d0eSMatt Porter * Allocates a RIO device and configures fields based on configuration 285eb188d0eSMatt Porter * space contents. If device has a destination ID register, a destination 286eb188d0eSMatt Porter * ID is either assigned in enumeration mode or read from configuration 287eb188d0eSMatt Porter * space in discovery mode. If the device has switch capabilities, then 288eb188d0eSMatt Porter * a switch is allocated and configured appropriately. Returns a pointer 289eb188d0eSMatt Porter * to a RIO device on success or NULL on failure. 290eb188d0eSMatt Porter * 291eb188d0eSMatt Porter */ 292eb188d0eSMatt Porter static struct rio_dev *rio_setup_device(struct rio_net *net, 293eb188d0eSMatt Porter struct rio_mport *port, u16 destid, 294eb188d0eSMatt Porter u8 hopcount, int do_enum) 295eb188d0eSMatt Porter { 296eb188d0eSMatt Porter struct rio_dev *rdev; 297eb188d0eSMatt Porter struct rio_switch *rswitch; 298eb188d0eSMatt Porter int result, rdid; 299eb188d0eSMatt Porter 300dd00cc48SYoann Padioleau rdev = kzalloc(sizeof(struct rio_dev), GFP_KERNEL); 301eb188d0eSMatt Porter if (!rdev) 302eb188d0eSMatt Porter goto out; 303eb188d0eSMatt Porter 304eb188d0eSMatt Porter rdev->net = net; 305eb188d0eSMatt Porter rio_mport_read_config_32(port, destid, hopcount, RIO_DEV_ID_CAR, 306eb188d0eSMatt Porter &result); 307eb188d0eSMatt Porter rdev->did = result >> 16; 308eb188d0eSMatt Porter rdev->vid = result & 0xffff; 309eb188d0eSMatt Porter rio_mport_read_config_32(port, destid, hopcount, RIO_DEV_INFO_CAR, 310eb188d0eSMatt Porter &rdev->device_rev); 311eb188d0eSMatt Porter rio_mport_read_config_32(port, destid, hopcount, RIO_ASM_ID_CAR, 312eb188d0eSMatt Porter &result); 313eb188d0eSMatt Porter rdev->asm_did = result >> 16; 314eb188d0eSMatt Porter rdev->asm_vid = result & 0xffff; 315eb188d0eSMatt Porter rio_mport_read_config_32(port, destid, hopcount, RIO_ASM_INFO_CAR, 316eb188d0eSMatt Porter &result); 317eb188d0eSMatt Porter rdev->asm_rev = result >> 16; 318eb188d0eSMatt Porter rio_mport_read_config_32(port, destid, hopcount, RIO_PEF_CAR, 319eb188d0eSMatt Porter &rdev->pef); 320eb188d0eSMatt Porter if (rdev->pef & RIO_PEF_EXT_FEATURES) 321eb188d0eSMatt Porter rdev->efptr = result & 0xffff; 322eb188d0eSMatt Porter 323eb188d0eSMatt Porter rio_mport_read_config_32(port, destid, hopcount, RIO_SRC_OPS_CAR, 324eb188d0eSMatt Porter &rdev->src_ops); 325eb188d0eSMatt Porter rio_mport_read_config_32(port, destid, hopcount, RIO_DST_OPS_CAR, 326eb188d0eSMatt Porter &rdev->dst_ops); 327eb188d0eSMatt Porter 328c70555b0SAlexandre Bounine if (rio_device_has_destid(port, rdev->src_ops, rdev->dst_ops)) { 329c70555b0SAlexandre Bounine if (do_enum) { 330eb188d0eSMatt Porter rio_set_device_id(port, destid, hopcount, next_destid); 331eb188d0eSMatt Porter rdev->destid = next_destid++; 332eb188d0eSMatt Porter if (next_destid == port->host_deviceid) 333eb188d0eSMatt Porter next_destid++; 334eb188d0eSMatt Porter } else 335eb188d0eSMatt Porter rdev->destid = rio_get_device_id(port, destid, hopcount); 336c70555b0SAlexandre Bounine } else 337c70555b0SAlexandre Bounine /* Switch device has an associated destID */ 338c70555b0SAlexandre Bounine rdev->destid = RIO_INVALID_DESTID; 339eb188d0eSMatt Porter 340eb188d0eSMatt Porter /* If a PE has both switch and other functions, show it as a switch */ 341eb188d0eSMatt Porter if (rio_is_switch(rdev)) { 342eb188d0eSMatt Porter rio_mport_read_config_32(port, destid, hopcount, 343eb188d0eSMatt Porter RIO_SWP_INFO_CAR, &rdev->swpinfo); 344eb188d0eSMatt Porter rswitch = kmalloc(sizeof(struct rio_switch), GFP_KERNEL); 345eb188d0eSMatt Porter if (!rswitch) { 346eb188d0eSMatt Porter kfree(rdev); 347eb188d0eSMatt Porter rdev = NULL; 348eb188d0eSMatt Porter goto out; 349eb188d0eSMatt Porter } 350eb188d0eSMatt Porter rswitch->switchid = next_switchid; 351eb188d0eSMatt Porter rswitch->hopcount = hopcount; 352c70555b0SAlexandre Bounine rswitch->destid = destid; 353eb188d0eSMatt Porter /* Initialize switch route table */ 354eb188d0eSMatt Porter for (rdid = 0; rdid < RIO_MAX_ROUTE_ENTRIES; rdid++) 355eb188d0eSMatt Porter rswitch->route_table[rdid] = RIO_INVALID_ROUTE; 356eb188d0eSMatt Porter rdev->rswitch = rswitch; 357eb188d0eSMatt Porter sprintf(rio_name(rdev), "%02x:s:%04x", rdev->net->id, 358eb188d0eSMatt Porter rdev->rswitch->switchid); 359eb188d0eSMatt Porter rio_route_set_ops(rdev); 360eb188d0eSMatt Porter 361eb188d0eSMatt Porter list_add_tail(&rswitch->node, &rio_switches); 362eb188d0eSMatt Porter 363eb188d0eSMatt Porter } else 364eb188d0eSMatt Porter sprintf(rio_name(rdev), "%02x:e:%04x", rdev->net->id, 365eb188d0eSMatt Porter rdev->destid); 366eb188d0eSMatt Porter 367eb188d0eSMatt Porter rdev->dev.bus = &rio_bus_type; 368eb188d0eSMatt Porter 369eb188d0eSMatt Porter device_initialize(&rdev->dev); 370eb188d0eSMatt Porter rdev->dev.release = rio_release_dev; 371eb188d0eSMatt Porter rio_dev_get(rdev); 372eb188d0eSMatt Porter 373fa78cc51SMatt Porter rdev->dma_mask = DMA_32BIT_MASK; 374fa78cc51SMatt Porter rdev->dev.dma_mask = &rdev->dma_mask; 375fa78cc51SMatt Porter rdev->dev.coherent_dma_mask = DMA_32BIT_MASK; 376eb188d0eSMatt Porter 377eb188d0eSMatt Porter if ((rdev->pef & RIO_PEF_INB_DOORBELL) && 378eb188d0eSMatt Porter (rdev->dst_ops & RIO_DST_OPS_DOORBELL)) 379eb188d0eSMatt Porter rio_init_dbell_res(&rdev->riores[RIO_DOORBELL_RESOURCE], 380eb188d0eSMatt Porter 0, 0xffff); 381eb188d0eSMatt Porter 382eb188d0eSMatt Porter rio_add_device(rdev); 383eb188d0eSMatt Porter 384eb188d0eSMatt Porter out: 385eb188d0eSMatt Porter return rdev; 386eb188d0eSMatt Porter } 387eb188d0eSMatt Porter 388eb188d0eSMatt Porter /** 389eb188d0eSMatt Porter * rio_sport_is_active- Tests if a switch port has an active connection. 390eb188d0eSMatt Porter * @port: Master port to send transaction 391eb188d0eSMatt Porter * @destid: Associated destination ID for switch 392eb188d0eSMatt Porter * @hopcount: Hopcount to reach switch 393eb188d0eSMatt Porter * @sport: Switch port number 394eb188d0eSMatt Porter * 395eb188d0eSMatt Porter * Reads the port error status CSR for a particular switch port to 396eb188d0eSMatt Porter * determine if the port has an active link. Returns 397eb188d0eSMatt Porter * %PORT_N_ERR_STS_PORT_OK if the port is active or %0 if it is 398eb188d0eSMatt Porter * inactive. 399eb188d0eSMatt Porter */ 400eb188d0eSMatt Porter static int 401eb188d0eSMatt Porter rio_sport_is_active(struct rio_mport *port, u16 destid, u8 hopcount, int sport) 402eb188d0eSMatt Porter { 403eb188d0eSMatt Porter u32 result; 404eb188d0eSMatt Porter u32 ext_ftr_ptr; 405eb188d0eSMatt Porter 406eb188d0eSMatt Porter int *entry = rio_sport_phys_table; 407eb188d0eSMatt Porter 408eb188d0eSMatt Porter do { 409eb188d0eSMatt Porter if ((ext_ftr_ptr = 410eb188d0eSMatt Porter rio_mport_get_feature(port, 0, destid, hopcount, *entry))) 411eb188d0eSMatt Porter 412eb188d0eSMatt Porter break; 413eb188d0eSMatt Porter } while (*++entry >= 0); 414eb188d0eSMatt Porter 415eb188d0eSMatt Porter if (ext_ftr_ptr) 416eb188d0eSMatt Porter rio_mport_read_config_32(port, destid, hopcount, 417eb188d0eSMatt Porter ext_ftr_ptr + 418eb188d0eSMatt Porter RIO_PORT_N_ERR_STS_CSR(sport), 419eb188d0eSMatt Porter &result); 420eb188d0eSMatt Porter 421eb188d0eSMatt Porter return (result & PORT_N_ERR_STS_PORT_OK); 422eb188d0eSMatt Porter } 423eb188d0eSMatt Porter 424eb188d0eSMatt Porter /** 425eb188d0eSMatt Porter * rio_route_add_entry- Add a route entry to a switch routing table 426eb188d0eSMatt Porter * @mport: Master port to send transaction 427c70555b0SAlexandre Bounine * @rswitch: Switch device 428eb188d0eSMatt Porter * @table: Routing table ID 429eb188d0eSMatt Porter * @route_destid: Destination ID to be routed 430eb188d0eSMatt Porter * @route_port: Port number to be routed 431eb188d0eSMatt Porter * 432eb188d0eSMatt Porter * Calls the switch specific add_entry() method to add a route entry 433eb188d0eSMatt Porter * on a switch. The route table can be specified using the @table 434eb188d0eSMatt Porter * argument if a switch has per port routing tables or the normal 435eb188d0eSMatt Porter * use is to specific all tables (or the global table) by passing 436eb188d0eSMatt Porter * %RIO_GLOBAL_TABLE in @table. Returns %0 on success or %-EINVAL 437eb188d0eSMatt Porter * on failure. 438eb188d0eSMatt Porter */ 439c70555b0SAlexandre Bounine static int rio_route_add_entry(struct rio_mport *mport, struct rio_switch *rswitch, 440eb188d0eSMatt Porter u16 table, u16 route_destid, u8 route_port) 441eb188d0eSMatt Porter { 442c70555b0SAlexandre Bounine return rswitch->add_entry(mport, rswitch->destid, 443c70555b0SAlexandre Bounine rswitch->hopcount, table, 444eb188d0eSMatt Porter route_destid, route_port); 445eb188d0eSMatt Porter } 446eb188d0eSMatt Porter 447eb188d0eSMatt Porter /** 448eb188d0eSMatt Porter * rio_route_get_entry- Read a route entry in a switch routing table 449eb188d0eSMatt Porter * @mport: Master port to send transaction 450c70555b0SAlexandre Bounine * @rswitch: Switch device 451eb188d0eSMatt Porter * @table: Routing table ID 452eb188d0eSMatt Porter * @route_destid: Destination ID to be routed 453eb188d0eSMatt Porter * @route_port: Pointer to read port number into 454eb188d0eSMatt Porter * 455eb188d0eSMatt Porter * Calls the switch specific get_entry() method to read a route entry 456eb188d0eSMatt Porter * in a switch. The route table can be specified using the @table 457eb188d0eSMatt Porter * argument if a switch has per port routing tables or the normal 458eb188d0eSMatt Porter * use is to specific all tables (or the global table) by passing 459eb188d0eSMatt Porter * %RIO_GLOBAL_TABLE in @table. Returns %0 on success or %-EINVAL 460eb188d0eSMatt Porter * on failure. 461eb188d0eSMatt Porter */ 462eb188d0eSMatt Porter static int 463c70555b0SAlexandre Bounine rio_route_get_entry(struct rio_mport *mport, struct rio_switch *rswitch, u16 table, 464eb188d0eSMatt Porter u16 route_destid, u8 * route_port) 465eb188d0eSMatt Porter { 466c70555b0SAlexandre Bounine return rswitch->get_entry(mport, rswitch->destid, 467c70555b0SAlexandre Bounine rswitch->hopcount, table, 468eb188d0eSMatt Porter route_destid, route_port); 469eb188d0eSMatt Porter } 470eb188d0eSMatt Porter 471eb188d0eSMatt Porter /** 472eb188d0eSMatt Porter * rio_get_host_deviceid_lock- Reads the Host Device ID Lock CSR on a device 473eb188d0eSMatt Porter * @port: Master port to send transaction 474eb188d0eSMatt Porter * @hopcount: Number of hops to the device 475eb188d0eSMatt Porter * 476eb188d0eSMatt Porter * Used during enumeration to read the Host Device ID Lock CSR on a 477eb188d0eSMatt Porter * RIO device. Returns the value of the lock register. 478eb188d0eSMatt Porter */ 479eb188d0eSMatt Porter static u16 rio_get_host_deviceid_lock(struct rio_mport *port, u8 hopcount) 480eb188d0eSMatt Porter { 481eb188d0eSMatt Porter u32 result; 482eb188d0eSMatt Porter 483eb188d0eSMatt Porter rio_mport_read_config_32(port, RIO_ANY_DESTID, hopcount, 484eb188d0eSMatt Porter RIO_HOST_DID_LOCK_CSR, &result); 485eb188d0eSMatt Porter 486eb188d0eSMatt Porter return (u16) (result & 0xffff); 487eb188d0eSMatt Porter } 488eb188d0eSMatt Porter 489eb188d0eSMatt Porter /** 490eb188d0eSMatt Porter * rio_get_swpinfo_inport- Gets the ingress port number 491eb188d0eSMatt Porter * @mport: Master port to send transaction 492eb188d0eSMatt Porter * @destid: Destination ID associated with the switch 493eb188d0eSMatt Porter * @hopcount: Number of hops to the device 494eb188d0eSMatt Porter * 495eb188d0eSMatt Porter * Returns port number being used to access the switch device. 496eb188d0eSMatt Porter */ 497eb188d0eSMatt Porter static u8 498eb188d0eSMatt Porter rio_get_swpinfo_inport(struct rio_mport *mport, u16 destid, u8 hopcount) 499eb188d0eSMatt Porter { 500eb188d0eSMatt Porter u32 result; 501eb188d0eSMatt Porter 502eb188d0eSMatt Porter rio_mport_read_config_32(mport, destid, hopcount, RIO_SWP_INFO_CAR, 503eb188d0eSMatt Porter &result); 504eb188d0eSMatt Porter 505eb188d0eSMatt Porter return (u8) (result & 0xff); 506eb188d0eSMatt Porter } 507eb188d0eSMatt Porter 508eb188d0eSMatt Porter /** 509eb188d0eSMatt Porter * rio_get_swpinfo_tports- Gets total number of ports on the switch 510eb188d0eSMatt Porter * @mport: Master port to send transaction 511eb188d0eSMatt Porter * @destid: Destination ID associated with the switch 512eb188d0eSMatt Porter * @hopcount: Number of hops to the device 513eb188d0eSMatt Porter * 514eb188d0eSMatt Porter * Returns total numbers of ports implemented by the switch device. 515eb188d0eSMatt Porter */ 516eb188d0eSMatt Porter static u8 rio_get_swpinfo_tports(struct rio_mport *mport, u16 destid, 517eb188d0eSMatt Porter u8 hopcount) 518eb188d0eSMatt Porter { 519eb188d0eSMatt Porter u32 result; 520eb188d0eSMatt Porter 521eb188d0eSMatt Porter rio_mport_read_config_32(mport, destid, hopcount, RIO_SWP_INFO_CAR, 522eb188d0eSMatt Porter &result); 523eb188d0eSMatt Porter 524eb188d0eSMatt Porter return RIO_GET_TOTAL_PORTS(result); 525eb188d0eSMatt Porter } 526eb188d0eSMatt Porter 527eb188d0eSMatt Porter /** 528eb188d0eSMatt Porter * rio_net_add_mport- Add a master port to a RIO network 529eb188d0eSMatt Porter * @net: RIO network 530eb188d0eSMatt Porter * @port: Master port to add 531eb188d0eSMatt Porter * 532eb188d0eSMatt Porter * Adds a master port to the network list of associated master 533eb188d0eSMatt Porter * ports.. 534eb188d0eSMatt Porter */ 535eb188d0eSMatt Porter static void rio_net_add_mport(struct rio_net *net, struct rio_mport *port) 536eb188d0eSMatt Porter { 537eb188d0eSMatt Porter spin_lock(&rio_global_list_lock); 538eb188d0eSMatt Porter list_add_tail(&port->nnode, &net->mports); 539eb188d0eSMatt Porter spin_unlock(&rio_global_list_lock); 540eb188d0eSMatt Porter } 541eb188d0eSMatt Porter 542eb188d0eSMatt Porter /** 543eb188d0eSMatt Porter * rio_enum_peer- Recursively enumerate a RIO network through a master port 544eb188d0eSMatt Porter * @net: RIO network being enumerated 545eb188d0eSMatt Porter * @port: Master port to send transactions 546eb188d0eSMatt Porter * @hopcount: Number of hops into the network 547eb188d0eSMatt Porter * 548eb188d0eSMatt Porter * Recursively enumerates a RIO network. Transactions are sent via the 549eb188d0eSMatt Porter * master port passed in @port. 550eb188d0eSMatt Porter */ 551eb188d0eSMatt Porter static int rio_enum_peer(struct rio_net *net, struct rio_mport *port, 552eb188d0eSMatt Porter u8 hopcount) 553eb188d0eSMatt Porter { 554eb188d0eSMatt Porter int port_num; 555eb188d0eSMatt Porter int num_ports; 556eb188d0eSMatt Porter int cur_destid; 557c70555b0SAlexandre Bounine int sw_destid; 558c70555b0SAlexandre Bounine int sw_inport; 559eb188d0eSMatt Porter struct rio_dev *rdev; 560eb188d0eSMatt Porter u16 destid; 561eb188d0eSMatt Porter int tmp; 562eb188d0eSMatt Porter 563eb188d0eSMatt Porter if (rio_get_host_deviceid_lock(port, hopcount) == port->host_deviceid) { 564eb188d0eSMatt Porter pr_debug("RIO: PE already discovered by this host\n"); 565eb188d0eSMatt Porter /* 566eb188d0eSMatt Porter * Already discovered by this host. Add it as another 567eb188d0eSMatt Porter * master port for the current network. 568eb188d0eSMatt Porter */ 569eb188d0eSMatt Porter rio_net_add_mport(net, port); 570eb188d0eSMatt Porter return 0; 571eb188d0eSMatt Porter } 572eb188d0eSMatt Porter 573eb188d0eSMatt Porter /* Attempt to acquire device lock */ 574eb188d0eSMatt Porter rio_mport_write_config_32(port, RIO_ANY_DESTID, hopcount, 575eb188d0eSMatt Porter RIO_HOST_DID_LOCK_CSR, port->host_deviceid); 576eb188d0eSMatt Porter while ((tmp = rio_get_host_deviceid_lock(port, hopcount)) 577eb188d0eSMatt Porter < port->host_deviceid) { 578eb188d0eSMatt Porter /* Delay a bit */ 579eb188d0eSMatt Porter mdelay(1); 580eb188d0eSMatt Porter /* Attempt to acquire device lock again */ 581eb188d0eSMatt Porter rio_mport_write_config_32(port, RIO_ANY_DESTID, hopcount, 582eb188d0eSMatt Porter RIO_HOST_DID_LOCK_CSR, 583eb188d0eSMatt Porter port->host_deviceid); 584eb188d0eSMatt Porter } 585eb188d0eSMatt Porter 586eb188d0eSMatt Porter if (rio_get_host_deviceid_lock(port, hopcount) > port->host_deviceid) { 587eb188d0eSMatt Porter pr_debug( 588eb188d0eSMatt Porter "RIO: PE locked by a higher priority host...retreating\n"); 589eb188d0eSMatt Porter return -1; 590eb188d0eSMatt Porter } 591eb188d0eSMatt Porter 592eb188d0eSMatt Porter /* Setup new RIO device */ 593eb188d0eSMatt Porter if ((rdev = rio_setup_device(net, port, RIO_ANY_DESTID, hopcount, 1))) { 594eb188d0eSMatt Porter /* Add device to the global and bus/net specific list. */ 595eb188d0eSMatt Porter list_add_tail(&rdev->net_list, &net->devices); 596eb188d0eSMatt Porter } else 597eb188d0eSMatt Porter return -1; 598eb188d0eSMatt Porter 599eb188d0eSMatt Porter if (rio_is_switch(rdev)) { 600eb188d0eSMatt Porter next_switchid++; 601c70555b0SAlexandre Bounine sw_inport = rio_get_swpinfo_inport(port, RIO_ANY_DESTID, hopcount); 602c70555b0SAlexandre Bounine rio_route_add_entry(port, rdev->rswitch, RIO_GLOBAL_TABLE, 603c70555b0SAlexandre Bounine port->host_deviceid, sw_inport); 604c70555b0SAlexandre Bounine rdev->rswitch->route_table[port->host_deviceid] = sw_inport; 605eb188d0eSMatt Porter 606eb188d0eSMatt Porter for (destid = 0; destid < next_destid; destid++) { 607c70555b0SAlexandre Bounine if (destid == port->host_deviceid) 608c70555b0SAlexandre Bounine continue; 609c70555b0SAlexandre Bounine rio_route_add_entry(port, rdev->rswitch, RIO_GLOBAL_TABLE, 610c70555b0SAlexandre Bounine destid, sw_inport); 611c70555b0SAlexandre Bounine rdev->rswitch->route_table[destid] = sw_inport; 612eb188d0eSMatt Porter } 613eb188d0eSMatt Porter 614eb188d0eSMatt Porter num_ports = 615eb188d0eSMatt Porter rio_get_swpinfo_tports(port, RIO_ANY_DESTID, hopcount); 616eb188d0eSMatt Porter pr_debug( 617eb188d0eSMatt Porter "RIO: found %s (vid %4.4x did %4.4x) with %d ports\n", 618eb188d0eSMatt Porter rio_name(rdev), rdev->vid, rdev->did, num_ports); 619c70555b0SAlexandre Bounine sw_destid = next_destid; 620eb188d0eSMatt Porter for (port_num = 0; port_num < num_ports; port_num++) { 621c70555b0SAlexandre Bounine if (sw_inport == port_num) 622eb188d0eSMatt Porter continue; 623eb188d0eSMatt Porter 624eb188d0eSMatt Porter cur_destid = next_destid; 625eb188d0eSMatt Porter 626eb188d0eSMatt Porter if (rio_sport_is_active 627eb188d0eSMatt Porter (port, RIO_ANY_DESTID, hopcount, port_num)) { 628eb188d0eSMatt Porter pr_debug( 629eb188d0eSMatt Porter "RIO: scanning device on port %d\n", 630eb188d0eSMatt Porter port_num); 631c70555b0SAlexandre Bounine rio_route_add_entry(port, rdev->rswitch, 632eb188d0eSMatt Porter RIO_GLOBAL_TABLE, 633eb188d0eSMatt Porter RIO_ANY_DESTID, port_num); 634eb188d0eSMatt Porter 635eb188d0eSMatt Porter if (rio_enum_peer(net, port, hopcount + 1) < 0) 636eb188d0eSMatt Porter return -1; 637eb188d0eSMatt Porter 638eb188d0eSMatt Porter /* Update routing tables */ 639eb188d0eSMatt Porter if (next_destid > cur_destid) { 640eb188d0eSMatt Porter for (destid = cur_destid; 641eb188d0eSMatt Porter destid < next_destid; destid++) { 642c70555b0SAlexandre Bounine if (destid == port->host_deviceid) 643c70555b0SAlexandre Bounine continue; 644c70555b0SAlexandre Bounine rio_route_add_entry(port, rdev->rswitch, 645eb188d0eSMatt Porter RIO_GLOBAL_TABLE, 646eb188d0eSMatt Porter destid, 647eb188d0eSMatt Porter port_num); 648eb188d0eSMatt Porter rdev->rswitch-> 649eb188d0eSMatt Porter route_table[destid] = 650eb188d0eSMatt Porter port_num; 651eb188d0eSMatt Porter } 652eb188d0eSMatt Porter } 653eb188d0eSMatt Porter } 654eb188d0eSMatt Porter } 655c70555b0SAlexandre Bounine 656c70555b0SAlexandre Bounine /* Check for empty switch */ 657c70555b0SAlexandre Bounine if (next_destid == sw_destid) { 658c70555b0SAlexandre Bounine next_destid++; 659c70555b0SAlexandre Bounine if (next_destid == port->host_deviceid) 660c70555b0SAlexandre Bounine next_destid++; 661c70555b0SAlexandre Bounine } 662c70555b0SAlexandre Bounine 663c70555b0SAlexandre Bounine rdev->rswitch->destid = sw_destid; 664eb188d0eSMatt Porter } else 665eb188d0eSMatt Porter pr_debug("RIO: found %s (vid %4.4x did %4.4x)\n", 666eb188d0eSMatt Porter rio_name(rdev), rdev->vid, rdev->did); 667eb188d0eSMatt Porter 668eb188d0eSMatt Porter return 0; 669eb188d0eSMatt Porter } 670eb188d0eSMatt Porter 671eb188d0eSMatt Porter /** 672eb188d0eSMatt Porter * rio_enum_complete- Tests if enumeration of a network is complete 673eb188d0eSMatt Porter * @port: Master port to send transaction 674eb188d0eSMatt Porter * 675eb188d0eSMatt Porter * Tests the Component Tag CSR for presence of the magic enumeration 676eb188d0eSMatt Porter * complete flag. Return %1 if enumeration is complete or %0 if 677eb188d0eSMatt Porter * enumeration is incomplete. 678eb188d0eSMatt Porter */ 679eb188d0eSMatt Porter static int rio_enum_complete(struct rio_mport *port) 680eb188d0eSMatt Porter { 681eb188d0eSMatt Porter u32 tag_csr; 682eb188d0eSMatt Porter int ret = 0; 683eb188d0eSMatt Porter 684eb188d0eSMatt Porter rio_local_read_config_32(port, RIO_COMPONENT_TAG_CSR, &tag_csr); 685eb188d0eSMatt Porter 686eb188d0eSMatt Porter if (tag_csr == RIO_ENUM_CMPL_MAGIC) 687eb188d0eSMatt Porter ret = 1; 688eb188d0eSMatt Porter 689eb188d0eSMatt Porter return ret; 690eb188d0eSMatt Porter } 691eb188d0eSMatt Porter 692eb188d0eSMatt Porter /** 693eb188d0eSMatt Porter * rio_disc_peer- Recursively discovers a RIO network through a master port 694eb188d0eSMatt Porter * @net: RIO network being discovered 695eb188d0eSMatt Porter * @port: Master port to send transactions 696eb188d0eSMatt Porter * @destid: Current destination ID in network 697eb188d0eSMatt Porter * @hopcount: Number of hops into the network 698eb188d0eSMatt Porter * 699eb188d0eSMatt Porter * Recursively discovers a RIO network. Transactions are sent via the 700eb188d0eSMatt Porter * master port passed in @port. 701eb188d0eSMatt Porter */ 702eb188d0eSMatt Porter static int 703eb188d0eSMatt Porter rio_disc_peer(struct rio_net *net, struct rio_mport *port, u16 destid, 704eb188d0eSMatt Porter u8 hopcount) 705eb188d0eSMatt Porter { 706eb188d0eSMatt Porter u8 port_num, route_port; 707eb188d0eSMatt Porter int num_ports; 708eb188d0eSMatt Porter struct rio_dev *rdev; 709eb188d0eSMatt Porter u16 ndestid; 710eb188d0eSMatt Porter 711eb188d0eSMatt Porter /* Setup new RIO device */ 712eb188d0eSMatt Porter if ((rdev = rio_setup_device(net, port, destid, hopcount, 0))) { 713eb188d0eSMatt Porter /* Add device to the global and bus/net specific list. */ 714eb188d0eSMatt Porter list_add_tail(&rdev->net_list, &net->devices); 715eb188d0eSMatt Porter } else 716eb188d0eSMatt Porter return -1; 717eb188d0eSMatt Porter 718eb188d0eSMatt Porter if (rio_is_switch(rdev)) { 719eb188d0eSMatt Porter next_switchid++; 720eb188d0eSMatt Porter 721eb188d0eSMatt Porter /* Associated destid is how we accessed this switch */ 722eb188d0eSMatt Porter rdev->rswitch->destid = destid; 723eb188d0eSMatt Porter 724eb188d0eSMatt Porter num_ports = rio_get_swpinfo_tports(port, destid, hopcount); 725eb188d0eSMatt Porter pr_debug( 726eb188d0eSMatt Porter "RIO: found %s (vid %4.4x did %4.4x) with %d ports\n", 727eb188d0eSMatt Porter rio_name(rdev), rdev->vid, rdev->did, num_ports); 728eb188d0eSMatt Porter for (port_num = 0; port_num < num_ports; port_num++) { 729eb188d0eSMatt Porter if (rio_get_swpinfo_inport(port, destid, hopcount) == 730eb188d0eSMatt Porter port_num) 731eb188d0eSMatt Porter continue; 732eb188d0eSMatt Porter 733eb188d0eSMatt Porter if (rio_sport_is_active 734eb188d0eSMatt Porter (port, destid, hopcount, port_num)) { 735eb188d0eSMatt Porter pr_debug( 736eb188d0eSMatt Porter "RIO: scanning device on port %d\n", 737eb188d0eSMatt Porter port_num); 738eb188d0eSMatt Porter for (ndestid = 0; ndestid < RIO_ANY_DESTID; 739eb188d0eSMatt Porter ndestid++) { 740c70555b0SAlexandre Bounine rio_route_get_entry(port, rdev->rswitch, 741eb188d0eSMatt Porter RIO_GLOBAL_TABLE, 742eb188d0eSMatt Porter ndestid, 743eb188d0eSMatt Porter &route_port); 744eb188d0eSMatt Porter if (route_port == port_num) 745eb188d0eSMatt Porter break; 746eb188d0eSMatt Porter } 747eb188d0eSMatt Porter 748eb188d0eSMatt Porter if (rio_disc_peer 749eb188d0eSMatt Porter (net, port, ndestid, hopcount + 1) < 0) 750eb188d0eSMatt Porter return -1; 751eb188d0eSMatt Porter } 752eb188d0eSMatt Porter } 753eb188d0eSMatt Porter } else 754eb188d0eSMatt Porter pr_debug("RIO: found %s (vid %4.4x did %4.4x)\n", 755eb188d0eSMatt Porter rio_name(rdev), rdev->vid, rdev->did); 756eb188d0eSMatt Porter 757eb188d0eSMatt Porter return 0; 758eb188d0eSMatt Porter } 759eb188d0eSMatt Porter 760eb188d0eSMatt Porter /** 761eb188d0eSMatt Porter * rio_mport_is_active- Tests if master port link is active 762eb188d0eSMatt Porter * @port: Master port to test 763eb188d0eSMatt Porter * 764eb188d0eSMatt Porter * Reads the port error status CSR for the master port to 765eb188d0eSMatt Porter * determine if the port has an active link. Returns 766eb188d0eSMatt Porter * %PORT_N_ERR_STS_PORT_OK if the master port is active 767eb188d0eSMatt Porter * or %0 if it is inactive. 768eb188d0eSMatt Porter */ 769eb188d0eSMatt Porter static int rio_mport_is_active(struct rio_mport *port) 770eb188d0eSMatt Porter { 771eb188d0eSMatt Porter u32 result = 0; 772eb188d0eSMatt Porter u32 ext_ftr_ptr; 773eb188d0eSMatt Porter int *entry = rio_mport_phys_table; 774eb188d0eSMatt Porter 775eb188d0eSMatt Porter do { 776eb188d0eSMatt Porter if ((ext_ftr_ptr = 777eb188d0eSMatt Porter rio_mport_get_feature(port, 1, 0, 0, *entry))) 778eb188d0eSMatt Porter break; 779eb188d0eSMatt Porter } while (*++entry >= 0); 780eb188d0eSMatt Porter 781eb188d0eSMatt Porter if (ext_ftr_ptr) 782eb188d0eSMatt Porter rio_local_read_config_32(port, 783eb188d0eSMatt Porter ext_ftr_ptr + 784eb188d0eSMatt Porter RIO_PORT_N_ERR_STS_CSR(port->index), 785eb188d0eSMatt Porter &result); 786eb188d0eSMatt Porter 787eb188d0eSMatt Porter return (result & PORT_N_ERR_STS_PORT_OK); 788eb188d0eSMatt Porter } 789eb188d0eSMatt Porter 790eb188d0eSMatt Porter /** 791eb188d0eSMatt Porter * rio_alloc_net- Allocate and configure a new RIO network 792eb188d0eSMatt Porter * @port: Master port associated with the RIO network 793eb188d0eSMatt Porter * 794eb188d0eSMatt Porter * Allocates a RIO network structure, initializes per-network 795eb188d0eSMatt Porter * list heads, and adds the associated master port to the 796eb188d0eSMatt Porter * network list of associated master ports. Returns a 797eb188d0eSMatt Porter * RIO network pointer on success or %NULL on failure. 798eb188d0eSMatt Porter */ 799eb188d0eSMatt Porter static struct rio_net __devinit *rio_alloc_net(struct rio_mport *port) 800eb188d0eSMatt Porter { 801eb188d0eSMatt Porter struct rio_net *net; 802eb188d0eSMatt Porter 803dd00cc48SYoann Padioleau net = kzalloc(sizeof(struct rio_net), GFP_KERNEL); 804eb188d0eSMatt Porter if (net) { 805eb188d0eSMatt Porter INIT_LIST_HEAD(&net->node); 806eb188d0eSMatt Porter INIT_LIST_HEAD(&net->devices); 807eb188d0eSMatt Porter INIT_LIST_HEAD(&net->mports); 808eb188d0eSMatt Porter list_add_tail(&port->nnode, &net->mports); 809eb188d0eSMatt Porter net->hport = port; 810eb188d0eSMatt Porter net->id = next_net++; 811eb188d0eSMatt Porter } 812eb188d0eSMatt Porter return net; 813eb188d0eSMatt Porter } 814eb188d0eSMatt Porter 815eb188d0eSMatt Porter /** 816c70555b0SAlexandre Bounine * rio_update_route_tables- Updates route tables in switches 817c70555b0SAlexandre Bounine * @port: Master port associated with the RIO network 818c70555b0SAlexandre Bounine * 819c70555b0SAlexandre Bounine * For each enumerated device, ensure that each switch in a system 820c70555b0SAlexandre Bounine * has correct routing entries. Add routes for devices that where 821c70555b0SAlexandre Bounine * unknown dirung the first enumeration pass through the switch. 822c70555b0SAlexandre Bounine */ 823c70555b0SAlexandre Bounine static void rio_update_route_tables(struct rio_mport *port) 824c70555b0SAlexandre Bounine { 825c70555b0SAlexandre Bounine struct rio_dev *rdev; 826c70555b0SAlexandre Bounine struct rio_switch *rswitch; 827c70555b0SAlexandre Bounine u8 sport; 828c70555b0SAlexandre Bounine u16 destid; 829c70555b0SAlexandre Bounine 830c70555b0SAlexandre Bounine list_for_each_entry(rdev, &rio_devices, global_list) { 831c70555b0SAlexandre Bounine 832c70555b0SAlexandre Bounine destid = (rio_is_switch(rdev))?rdev->rswitch->destid:rdev->destid; 833c70555b0SAlexandre Bounine 834c70555b0SAlexandre Bounine list_for_each_entry(rswitch, &rio_switches, node) { 835c70555b0SAlexandre Bounine 836c70555b0SAlexandre Bounine if (rio_is_switch(rdev) && (rdev->rswitch == rswitch)) 837c70555b0SAlexandre Bounine continue; 838c70555b0SAlexandre Bounine 839c70555b0SAlexandre Bounine if (RIO_INVALID_ROUTE == rswitch->route_table[destid]) { 840c70555b0SAlexandre Bounine 841c70555b0SAlexandre Bounine sport = rio_get_swpinfo_inport(port, 842c70555b0SAlexandre Bounine rswitch->destid, rswitch->hopcount); 843c70555b0SAlexandre Bounine 844c70555b0SAlexandre Bounine if (rswitch->add_entry) { 845c70555b0SAlexandre Bounine rio_route_add_entry(port, rswitch, RIO_GLOBAL_TABLE, destid, sport); 846c70555b0SAlexandre Bounine rswitch->route_table[destid] = sport; 847c70555b0SAlexandre Bounine } 848c70555b0SAlexandre Bounine } 849c70555b0SAlexandre Bounine } 850c70555b0SAlexandre Bounine } 851c70555b0SAlexandre Bounine } 852c70555b0SAlexandre Bounine 853c70555b0SAlexandre Bounine /** 854eb188d0eSMatt Porter * rio_enum_mport- Start enumeration through a master port 855eb188d0eSMatt Porter * @mport: Master port to send transactions 856eb188d0eSMatt Porter * 857eb188d0eSMatt Porter * Starts the enumeration process. If somebody has enumerated our 858eb188d0eSMatt Porter * master port device, then give up. If not and we have an active 859eb188d0eSMatt Porter * link, then start recursive peer enumeration. Returns %0 if 860eb188d0eSMatt Porter * enumeration succeeds or %-EBUSY if enumeration fails. 861eb188d0eSMatt Porter */ 862eb188d0eSMatt Porter int rio_enum_mport(struct rio_mport *mport) 863eb188d0eSMatt Porter { 864eb188d0eSMatt Porter struct rio_net *net = NULL; 865eb188d0eSMatt Porter int rc = 0; 866eb188d0eSMatt Porter 867eb188d0eSMatt Porter printk(KERN_INFO "RIO: enumerate master port %d, %s\n", mport->id, 868eb188d0eSMatt Porter mport->name); 869eb188d0eSMatt Porter /* If somebody else enumerated our master port device, bail. */ 870eb188d0eSMatt Porter if (rio_enum_host(mport) < 0) { 871eb188d0eSMatt Porter printk(KERN_INFO 872eb188d0eSMatt Porter "RIO: master port %d device has been enumerated by a remote host\n", 873eb188d0eSMatt Porter mport->id); 874eb188d0eSMatt Porter rc = -EBUSY; 875eb188d0eSMatt Porter goto out; 876eb188d0eSMatt Porter } 877eb188d0eSMatt Porter 878eb188d0eSMatt Porter /* If master port has an active link, allocate net and enum peers */ 879eb188d0eSMatt Porter if (rio_mport_is_active(mport)) { 880eb188d0eSMatt Porter if (!(net = rio_alloc_net(mport))) { 881eb188d0eSMatt Porter printk(KERN_ERR "RIO: failed to allocate new net\n"); 882eb188d0eSMatt Porter rc = -ENOMEM; 883eb188d0eSMatt Porter goto out; 884eb188d0eSMatt Porter } 885eb188d0eSMatt Porter if (rio_enum_peer(net, mport, 0) < 0) { 886eb188d0eSMatt Porter /* A higher priority host won enumeration, bail. */ 887eb188d0eSMatt Porter printk(KERN_INFO 888eb188d0eSMatt Porter "RIO: master port %d device has lost enumeration to a remote host\n", 889eb188d0eSMatt Porter mport->id); 890eb188d0eSMatt Porter rio_clear_locks(mport); 891eb188d0eSMatt Porter rc = -EBUSY; 892eb188d0eSMatt Porter goto out; 893eb188d0eSMatt Porter } 894c70555b0SAlexandre Bounine rio_update_route_tables(mport); 895eb188d0eSMatt Porter rio_clear_locks(mport); 896eb188d0eSMatt Porter } else { 897eb188d0eSMatt Porter printk(KERN_INFO "RIO: master port %d link inactive\n", 898eb188d0eSMatt Porter mport->id); 899eb188d0eSMatt Porter rc = -EINVAL; 900eb188d0eSMatt Porter } 901eb188d0eSMatt Porter 902eb188d0eSMatt Porter out: 903eb188d0eSMatt Porter return rc; 904eb188d0eSMatt Porter } 905eb188d0eSMatt Porter 906eb188d0eSMatt Porter /** 907eb188d0eSMatt Porter * rio_build_route_tables- Generate route tables from switch route entries 908eb188d0eSMatt Porter * 909eb188d0eSMatt Porter * For each switch device, generate a route table by copying existing 910eb188d0eSMatt Porter * route entries from the switch. 911eb188d0eSMatt Porter */ 912eb188d0eSMatt Porter static void rio_build_route_tables(void) 913eb188d0eSMatt Porter { 914eb188d0eSMatt Porter struct rio_dev *rdev; 915eb188d0eSMatt Porter int i; 916eb188d0eSMatt Porter u8 sport; 917eb188d0eSMatt Porter 918eb188d0eSMatt Porter list_for_each_entry(rdev, &rio_devices, global_list) 919eb188d0eSMatt Porter if (rio_is_switch(rdev)) 920eb188d0eSMatt Porter for (i = 0; i < RIO_MAX_ROUTE_ENTRIES; i++) { 921eb188d0eSMatt Porter if (rio_route_get_entry 922c70555b0SAlexandre Bounine (rdev->net->hport, rdev->rswitch, RIO_GLOBAL_TABLE, 923c70555b0SAlexandre Bounine i, &sport) < 0) 924eb188d0eSMatt Porter continue; 925eb188d0eSMatt Porter rdev->rswitch->route_table[i] = sport; 926eb188d0eSMatt Porter } 927eb188d0eSMatt Porter } 928eb188d0eSMatt Porter 929eb188d0eSMatt Porter /** 930eb188d0eSMatt Porter * rio_enum_timeout- Signal that enumeration timed out 931eb188d0eSMatt Porter * @data: Address of timeout flag. 932eb188d0eSMatt Porter * 933eb188d0eSMatt Porter * When the enumeration complete timer expires, set a flag that 934eb188d0eSMatt Porter * signals to the discovery process that enumeration did not 935eb188d0eSMatt Porter * complete in a sane amount of time. 936eb188d0eSMatt Porter */ 937eb188d0eSMatt Porter static void rio_enum_timeout(unsigned long data) 938eb188d0eSMatt Porter { 939eb188d0eSMatt Porter /* Enumeration timed out, set flag */ 940eb188d0eSMatt Porter *(int *)data = 1; 941eb188d0eSMatt Porter } 942eb188d0eSMatt Porter 943eb188d0eSMatt Porter /** 944eb188d0eSMatt Porter * rio_disc_mport- Start discovery through a master port 945eb188d0eSMatt Porter * @mport: Master port to send transactions 946eb188d0eSMatt Porter * 947eb188d0eSMatt Porter * Starts the discovery process. If we have an active link, 948eb188d0eSMatt Porter * then wait for the signal that enumeration is complete. 949eb188d0eSMatt Porter * When enumeration completion is signaled, start recursive 950eb188d0eSMatt Porter * peer discovery. Returns %0 if discovery succeeds or %-EBUSY 951eb188d0eSMatt Porter * on failure. 952eb188d0eSMatt Porter */ 953eb188d0eSMatt Porter int rio_disc_mport(struct rio_mport *mport) 954eb188d0eSMatt Porter { 955eb188d0eSMatt Porter struct rio_net *net = NULL; 956eb188d0eSMatt Porter int enum_timeout_flag = 0; 957eb188d0eSMatt Porter 958eb188d0eSMatt Porter printk(KERN_INFO "RIO: discover master port %d, %s\n", mport->id, 959eb188d0eSMatt Porter mport->name); 960eb188d0eSMatt Porter 961eb188d0eSMatt Porter /* If master port has an active link, allocate net and discover peers */ 962eb188d0eSMatt Porter if (rio_mport_is_active(mport)) { 963eb188d0eSMatt Porter if (!(net = rio_alloc_net(mport))) { 964eb188d0eSMatt Porter printk(KERN_ERR "RIO: Failed to allocate new net\n"); 965eb188d0eSMatt Porter goto bail; 966eb188d0eSMatt Porter } 967eb188d0eSMatt Porter 968eb188d0eSMatt Porter pr_debug("RIO: wait for enumeration complete..."); 969eb188d0eSMatt Porter 970eb188d0eSMatt Porter rio_enum_timer.expires = 971eb188d0eSMatt Porter jiffies + CONFIG_RAPIDIO_DISC_TIMEOUT * HZ; 972eb188d0eSMatt Porter rio_enum_timer.data = (unsigned long)&enum_timeout_flag; 973eb188d0eSMatt Porter add_timer(&rio_enum_timer); 974eb188d0eSMatt Porter while (!rio_enum_complete(mport)) { 975eb188d0eSMatt Porter mdelay(1); 976eb188d0eSMatt Porter if (enum_timeout_flag) { 977eb188d0eSMatt Porter del_timer_sync(&rio_enum_timer); 978eb188d0eSMatt Porter goto timeout; 979eb188d0eSMatt Porter } 980eb188d0eSMatt Porter } 981eb188d0eSMatt Porter del_timer_sync(&rio_enum_timer); 982eb188d0eSMatt Porter 983eb188d0eSMatt Porter pr_debug("done\n"); 984eb188d0eSMatt Porter if (rio_disc_peer(net, mport, RIO_ANY_DESTID, 0) < 0) { 985eb188d0eSMatt Porter printk(KERN_INFO 986eb188d0eSMatt Porter "RIO: master port %d device has failed discovery\n", 987eb188d0eSMatt Porter mport->id); 988eb188d0eSMatt Porter goto bail; 989eb188d0eSMatt Porter } 990eb188d0eSMatt Porter 991eb188d0eSMatt Porter rio_build_route_tables(); 992eb188d0eSMatt Porter } 993eb188d0eSMatt Porter 994eb188d0eSMatt Porter return 0; 995eb188d0eSMatt Porter 996eb188d0eSMatt Porter timeout: 997eb188d0eSMatt Porter pr_debug("timeout\n"); 998eb188d0eSMatt Porter bail: 999eb188d0eSMatt Porter return -EBUSY; 1000eb188d0eSMatt Porter } 1001