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, 5807590ff0SAlexandre Bounine RIO_EFB_SER_EP_FREC_ID, 59eb188d0eSMatt Porter -1, 60eb188d0eSMatt Porter }; 61eb188d0eSMatt Porter 62eb188d0eSMatt Porter /** 63eb188d0eSMatt Porter * rio_get_device_id - Get the base/extended device id for a device 64eb188d0eSMatt Porter * @port: RIO master port 65eb188d0eSMatt Porter * @destid: Destination ID of device 66eb188d0eSMatt Porter * @hopcount: Hopcount to device 67eb188d0eSMatt Porter * 68eb188d0eSMatt Porter * Reads the base/extended device id from a device. Returns the 69eb188d0eSMatt Porter * 8/16-bit device ID. 70eb188d0eSMatt Porter */ 71eb188d0eSMatt Porter static u16 rio_get_device_id(struct rio_mport *port, u16 destid, u8 hopcount) 72eb188d0eSMatt Porter { 73eb188d0eSMatt Porter u32 result; 74eb188d0eSMatt Porter 75eb188d0eSMatt Porter rio_mport_read_config_32(port, destid, hopcount, RIO_DID_CSR, &result); 76eb188d0eSMatt Porter 77e0423236SZhang Wei return RIO_GET_DID(port->sys_size, result); 78eb188d0eSMatt Porter } 79eb188d0eSMatt Porter 80eb188d0eSMatt Porter /** 81eb188d0eSMatt Porter * rio_set_device_id - Set the base/extended device id for a device 82eb188d0eSMatt Porter * @port: RIO master port 83eb188d0eSMatt Porter * @destid: Destination ID of device 84eb188d0eSMatt Porter * @hopcount: Hopcount to device 85eb188d0eSMatt Porter * @did: Device ID value to be written 86eb188d0eSMatt Porter * 87eb188d0eSMatt Porter * Writes the base/extended device id from a device. 88eb188d0eSMatt Porter */ 89fa78cc51SMatt Porter static void rio_set_device_id(struct rio_mport *port, u16 destid, u8 hopcount, u16 did) 90eb188d0eSMatt Porter { 91eb188d0eSMatt Porter rio_mport_write_config_32(port, destid, hopcount, RIO_DID_CSR, 92e0423236SZhang Wei RIO_SET_DID(port->sys_size, did)); 93eb188d0eSMatt Porter } 94eb188d0eSMatt Porter 95eb188d0eSMatt Porter /** 96eb188d0eSMatt Porter * rio_local_set_device_id - Set the base/extended device id for a port 97eb188d0eSMatt Porter * @port: RIO master port 98eb188d0eSMatt Porter * @did: Device ID value to be written 99eb188d0eSMatt Porter * 100eb188d0eSMatt Porter * Writes the base/extended device id from a device. 101eb188d0eSMatt Porter */ 102eb188d0eSMatt Porter static void rio_local_set_device_id(struct rio_mport *port, u16 did) 103eb188d0eSMatt Porter { 104e0423236SZhang Wei rio_local_write_config_32(port, RIO_DID_CSR, RIO_SET_DID(port->sys_size, 105e0423236SZhang Wei did)); 106eb188d0eSMatt Porter } 107eb188d0eSMatt Porter 108eb188d0eSMatt Porter /** 109eb188d0eSMatt Porter * rio_clear_locks- Release all host locks and signal enumeration complete 110eb188d0eSMatt Porter * @port: Master port to issue transaction 111eb188d0eSMatt Porter * 112eb188d0eSMatt Porter * Marks the component tag CSR on each device with the enumeration 113eb188d0eSMatt Porter * complete flag. When complete, it then release the host locks on 114eb188d0eSMatt Porter * each device. Returns 0 on success or %-EINVAL on failure. 115eb188d0eSMatt Porter */ 116eb188d0eSMatt Porter static int rio_clear_locks(struct rio_mport *port) 117eb188d0eSMatt Porter { 118eb188d0eSMatt Porter struct rio_dev *rdev; 119eb188d0eSMatt Porter u32 result; 120eb188d0eSMatt Porter int ret = 0; 121eb188d0eSMatt Porter 122eb188d0eSMatt Porter /* Write component tag CSR magic complete value */ 123eb188d0eSMatt Porter rio_local_write_config_32(port, RIO_COMPONENT_TAG_CSR, 124eb188d0eSMatt Porter RIO_ENUM_CMPL_MAGIC); 125eb188d0eSMatt Porter list_for_each_entry(rdev, &rio_devices, global_list) 126eb188d0eSMatt Porter rio_write_config_32(rdev, RIO_COMPONENT_TAG_CSR, 127eb188d0eSMatt Porter RIO_ENUM_CMPL_MAGIC); 128eb188d0eSMatt Porter 129eb188d0eSMatt Porter /* Release host device id locks */ 130eb188d0eSMatt Porter rio_local_write_config_32(port, RIO_HOST_DID_LOCK_CSR, 131eb188d0eSMatt Porter port->host_deviceid); 132eb188d0eSMatt Porter rio_local_read_config_32(port, RIO_HOST_DID_LOCK_CSR, &result); 133eb188d0eSMatt Porter if ((result & 0xffff) != 0xffff) { 134eb188d0eSMatt Porter printk(KERN_INFO 135eb188d0eSMatt Porter "RIO: badness when releasing host lock on master port, result %8.8x\n", 136eb188d0eSMatt Porter result); 137eb188d0eSMatt Porter ret = -EINVAL; 138eb188d0eSMatt Porter } 139eb188d0eSMatt Porter list_for_each_entry(rdev, &rio_devices, global_list) { 140eb188d0eSMatt Porter rio_write_config_32(rdev, RIO_HOST_DID_LOCK_CSR, 141eb188d0eSMatt Porter port->host_deviceid); 142eb188d0eSMatt Porter rio_read_config_32(rdev, RIO_HOST_DID_LOCK_CSR, &result); 143eb188d0eSMatt Porter if ((result & 0xffff) != 0xffff) { 144eb188d0eSMatt Porter printk(KERN_INFO 145eb188d0eSMatt Porter "RIO: badness when releasing host lock on vid %4.4x did %4.4x\n", 146eb188d0eSMatt Porter rdev->vid, rdev->did); 147eb188d0eSMatt Porter ret = -EINVAL; 148eb188d0eSMatt Porter } 149eb188d0eSMatt Porter } 150eb188d0eSMatt Porter 151eb188d0eSMatt Porter return ret; 152eb188d0eSMatt Porter } 153eb188d0eSMatt Porter 154eb188d0eSMatt Porter /** 155eb188d0eSMatt Porter * rio_enum_host- Set host lock and initialize host destination ID 156eb188d0eSMatt Porter * @port: Master port to issue transaction 157eb188d0eSMatt Porter * 158eb188d0eSMatt Porter * Sets the local host master port lock and destination ID register 159eb188d0eSMatt Porter * with the host device ID value. The host device ID value is provided 160eb188d0eSMatt Porter * by the platform. Returns %0 on success or %-1 on failure. 161eb188d0eSMatt Porter */ 162eb188d0eSMatt Porter static int rio_enum_host(struct rio_mport *port) 163eb188d0eSMatt Porter { 164eb188d0eSMatt Porter u32 result; 165eb188d0eSMatt Porter 166eb188d0eSMatt Porter /* Set master port host device id lock */ 167eb188d0eSMatt Porter rio_local_write_config_32(port, RIO_HOST_DID_LOCK_CSR, 168eb188d0eSMatt Porter port->host_deviceid); 169eb188d0eSMatt Porter 170eb188d0eSMatt Porter rio_local_read_config_32(port, RIO_HOST_DID_LOCK_CSR, &result); 171eb188d0eSMatt Porter if ((result & 0xffff) != port->host_deviceid) 172eb188d0eSMatt Porter return -1; 173eb188d0eSMatt Porter 174eb188d0eSMatt Porter /* Set master port destid and init destid ctr */ 175eb188d0eSMatt Porter rio_local_set_device_id(port, port->host_deviceid); 176eb188d0eSMatt Porter 177eb188d0eSMatt Porter if (next_destid == port->host_deviceid) 178eb188d0eSMatt Porter next_destid++; 179eb188d0eSMatt Porter 180eb188d0eSMatt Porter return 0; 181eb188d0eSMatt Porter } 182eb188d0eSMatt Porter 183eb188d0eSMatt Porter /** 184eb188d0eSMatt Porter * rio_device_has_destid- Test if a device contains a destination ID register 185eb188d0eSMatt Porter * @port: Master port to issue transaction 186eb188d0eSMatt Porter * @src_ops: RIO device source operations 187eb188d0eSMatt Porter * @dst_ops: RIO device destination operations 188eb188d0eSMatt Porter * 189eb188d0eSMatt Porter * Checks the provided @src_ops and @dst_ops for the necessary transaction 190eb188d0eSMatt Porter * capabilities that indicate whether or not a device will implement a 191eb188d0eSMatt Porter * destination ID register. Returns 1 if true or 0 if false. 192eb188d0eSMatt Porter */ 193eb188d0eSMatt Porter static int rio_device_has_destid(struct rio_mport *port, int src_ops, 194eb188d0eSMatt Porter int dst_ops) 195eb188d0eSMatt Porter { 196fa78cc51SMatt 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; 197fa78cc51SMatt Porter 198fa78cc51SMatt Porter return !!((src_ops | dst_ops) & mask); 199eb188d0eSMatt Porter } 200eb188d0eSMatt Porter 201eb188d0eSMatt Porter /** 202eb188d0eSMatt Porter * rio_release_dev- Frees a RIO device struct 203eb188d0eSMatt Porter * @dev: LDM device associated with a RIO device struct 204eb188d0eSMatt Porter * 205eb188d0eSMatt Porter * Gets the RIO device struct associated a RIO device struct. 206eb188d0eSMatt Porter * The RIO device struct is freed. 207eb188d0eSMatt Porter */ 208eb188d0eSMatt Porter static void rio_release_dev(struct device *dev) 209eb188d0eSMatt Porter { 210eb188d0eSMatt Porter struct rio_dev *rdev; 211eb188d0eSMatt Porter 212eb188d0eSMatt Porter rdev = to_rio_dev(dev); 213eb188d0eSMatt Porter kfree(rdev); 214eb188d0eSMatt Porter } 215eb188d0eSMatt Porter 216eb188d0eSMatt Porter /** 217eb188d0eSMatt Porter * rio_is_switch- Tests if a RIO device has switch capabilities 218eb188d0eSMatt Porter * @rdev: RIO device 219eb188d0eSMatt Porter * 220eb188d0eSMatt Porter * Gets the RIO device Processing Element Features register 221eb188d0eSMatt Porter * contents and tests for switch capabilities. Returns 1 if 222eb188d0eSMatt Porter * the device is a switch or 0 if it is not a switch. 223eb188d0eSMatt Porter * The RIO device struct is freed. 224eb188d0eSMatt Porter */ 225eb188d0eSMatt Porter static int rio_is_switch(struct rio_dev *rdev) 226eb188d0eSMatt Porter { 227eb188d0eSMatt Porter if (rdev->pef & RIO_PEF_SWITCH) 228eb188d0eSMatt Porter return 1; 229eb188d0eSMatt Porter return 0; 230eb188d0eSMatt Porter } 231eb188d0eSMatt Porter 232eb188d0eSMatt Porter /** 233eb188d0eSMatt Porter * rio_route_set_ops- Sets routing operations for a particular vendor switch 234eb188d0eSMatt Porter * @rdev: RIO device 235eb188d0eSMatt Porter * 236eb188d0eSMatt Porter * Searches the RIO route ops table for known switch types. If the vid 237eb188d0eSMatt Porter * and did match a switch table entry, then set the add_entry() and 238eb188d0eSMatt Porter * get_entry() ops to the table entry values. 239eb188d0eSMatt Porter */ 240eb188d0eSMatt Porter static void rio_route_set_ops(struct rio_dev *rdev) 241eb188d0eSMatt Porter { 242eb188d0eSMatt Porter struct rio_route_ops *cur = __start_rio_route_ops; 243eb188d0eSMatt Porter struct rio_route_ops *end = __end_rio_route_ops; 244eb188d0eSMatt Porter 245eb188d0eSMatt Porter while (cur < end) { 246eb188d0eSMatt Porter if ((cur->vid == rdev->vid) && (cur->did == rdev->did)) { 247eb188d0eSMatt Porter pr_debug("RIO: adding routing ops for %s\n", rio_name(rdev)); 248eb188d0eSMatt Porter rdev->rswitch->add_entry = cur->add_hook; 249eb188d0eSMatt Porter rdev->rswitch->get_entry = cur->get_hook; 25007590ff0SAlexandre Bounine rdev->rswitch->clr_table = cur->clr_hook; 25107590ff0SAlexandre Bounine break; 252eb188d0eSMatt Porter } 253eb188d0eSMatt Porter cur++; 254eb188d0eSMatt Porter } 255eb188d0eSMatt Porter 25607590ff0SAlexandre Bounine if ((cur >= end) && (rdev->pef & RIO_PEF_STD_RT)) { 25707590ff0SAlexandre Bounine pr_debug("RIO: adding STD routing ops for %s\n", 25807590ff0SAlexandre Bounine rio_name(rdev)); 25907590ff0SAlexandre Bounine rdev->rswitch->add_entry = rio_std_route_add_entry; 26007590ff0SAlexandre Bounine rdev->rswitch->get_entry = rio_std_route_get_entry; 26107590ff0SAlexandre Bounine rdev->rswitch->clr_table = rio_std_route_clr_table; 26207590ff0SAlexandre Bounine } 26307590ff0SAlexandre Bounine 264eb188d0eSMatt Porter if (!rdev->rswitch->add_entry || !rdev->rswitch->get_entry) 265eb188d0eSMatt Porter printk(KERN_ERR "RIO: missing routing ops for %s\n", 266eb188d0eSMatt Porter rio_name(rdev)); 267eb188d0eSMatt Porter } 268eb188d0eSMatt Porter 269eb188d0eSMatt Porter /** 270eb188d0eSMatt Porter * rio_add_device- Adds a RIO device to the device model 271eb188d0eSMatt Porter * @rdev: RIO device 272eb188d0eSMatt Porter * 273eb188d0eSMatt Porter * Adds the RIO device to the global device list and adds the RIO 274eb188d0eSMatt Porter * device to the RIO device list. Creates the generic sysfs nodes 275eb188d0eSMatt Porter * for an RIO device. 276eb188d0eSMatt Porter */ 2775f28c520SYang Li static int __devinit rio_add_device(struct rio_dev *rdev) 278eb188d0eSMatt Porter { 2795f28c520SYang Li int err; 2805f28c520SYang Li 2815f28c520SYang Li err = device_add(&rdev->dev); 2825f28c520SYang Li if (err) 2835f28c520SYang Li return err; 284eb188d0eSMatt Porter 285eb188d0eSMatt Porter spin_lock(&rio_global_list_lock); 286eb188d0eSMatt Porter list_add_tail(&rdev->global_list, &rio_devices); 287eb188d0eSMatt Porter spin_unlock(&rio_global_list_lock); 288eb188d0eSMatt Porter 289eb188d0eSMatt Porter rio_create_sysfs_dev_files(rdev); 2905f28c520SYang Li 2915f28c520SYang Li return 0; 292eb188d0eSMatt Porter } 293eb188d0eSMatt Porter 294eb188d0eSMatt Porter /** 295eb188d0eSMatt Porter * rio_setup_device- Allocates and sets up a RIO device 296eb188d0eSMatt Porter * @net: RIO network 297eb188d0eSMatt Porter * @port: Master port to send transactions 298eb188d0eSMatt Porter * @destid: Current destination ID 299eb188d0eSMatt Porter * @hopcount: Current hopcount 300eb188d0eSMatt Porter * @do_enum: Enumeration/Discovery mode flag 301eb188d0eSMatt Porter * 302eb188d0eSMatt Porter * Allocates a RIO device and configures fields based on configuration 303eb188d0eSMatt Porter * space contents. If device has a destination ID register, a destination 304eb188d0eSMatt Porter * ID is either assigned in enumeration mode or read from configuration 305eb188d0eSMatt Porter * space in discovery mode. If the device has switch capabilities, then 306eb188d0eSMatt Porter * a switch is allocated and configured appropriately. Returns a pointer 307eb188d0eSMatt Porter * to a RIO device on success or NULL on failure. 308eb188d0eSMatt Porter * 309eb188d0eSMatt Porter */ 310181a6ff0SLi Yang static struct rio_dev __devinit *rio_setup_device(struct rio_net *net, 311eb188d0eSMatt Porter struct rio_mport *port, u16 destid, 312eb188d0eSMatt Porter u8 hopcount, int do_enum) 313eb188d0eSMatt Porter { 3145f28c520SYang Li int ret = 0; 315eb188d0eSMatt Porter struct rio_dev *rdev; 3165f28c520SYang Li struct rio_switch *rswitch = NULL; 317eb188d0eSMatt Porter int result, rdid; 318eb188d0eSMatt Porter 319dd00cc48SYoann Padioleau rdev = kzalloc(sizeof(struct rio_dev), GFP_KERNEL); 320eb188d0eSMatt Porter if (!rdev) 3215f28c520SYang Li return NULL; 322eb188d0eSMatt Porter 323eb188d0eSMatt Porter rdev->net = net; 324eb188d0eSMatt Porter rio_mport_read_config_32(port, destid, hopcount, RIO_DEV_ID_CAR, 325eb188d0eSMatt Porter &result); 326eb188d0eSMatt Porter rdev->did = result >> 16; 327eb188d0eSMatt Porter rdev->vid = result & 0xffff; 328eb188d0eSMatt Porter rio_mport_read_config_32(port, destid, hopcount, RIO_DEV_INFO_CAR, 329eb188d0eSMatt Porter &rdev->device_rev); 330eb188d0eSMatt Porter rio_mport_read_config_32(port, destid, hopcount, RIO_ASM_ID_CAR, 331eb188d0eSMatt Porter &result); 332eb188d0eSMatt Porter rdev->asm_did = result >> 16; 333eb188d0eSMatt Porter rdev->asm_vid = result & 0xffff; 334eb188d0eSMatt Porter rio_mport_read_config_32(port, destid, hopcount, RIO_ASM_INFO_CAR, 335eb188d0eSMatt Porter &result); 336eb188d0eSMatt Porter rdev->asm_rev = result >> 16; 337eb188d0eSMatt Porter rio_mport_read_config_32(port, destid, hopcount, RIO_PEF_CAR, 338eb188d0eSMatt Porter &rdev->pef); 339eb188d0eSMatt Porter if (rdev->pef & RIO_PEF_EXT_FEATURES) 340eb188d0eSMatt Porter rdev->efptr = result & 0xffff; 341eb188d0eSMatt Porter 342eb188d0eSMatt Porter rio_mport_read_config_32(port, destid, hopcount, RIO_SRC_OPS_CAR, 343eb188d0eSMatt Porter &rdev->src_ops); 344eb188d0eSMatt Porter rio_mport_read_config_32(port, destid, hopcount, RIO_DST_OPS_CAR, 345eb188d0eSMatt Porter &rdev->dst_ops); 346eb188d0eSMatt Porter 347c70555b0SAlexandre Bounine if (rio_device_has_destid(port, rdev->src_ops, rdev->dst_ops)) { 348c70555b0SAlexandre Bounine if (do_enum) { 349eb188d0eSMatt Porter rio_set_device_id(port, destid, hopcount, next_destid); 350eb188d0eSMatt Porter rdev->destid = next_destid++; 351eb188d0eSMatt Porter if (next_destid == port->host_deviceid) 352eb188d0eSMatt Porter next_destid++; 353eb188d0eSMatt Porter } else 354eb188d0eSMatt Porter rdev->destid = rio_get_device_id(port, destid, hopcount); 355c70555b0SAlexandre Bounine } else 356c70555b0SAlexandre Bounine /* Switch device has an associated destID */ 357c70555b0SAlexandre Bounine rdev->destid = RIO_INVALID_DESTID; 358eb188d0eSMatt Porter 359eb188d0eSMatt Porter /* If a PE has both switch and other functions, show it as a switch */ 360eb188d0eSMatt Porter if (rio_is_switch(rdev)) { 361eb188d0eSMatt Porter rio_mport_read_config_32(port, destid, hopcount, 362eb188d0eSMatt Porter RIO_SWP_INFO_CAR, &rdev->swpinfo); 36307590ff0SAlexandre Bounine rswitch = kzalloc(sizeof(struct rio_switch), GFP_KERNEL); 3645f28c520SYang Li if (!rswitch) 3655f28c520SYang Li goto cleanup; 366eb188d0eSMatt Porter rswitch->switchid = next_switchid; 367eb188d0eSMatt Porter rswitch->hopcount = hopcount; 368c70555b0SAlexandre Bounine rswitch->destid = destid; 369e0423236SZhang Wei rswitch->route_table = kzalloc(sizeof(u8)* 370e0423236SZhang Wei RIO_MAX_ROUTE_ENTRIES(port->sys_size), 371e0423236SZhang Wei GFP_KERNEL); 3725f28c520SYang Li if (!rswitch->route_table) 3735f28c520SYang Li goto cleanup; 374eb188d0eSMatt Porter /* Initialize switch route table */ 375e0423236SZhang Wei for (rdid = 0; rdid < RIO_MAX_ROUTE_ENTRIES(port->sys_size); 376e0423236SZhang Wei rdid++) 377eb188d0eSMatt Porter rswitch->route_table[rdid] = RIO_INVALID_ROUTE; 378eb188d0eSMatt Porter rdev->rswitch = rswitch; 379b53c7583SKay Sievers dev_set_name(&rdev->dev, "%02x:s:%04x", rdev->net->id, 380eb188d0eSMatt Porter rdev->rswitch->switchid); 381eb188d0eSMatt Porter rio_route_set_ops(rdev); 382eb188d0eSMatt Porter 38307590ff0SAlexandre Bounine if (do_enum && rdev->rswitch->clr_table) 38407590ff0SAlexandre Bounine rdev->rswitch->clr_table(port, destid, hopcount, 38507590ff0SAlexandre Bounine RIO_GLOBAL_TABLE); 38607590ff0SAlexandre Bounine 387eb188d0eSMatt Porter list_add_tail(&rswitch->node, &rio_switches); 388eb188d0eSMatt Porter 389eb188d0eSMatt Porter } else 390b53c7583SKay Sievers dev_set_name(&rdev->dev, "%02x:e:%04x", rdev->net->id, 391eb188d0eSMatt Porter rdev->destid); 392eb188d0eSMatt Porter 393eb188d0eSMatt Porter rdev->dev.bus = &rio_bus_type; 394eb188d0eSMatt Porter 395eb188d0eSMatt Porter device_initialize(&rdev->dev); 396eb188d0eSMatt Porter rdev->dev.release = rio_release_dev; 397eb188d0eSMatt Porter rio_dev_get(rdev); 398eb188d0eSMatt Porter 399284901a9SYang Hongyang rdev->dma_mask = DMA_BIT_MASK(32); 400fa78cc51SMatt Porter rdev->dev.dma_mask = &rdev->dma_mask; 401284901a9SYang Hongyang rdev->dev.coherent_dma_mask = DMA_BIT_MASK(32); 402eb188d0eSMatt Porter 403eb188d0eSMatt Porter if ((rdev->pef & RIO_PEF_INB_DOORBELL) && 404eb188d0eSMatt Porter (rdev->dst_ops & RIO_DST_OPS_DOORBELL)) 405eb188d0eSMatt Porter rio_init_dbell_res(&rdev->riores[RIO_DOORBELL_RESOURCE], 406eb188d0eSMatt Porter 0, 0xffff); 407eb188d0eSMatt Porter 4085f28c520SYang Li ret = rio_add_device(rdev); 4095f28c520SYang Li if (ret) 4105f28c520SYang Li goto cleanup; 411eb188d0eSMatt Porter 412eb188d0eSMatt Porter return rdev; 4135f28c520SYang Li 4145f28c520SYang Li cleanup: 4155f28c520SYang Li if (rswitch) { 4165f28c520SYang Li kfree(rswitch->route_table); 4175f28c520SYang Li kfree(rswitch); 4185f28c520SYang Li } 4195f28c520SYang Li kfree(rdev); 4205f28c520SYang Li return NULL; 421eb188d0eSMatt Porter } 422eb188d0eSMatt Porter 423eb188d0eSMatt Porter /** 424eb188d0eSMatt Porter * rio_sport_is_active- Tests if a switch port has an active connection. 425eb188d0eSMatt Porter * @port: Master port to send transaction 426eb188d0eSMatt Porter * @destid: Associated destination ID for switch 427eb188d0eSMatt Porter * @hopcount: Hopcount to reach switch 428eb188d0eSMatt Porter * @sport: Switch port number 429eb188d0eSMatt Porter * 430eb188d0eSMatt Porter * Reads the port error status CSR for a particular switch port to 431eb188d0eSMatt Porter * determine if the port has an active link. Returns 432eb188d0eSMatt Porter * %PORT_N_ERR_STS_PORT_OK if the port is active or %0 if it is 433eb188d0eSMatt Porter * inactive. 434eb188d0eSMatt Porter */ 435eb188d0eSMatt Porter static int 436eb188d0eSMatt Porter rio_sport_is_active(struct rio_mport *port, u16 destid, u8 hopcount, int sport) 437eb188d0eSMatt Porter { 438eb188d0eSMatt Porter u32 result; 439eb188d0eSMatt Porter u32 ext_ftr_ptr; 440eb188d0eSMatt Porter 441eb188d0eSMatt Porter int *entry = rio_sport_phys_table; 442eb188d0eSMatt Porter 443eb188d0eSMatt Porter do { 444eb188d0eSMatt Porter if ((ext_ftr_ptr = 445eb188d0eSMatt Porter rio_mport_get_feature(port, 0, destid, hopcount, *entry))) 446eb188d0eSMatt Porter 447eb188d0eSMatt Porter break; 448eb188d0eSMatt Porter } while (*++entry >= 0); 449eb188d0eSMatt Porter 450eb188d0eSMatt Porter if (ext_ftr_ptr) 451eb188d0eSMatt Porter rio_mport_read_config_32(port, destid, hopcount, 452eb188d0eSMatt Porter ext_ftr_ptr + 453eb188d0eSMatt Porter RIO_PORT_N_ERR_STS_CSR(sport), 454eb188d0eSMatt Porter &result); 455eb188d0eSMatt Porter 456eb188d0eSMatt Porter return (result & PORT_N_ERR_STS_PORT_OK); 457eb188d0eSMatt Porter } 458eb188d0eSMatt Porter 459eb188d0eSMatt Porter /** 460818a04a0SAlexandre Bounine * rio_lock_device - Acquires host device lock for specified device 461818a04a0SAlexandre Bounine * @port: Master port to send transaction 462818a04a0SAlexandre Bounine * @destid: Destination ID for device/switch 463818a04a0SAlexandre Bounine * @hopcount: Hopcount to reach switch 464818a04a0SAlexandre Bounine * @wait_ms: Max wait time in msec (0 = no timeout) 465818a04a0SAlexandre Bounine * 466818a04a0SAlexandre Bounine * Attepts to acquire host device lock for specified device 467818a04a0SAlexandre Bounine * Returns 0 if device lock acquired or EINVAL if timeout expires. 468818a04a0SAlexandre Bounine */ 469818a04a0SAlexandre Bounine static int 470818a04a0SAlexandre Bounine rio_lock_device(struct rio_mport *port, u16 destid, u8 hopcount, int wait_ms) 471818a04a0SAlexandre Bounine { 472818a04a0SAlexandre Bounine u32 result; 473818a04a0SAlexandre Bounine int tcnt = 0; 474818a04a0SAlexandre Bounine 475818a04a0SAlexandre Bounine /* Attempt to acquire device lock */ 476818a04a0SAlexandre Bounine rio_mport_write_config_32(port, destid, hopcount, 477818a04a0SAlexandre Bounine RIO_HOST_DID_LOCK_CSR, port->host_deviceid); 478818a04a0SAlexandre Bounine rio_mport_read_config_32(port, destid, hopcount, 479818a04a0SAlexandre Bounine RIO_HOST_DID_LOCK_CSR, &result); 480818a04a0SAlexandre Bounine 481818a04a0SAlexandre Bounine while (result != port->host_deviceid) { 482818a04a0SAlexandre Bounine if (wait_ms != 0 && tcnt == wait_ms) { 483818a04a0SAlexandre Bounine pr_debug("RIO: timeout when locking device %x:%x\n", 484818a04a0SAlexandre Bounine destid, hopcount); 485818a04a0SAlexandre Bounine return -EINVAL; 486818a04a0SAlexandre Bounine } 487818a04a0SAlexandre Bounine 488818a04a0SAlexandre Bounine /* Delay a bit */ 489818a04a0SAlexandre Bounine mdelay(1); 490818a04a0SAlexandre Bounine tcnt++; 491818a04a0SAlexandre Bounine /* Try to acquire device lock again */ 492818a04a0SAlexandre Bounine rio_mport_write_config_32(port, destid, 493818a04a0SAlexandre Bounine hopcount, 494818a04a0SAlexandre Bounine RIO_HOST_DID_LOCK_CSR, 495818a04a0SAlexandre Bounine port->host_deviceid); 496818a04a0SAlexandre Bounine rio_mport_read_config_32(port, destid, 497818a04a0SAlexandre Bounine hopcount, 498818a04a0SAlexandre Bounine RIO_HOST_DID_LOCK_CSR, &result); 499818a04a0SAlexandre Bounine } 500818a04a0SAlexandre Bounine 501818a04a0SAlexandre Bounine return 0; 502818a04a0SAlexandre Bounine } 503818a04a0SAlexandre Bounine 504818a04a0SAlexandre Bounine /** 505818a04a0SAlexandre Bounine * rio_unlock_device - Releases host device lock for specified device 506818a04a0SAlexandre Bounine * @port: Master port to send transaction 507818a04a0SAlexandre Bounine * @destid: Destination ID for device/switch 508818a04a0SAlexandre Bounine * @hopcount: Hopcount to reach switch 509818a04a0SAlexandre Bounine * 510818a04a0SAlexandre Bounine * Returns 0 if device lock released or EINVAL if fails. 511818a04a0SAlexandre Bounine */ 512818a04a0SAlexandre Bounine static int 513818a04a0SAlexandre Bounine rio_unlock_device(struct rio_mport *port, u16 destid, u8 hopcount) 514818a04a0SAlexandre Bounine { 515818a04a0SAlexandre Bounine u32 result; 516818a04a0SAlexandre Bounine 517818a04a0SAlexandre Bounine /* Release device lock */ 518818a04a0SAlexandre Bounine rio_mport_write_config_32(port, destid, 519818a04a0SAlexandre Bounine hopcount, 520818a04a0SAlexandre Bounine RIO_HOST_DID_LOCK_CSR, 521818a04a0SAlexandre Bounine port->host_deviceid); 522818a04a0SAlexandre Bounine rio_mport_read_config_32(port, destid, hopcount, 523818a04a0SAlexandre Bounine RIO_HOST_DID_LOCK_CSR, &result); 524818a04a0SAlexandre Bounine if ((result & 0xffff) != 0xffff) { 525818a04a0SAlexandre Bounine pr_debug("RIO: badness when releasing device lock %x:%x\n", 526818a04a0SAlexandre Bounine destid, hopcount); 527818a04a0SAlexandre Bounine return -EINVAL; 528818a04a0SAlexandre Bounine } 529818a04a0SAlexandre Bounine 530818a04a0SAlexandre Bounine return 0; 531818a04a0SAlexandre Bounine } 532818a04a0SAlexandre Bounine 533818a04a0SAlexandre Bounine /** 534eb188d0eSMatt Porter * rio_route_add_entry- Add a route entry to a switch routing table 535eb188d0eSMatt Porter * @mport: Master port to send transaction 536c70555b0SAlexandre Bounine * @rswitch: Switch device 537eb188d0eSMatt Porter * @table: Routing table ID 538eb188d0eSMatt Porter * @route_destid: Destination ID to be routed 539eb188d0eSMatt Porter * @route_port: Port number to be routed 540818a04a0SAlexandre Bounine * @lock: lock switch device flag 541eb188d0eSMatt Porter * 542eb188d0eSMatt Porter * Calls the switch specific add_entry() method to add a route entry 543eb188d0eSMatt Porter * on a switch. The route table can be specified using the @table 544eb188d0eSMatt Porter * argument if a switch has per port routing tables or the normal 545eb188d0eSMatt Porter * use is to specific all tables (or the global table) by passing 546eb188d0eSMatt Porter * %RIO_GLOBAL_TABLE in @table. Returns %0 on success or %-EINVAL 547eb188d0eSMatt Porter * on failure. 548eb188d0eSMatt Porter */ 549818a04a0SAlexandre Bounine static int 550818a04a0SAlexandre Bounine rio_route_add_entry(struct rio_mport *mport, struct rio_switch *rswitch, 551818a04a0SAlexandre Bounine u16 table, u16 route_destid, u8 route_port, int lock) 552eb188d0eSMatt Porter { 553818a04a0SAlexandre Bounine int rc; 554818a04a0SAlexandre Bounine 555818a04a0SAlexandre Bounine if (lock) { 556818a04a0SAlexandre Bounine rc = rio_lock_device(mport, rswitch->destid, 557818a04a0SAlexandre Bounine rswitch->hopcount, 1000); 558818a04a0SAlexandre Bounine if (rc) 559818a04a0SAlexandre Bounine return rc; 560818a04a0SAlexandre Bounine } 561818a04a0SAlexandre Bounine 562818a04a0SAlexandre Bounine rc = rswitch->add_entry(mport, rswitch->destid, 563c70555b0SAlexandre Bounine rswitch->hopcount, table, 564eb188d0eSMatt Porter route_destid, route_port); 565818a04a0SAlexandre Bounine if (lock) 566818a04a0SAlexandre Bounine rio_unlock_device(mport, rswitch->destid, rswitch->hopcount); 567818a04a0SAlexandre Bounine 568818a04a0SAlexandre Bounine return rc; 569eb188d0eSMatt Porter } 570eb188d0eSMatt Porter 571eb188d0eSMatt Porter /** 572eb188d0eSMatt Porter * rio_route_get_entry- Read a route entry in a switch routing table 573eb188d0eSMatt Porter * @mport: Master port to send transaction 574c70555b0SAlexandre Bounine * @rswitch: Switch device 575eb188d0eSMatt Porter * @table: Routing table ID 576eb188d0eSMatt Porter * @route_destid: Destination ID to be routed 577eb188d0eSMatt Porter * @route_port: Pointer to read port number into 578818a04a0SAlexandre Bounine * @lock: lock switch device flag 579eb188d0eSMatt Porter * 580eb188d0eSMatt Porter * Calls the switch specific get_entry() method to read a route entry 581eb188d0eSMatt Porter * in a switch. The route table can be specified using the @table 582eb188d0eSMatt Porter * argument if a switch has per port routing tables or the normal 583eb188d0eSMatt Porter * use is to specific all tables (or the global table) by passing 584eb188d0eSMatt Porter * %RIO_GLOBAL_TABLE in @table. Returns %0 on success or %-EINVAL 585eb188d0eSMatt Porter * on failure. 586eb188d0eSMatt Porter */ 587eb188d0eSMatt Porter static int 588c70555b0SAlexandre Bounine rio_route_get_entry(struct rio_mport *mport, struct rio_switch *rswitch, u16 table, 589818a04a0SAlexandre Bounine u16 route_destid, u8 *route_port, int lock) 590eb188d0eSMatt Porter { 591818a04a0SAlexandre Bounine int rc; 592818a04a0SAlexandre Bounine 593818a04a0SAlexandre Bounine if (lock) { 594818a04a0SAlexandre Bounine rc = rio_lock_device(mport, rswitch->destid, 595818a04a0SAlexandre Bounine rswitch->hopcount, 1000); 596818a04a0SAlexandre Bounine if (rc) 597818a04a0SAlexandre Bounine return rc; 598818a04a0SAlexandre Bounine } 599818a04a0SAlexandre Bounine 600818a04a0SAlexandre Bounine rc = rswitch->get_entry(mport, rswitch->destid, 601c70555b0SAlexandre Bounine rswitch->hopcount, table, 602eb188d0eSMatt Porter route_destid, route_port); 603818a04a0SAlexandre Bounine if (lock) 604818a04a0SAlexandre Bounine rio_unlock_device(mport, rswitch->destid, rswitch->hopcount); 605818a04a0SAlexandre Bounine 606818a04a0SAlexandre Bounine return rc; 607eb188d0eSMatt Porter } 608eb188d0eSMatt Porter 609eb188d0eSMatt Porter /** 610eb188d0eSMatt Porter * rio_get_host_deviceid_lock- Reads the Host Device ID Lock CSR on a device 611eb188d0eSMatt Porter * @port: Master port to send transaction 612eb188d0eSMatt Porter * @hopcount: Number of hops to the device 613eb188d0eSMatt Porter * 614eb188d0eSMatt Porter * Used during enumeration to read the Host Device ID Lock CSR on a 615eb188d0eSMatt Porter * RIO device. Returns the value of the lock register. 616eb188d0eSMatt Porter */ 617eb188d0eSMatt Porter static u16 rio_get_host_deviceid_lock(struct rio_mport *port, u8 hopcount) 618eb188d0eSMatt Porter { 619eb188d0eSMatt Porter u32 result; 620eb188d0eSMatt Porter 621e0423236SZhang Wei rio_mport_read_config_32(port, RIO_ANY_DESTID(port->sys_size), hopcount, 622eb188d0eSMatt Porter RIO_HOST_DID_LOCK_CSR, &result); 623eb188d0eSMatt Porter 624eb188d0eSMatt Porter return (u16) (result & 0xffff); 625eb188d0eSMatt Porter } 626eb188d0eSMatt Porter 627eb188d0eSMatt Porter /** 628eb188d0eSMatt Porter * rio_get_swpinfo_inport- Gets the ingress port number 629eb188d0eSMatt Porter * @mport: Master port to send transaction 630eb188d0eSMatt Porter * @destid: Destination ID associated with the switch 631eb188d0eSMatt Porter * @hopcount: Number of hops to the device 632eb188d0eSMatt Porter * 633eb188d0eSMatt Porter * Returns port number being used to access the switch device. 634eb188d0eSMatt Porter */ 635eb188d0eSMatt Porter static u8 636eb188d0eSMatt Porter rio_get_swpinfo_inport(struct rio_mport *mport, u16 destid, u8 hopcount) 637eb188d0eSMatt Porter { 638eb188d0eSMatt Porter u32 result; 639eb188d0eSMatt Porter 640eb188d0eSMatt Porter rio_mport_read_config_32(mport, destid, hopcount, RIO_SWP_INFO_CAR, 641eb188d0eSMatt Porter &result); 642eb188d0eSMatt Porter 643eb188d0eSMatt Porter return (u8) (result & 0xff); 644eb188d0eSMatt Porter } 645eb188d0eSMatt Porter 646eb188d0eSMatt Porter /** 647eb188d0eSMatt Porter * rio_get_swpinfo_tports- Gets total number of ports on the switch 648eb188d0eSMatt Porter * @mport: Master port to send transaction 649eb188d0eSMatt Porter * @destid: Destination ID associated with the switch 650eb188d0eSMatt Porter * @hopcount: Number of hops to the device 651eb188d0eSMatt Porter * 652eb188d0eSMatt Porter * Returns total numbers of ports implemented by the switch device. 653eb188d0eSMatt Porter */ 654eb188d0eSMatt Porter static u8 rio_get_swpinfo_tports(struct rio_mport *mport, u16 destid, 655eb188d0eSMatt Porter u8 hopcount) 656eb188d0eSMatt Porter { 657eb188d0eSMatt Porter u32 result; 658eb188d0eSMatt Porter 659eb188d0eSMatt Porter rio_mport_read_config_32(mport, destid, hopcount, RIO_SWP_INFO_CAR, 660eb188d0eSMatt Porter &result); 661eb188d0eSMatt Porter 662eb188d0eSMatt Porter return RIO_GET_TOTAL_PORTS(result); 663eb188d0eSMatt Porter } 664eb188d0eSMatt Porter 665eb188d0eSMatt Porter /** 666eb188d0eSMatt Porter * rio_net_add_mport- Add a master port to a RIO network 667eb188d0eSMatt Porter * @net: RIO network 668eb188d0eSMatt Porter * @port: Master port to add 669eb188d0eSMatt Porter * 670eb188d0eSMatt Porter * Adds a master port to the network list of associated master 671eb188d0eSMatt Porter * ports.. 672eb188d0eSMatt Porter */ 673eb188d0eSMatt Porter static void rio_net_add_mport(struct rio_net *net, struct rio_mport *port) 674eb188d0eSMatt Porter { 675eb188d0eSMatt Porter spin_lock(&rio_global_list_lock); 676eb188d0eSMatt Porter list_add_tail(&port->nnode, &net->mports); 677eb188d0eSMatt Porter spin_unlock(&rio_global_list_lock); 678eb188d0eSMatt Porter } 679eb188d0eSMatt Porter 680eb188d0eSMatt Porter /** 681eb188d0eSMatt Porter * rio_enum_peer- Recursively enumerate a RIO network through a master port 682eb188d0eSMatt Porter * @net: RIO network being enumerated 683eb188d0eSMatt Porter * @port: Master port to send transactions 684eb188d0eSMatt Porter * @hopcount: Number of hops into the network 685eb188d0eSMatt Porter * 686eb188d0eSMatt Porter * Recursively enumerates a RIO network. Transactions are sent via the 687eb188d0eSMatt Porter * master port passed in @port. 688eb188d0eSMatt Porter */ 689181a6ff0SLi Yang static int __devinit rio_enum_peer(struct rio_net *net, struct rio_mport *port, 690eb188d0eSMatt Porter u8 hopcount) 691eb188d0eSMatt Porter { 692eb188d0eSMatt Porter int port_num; 693eb188d0eSMatt Porter int num_ports; 694eb188d0eSMatt Porter int cur_destid; 695c70555b0SAlexandre Bounine int sw_destid; 696c70555b0SAlexandre Bounine int sw_inport; 697eb188d0eSMatt Porter struct rio_dev *rdev; 698eb188d0eSMatt Porter u16 destid; 699eb188d0eSMatt Porter int tmp; 700eb188d0eSMatt Porter 701eb188d0eSMatt Porter if (rio_get_host_deviceid_lock(port, hopcount) == port->host_deviceid) { 702eb188d0eSMatt Porter pr_debug("RIO: PE already discovered by this host\n"); 703eb188d0eSMatt Porter /* 704eb188d0eSMatt Porter * Already discovered by this host. Add it as another 705eb188d0eSMatt Porter * master port for the current network. 706eb188d0eSMatt Porter */ 707eb188d0eSMatt Porter rio_net_add_mport(net, port); 708eb188d0eSMatt Porter return 0; 709eb188d0eSMatt Porter } 710eb188d0eSMatt Porter 711eb188d0eSMatt Porter /* Attempt to acquire device lock */ 712e0423236SZhang Wei rio_mport_write_config_32(port, RIO_ANY_DESTID(port->sys_size), 713e0423236SZhang Wei hopcount, 714eb188d0eSMatt Porter RIO_HOST_DID_LOCK_CSR, port->host_deviceid); 715eb188d0eSMatt Porter while ((tmp = rio_get_host_deviceid_lock(port, hopcount)) 716eb188d0eSMatt Porter < port->host_deviceid) { 717eb188d0eSMatt Porter /* Delay a bit */ 718eb188d0eSMatt Porter mdelay(1); 719eb188d0eSMatt Porter /* Attempt to acquire device lock again */ 720e0423236SZhang Wei rio_mport_write_config_32(port, RIO_ANY_DESTID(port->sys_size), 721e0423236SZhang Wei hopcount, 722eb188d0eSMatt Porter RIO_HOST_DID_LOCK_CSR, 723eb188d0eSMatt Porter port->host_deviceid); 724eb188d0eSMatt Porter } 725eb188d0eSMatt Porter 726eb188d0eSMatt Porter if (rio_get_host_deviceid_lock(port, hopcount) > port->host_deviceid) { 727eb188d0eSMatt Porter pr_debug( 728eb188d0eSMatt Porter "RIO: PE locked by a higher priority host...retreating\n"); 729eb188d0eSMatt Porter return -1; 730eb188d0eSMatt Porter } 731eb188d0eSMatt Porter 732eb188d0eSMatt Porter /* Setup new RIO device */ 733e0423236SZhang Wei rdev = rio_setup_device(net, port, RIO_ANY_DESTID(port->sys_size), 734e0423236SZhang Wei hopcount, 1); 735e0423236SZhang Wei if (rdev) { 736eb188d0eSMatt Porter /* Add device to the global and bus/net specific list. */ 737eb188d0eSMatt Porter list_add_tail(&rdev->net_list, &net->devices); 738eb188d0eSMatt Porter } else 739eb188d0eSMatt Porter return -1; 740eb188d0eSMatt Porter 741eb188d0eSMatt Porter if (rio_is_switch(rdev)) { 742eb188d0eSMatt Porter next_switchid++; 743e0423236SZhang Wei sw_inport = rio_get_swpinfo_inport(port, 744e0423236SZhang Wei RIO_ANY_DESTID(port->sys_size), hopcount); 745c70555b0SAlexandre Bounine rio_route_add_entry(port, rdev->rswitch, RIO_GLOBAL_TABLE, 746818a04a0SAlexandre Bounine port->host_deviceid, sw_inport, 0); 747c70555b0SAlexandre Bounine rdev->rswitch->route_table[port->host_deviceid] = sw_inport; 748eb188d0eSMatt Porter 749eb188d0eSMatt Porter for (destid = 0; destid < next_destid; destid++) { 750c70555b0SAlexandre Bounine if (destid == port->host_deviceid) 751c70555b0SAlexandre Bounine continue; 752c70555b0SAlexandre Bounine rio_route_add_entry(port, rdev->rswitch, RIO_GLOBAL_TABLE, 753818a04a0SAlexandre Bounine destid, sw_inport, 0); 754c70555b0SAlexandre Bounine rdev->rswitch->route_table[destid] = sw_inport; 755eb188d0eSMatt Porter } 756eb188d0eSMatt Porter 757eb188d0eSMatt Porter num_ports = 758e0423236SZhang Wei rio_get_swpinfo_tports(port, RIO_ANY_DESTID(port->sys_size), 759e0423236SZhang Wei hopcount); 760eb188d0eSMatt Porter pr_debug( 761eb188d0eSMatt Porter "RIO: found %s (vid %4.4x did %4.4x) with %d ports\n", 762eb188d0eSMatt Porter rio_name(rdev), rdev->vid, rdev->did, num_ports); 763c70555b0SAlexandre Bounine sw_destid = next_destid; 764eb188d0eSMatt Porter for (port_num = 0; port_num < num_ports; port_num++) { 765c70555b0SAlexandre Bounine if (sw_inport == port_num) 766eb188d0eSMatt Porter continue; 767eb188d0eSMatt Porter 768eb188d0eSMatt Porter cur_destid = next_destid; 769eb188d0eSMatt Porter 770eb188d0eSMatt Porter if (rio_sport_is_active 771e0423236SZhang Wei (port, RIO_ANY_DESTID(port->sys_size), hopcount, 772e0423236SZhang Wei port_num)) { 773eb188d0eSMatt Porter pr_debug( 774eb188d0eSMatt Porter "RIO: scanning device on port %d\n", 775eb188d0eSMatt Porter port_num); 776c70555b0SAlexandre Bounine rio_route_add_entry(port, rdev->rswitch, 777eb188d0eSMatt Porter RIO_GLOBAL_TABLE, 778e0423236SZhang Wei RIO_ANY_DESTID(port->sys_size), 779818a04a0SAlexandre Bounine port_num, 0); 780eb188d0eSMatt Porter 781eb188d0eSMatt Porter if (rio_enum_peer(net, port, hopcount + 1) < 0) 782eb188d0eSMatt Porter return -1; 783eb188d0eSMatt Porter 784eb188d0eSMatt Porter /* Update routing tables */ 785eb188d0eSMatt Porter if (next_destid > cur_destid) { 786eb188d0eSMatt Porter for (destid = cur_destid; 787eb188d0eSMatt Porter destid < next_destid; destid++) { 788c70555b0SAlexandre Bounine if (destid == port->host_deviceid) 789c70555b0SAlexandre Bounine continue; 790c70555b0SAlexandre Bounine rio_route_add_entry(port, rdev->rswitch, 791eb188d0eSMatt Porter RIO_GLOBAL_TABLE, 792eb188d0eSMatt Porter destid, 793818a04a0SAlexandre Bounine port_num, 794818a04a0SAlexandre Bounine 0); 795eb188d0eSMatt Porter rdev->rswitch-> 796eb188d0eSMatt Porter route_table[destid] = 797eb188d0eSMatt Porter port_num; 798eb188d0eSMatt Porter } 799eb188d0eSMatt Porter } 800eb188d0eSMatt Porter } 801eb188d0eSMatt Porter } 802c70555b0SAlexandre Bounine 803c70555b0SAlexandre Bounine /* Check for empty switch */ 804c70555b0SAlexandre Bounine if (next_destid == sw_destid) { 805c70555b0SAlexandre Bounine next_destid++; 806c70555b0SAlexandre Bounine if (next_destid == port->host_deviceid) 807c70555b0SAlexandre Bounine next_destid++; 808c70555b0SAlexandre Bounine } 809c70555b0SAlexandre Bounine 810c70555b0SAlexandre Bounine rdev->rswitch->destid = sw_destid; 811eb188d0eSMatt Porter } else 812eb188d0eSMatt Porter pr_debug("RIO: found %s (vid %4.4x did %4.4x)\n", 813eb188d0eSMatt Porter rio_name(rdev), rdev->vid, rdev->did); 814eb188d0eSMatt Porter 815eb188d0eSMatt Porter return 0; 816eb188d0eSMatt Porter } 817eb188d0eSMatt Porter 818eb188d0eSMatt Porter /** 819eb188d0eSMatt Porter * rio_enum_complete- Tests if enumeration of a network is complete 820eb188d0eSMatt Porter * @port: Master port to send transaction 821eb188d0eSMatt Porter * 822eb188d0eSMatt Porter * Tests the Component Tag CSR for presence of the magic enumeration 823eb188d0eSMatt Porter * complete flag. Return %1 if enumeration is complete or %0 if 824eb188d0eSMatt Porter * enumeration is incomplete. 825eb188d0eSMatt Porter */ 826eb188d0eSMatt Porter static int rio_enum_complete(struct rio_mport *port) 827eb188d0eSMatt Porter { 828eb188d0eSMatt Porter u32 tag_csr; 829eb188d0eSMatt Porter int ret = 0; 830eb188d0eSMatt Porter 831eb188d0eSMatt Porter rio_local_read_config_32(port, RIO_COMPONENT_TAG_CSR, &tag_csr); 832eb188d0eSMatt Porter 833eb188d0eSMatt Porter if (tag_csr == RIO_ENUM_CMPL_MAGIC) 834eb188d0eSMatt Porter ret = 1; 835eb188d0eSMatt Porter 836eb188d0eSMatt Porter return ret; 837eb188d0eSMatt Porter } 838eb188d0eSMatt Porter 839eb188d0eSMatt Porter /** 840eb188d0eSMatt Porter * rio_disc_peer- Recursively discovers a RIO network through a master port 841eb188d0eSMatt Porter * @net: RIO network being discovered 842eb188d0eSMatt Porter * @port: Master port to send transactions 843eb188d0eSMatt Porter * @destid: Current destination ID in network 844eb188d0eSMatt Porter * @hopcount: Number of hops into the network 845eb188d0eSMatt Porter * 846eb188d0eSMatt Porter * Recursively discovers a RIO network. Transactions are sent via the 847eb188d0eSMatt Porter * master port passed in @port. 848eb188d0eSMatt Porter */ 849181a6ff0SLi Yang static int __devinit 850eb188d0eSMatt Porter rio_disc_peer(struct rio_net *net, struct rio_mport *port, u16 destid, 851eb188d0eSMatt Porter u8 hopcount) 852eb188d0eSMatt Porter { 853eb188d0eSMatt Porter u8 port_num, route_port; 854eb188d0eSMatt Porter int num_ports; 855eb188d0eSMatt Porter struct rio_dev *rdev; 856eb188d0eSMatt Porter u16 ndestid; 857eb188d0eSMatt Porter 858eb188d0eSMatt Porter /* Setup new RIO device */ 859eb188d0eSMatt Porter if ((rdev = rio_setup_device(net, port, destid, hopcount, 0))) { 860eb188d0eSMatt Porter /* Add device to the global and bus/net specific list. */ 861eb188d0eSMatt Porter list_add_tail(&rdev->net_list, &net->devices); 862eb188d0eSMatt Porter } else 863eb188d0eSMatt Porter return -1; 864eb188d0eSMatt Porter 865eb188d0eSMatt Porter if (rio_is_switch(rdev)) { 866eb188d0eSMatt Porter next_switchid++; 867eb188d0eSMatt Porter 868eb188d0eSMatt Porter /* Associated destid is how we accessed this switch */ 869eb188d0eSMatt Porter rdev->rswitch->destid = destid; 870eb188d0eSMatt Porter 871eb188d0eSMatt Porter num_ports = rio_get_swpinfo_tports(port, destid, hopcount); 872eb188d0eSMatt Porter pr_debug( 873eb188d0eSMatt Porter "RIO: found %s (vid %4.4x did %4.4x) with %d ports\n", 874eb188d0eSMatt Porter rio_name(rdev), rdev->vid, rdev->did, num_ports); 875eb188d0eSMatt Porter for (port_num = 0; port_num < num_ports; port_num++) { 876eb188d0eSMatt Porter if (rio_get_swpinfo_inport(port, destid, hopcount) == 877eb188d0eSMatt Porter port_num) 878eb188d0eSMatt Porter continue; 879eb188d0eSMatt Porter 880eb188d0eSMatt Porter if (rio_sport_is_active 881eb188d0eSMatt Porter (port, destid, hopcount, port_num)) { 882eb188d0eSMatt Porter pr_debug( 883eb188d0eSMatt Porter "RIO: scanning device on port %d\n", 884eb188d0eSMatt Porter port_num); 885818a04a0SAlexandre Bounine 886818a04a0SAlexandre Bounine rio_lock_device(port, destid, hopcount, 1000); 887818a04a0SAlexandre Bounine 888e0423236SZhang Wei for (ndestid = 0; 889e0423236SZhang Wei ndestid < RIO_ANY_DESTID(port->sys_size); 890eb188d0eSMatt Porter ndestid++) { 891c70555b0SAlexandre Bounine rio_route_get_entry(port, rdev->rswitch, 892eb188d0eSMatt Porter RIO_GLOBAL_TABLE, 893eb188d0eSMatt Porter ndestid, 894818a04a0SAlexandre Bounine &route_port, 0); 895eb188d0eSMatt Porter if (route_port == port_num) 896eb188d0eSMatt Porter break; 897eb188d0eSMatt Porter } 898eb188d0eSMatt Porter 899818a04a0SAlexandre Bounine rio_unlock_device(port, destid, hopcount); 900eb188d0eSMatt Porter if (rio_disc_peer 901eb188d0eSMatt Porter (net, port, ndestid, hopcount + 1) < 0) 902eb188d0eSMatt Porter return -1; 903eb188d0eSMatt Porter } 904eb188d0eSMatt Porter } 905eb188d0eSMatt Porter } else 906eb188d0eSMatt Porter pr_debug("RIO: found %s (vid %4.4x did %4.4x)\n", 907eb188d0eSMatt Porter rio_name(rdev), rdev->vid, rdev->did); 908eb188d0eSMatt Porter 909eb188d0eSMatt Porter return 0; 910eb188d0eSMatt Porter } 911eb188d0eSMatt Porter 912eb188d0eSMatt Porter /** 913eb188d0eSMatt Porter * rio_mport_is_active- Tests if master port link is active 914eb188d0eSMatt Porter * @port: Master port to test 915eb188d0eSMatt Porter * 916eb188d0eSMatt Porter * Reads the port error status CSR for the master port to 917eb188d0eSMatt Porter * determine if the port has an active link. Returns 918eb188d0eSMatt Porter * %PORT_N_ERR_STS_PORT_OK if the master port is active 919eb188d0eSMatt Porter * or %0 if it is inactive. 920eb188d0eSMatt Porter */ 921eb188d0eSMatt Porter static int rio_mport_is_active(struct rio_mport *port) 922eb188d0eSMatt Porter { 923eb188d0eSMatt Porter u32 result = 0; 924eb188d0eSMatt Porter u32 ext_ftr_ptr; 925eb188d0eSMatt Porter int *entry = rio_mport_phys_table; 926eb188d0eSMatt Porter 927eb188d0eSMatt Porter do { 928eb188d0eSMatt Porter if ((ext_ftr_ptr = 929eb188d0eSMatt Porter rio_mport_get_feature(port, 1, 0, 0, *entry))) 930eb188d0eSMatt Porter break; 931eb188d0eSMatt Porter } while (*++entry >= 0); 932eb188d0eSMatt Porter 933eb188d0eSMatt Porter if (ext_ftr_ptr) 934eb188d0eSMatt Porter rio_local_read_config_32(port, 935eb188d0eSMatt Porter ext_ftr_ptr + 936eb188d0eSMatt Porter RIO_PORT_N_ERR_STS_CSR(port->index), 937eb188d0eSMatt Porter &result); 938eb188d0eSMatt Porter 939eb188d0eSMatt Porter return (result & PORT_N_ERR_STS_PORT_OK); 940eb188d0eSMatt Porter } 941eb188d0eSMatt Porter 942eb188d0eSMatt Porter /** 943eb188d0eSMatt Porter * rio_alloc_net- Allocate and configure a new RIO network 944eb188d0eSMatt Porter * @port: Master port associated with the RIO network 945eb188d0eSMatt Porter * 946eb188d0eSMatt Porter * Allocates a RIO network structure, initializes per-network 947eb188d0eSMatt Porter * list heads, and adds the associated master port to the 948eb188d0eSMatt Porter * network list of associated master ports. Returns a 949eb188d0eSMatt Porter * RIO network pointer on success or %NULL on failure. 950eb188d0eSMatt Porter */ 951eb188d0eSMatt Porter static struct rio_net __devinit *rio_alloc_net(struct rio_mport *port) 952eb188d0eSMatt Porter { 953eb188d0eSMatt Porter struct rio_net *net; 954eb188d0eSMatt Porter 955dd00cc48SYoann Padioleau net = kzalloc(sizeof(struct rio_net), GFP_KERNEL); 956eb188d0eSMatt Porter if (net) { 957eb188d0eSMatt Porter INIT_LIST_HEAD(&net->node); 958eb188d0eSMatt Porter INIT_LIST_HEAD(&net->devices); 959eb188d0eSMatt Porter INIT_LIST_HEAD(&net->mports); 960eb188d0eSMatt Porter list_add_tail(&port->nnode, &net->mports); 961eb188d0eSMatt Porter net->hport = port; 962eb188d0eSMatt Porter net->id = next_net++; 963eb188d0eSMatt Porter } 964eb188d0eSMatt Porter return net; 965eb188d0eSMatt Porter } 966eb188d0eSMatt Porter 967eb188d0eSMatt Porter /** 968c70555b0SAlexandre Bounine * rio_update_route_tables- Updates route tables in switches 969c70555b0SAlexandre Bounine * @port: Master port associated with the RIO network 970c70555b0SAlexandre Bounine * 971c70555b0SAlexandre Bounine * For each enumerated device, ensure that each switch in a system 972c70555b0SAlexandre Bounine * has correct routing entries. Add routes for devices that where 973c70555b0SAlexandre Bounine * unknown dirung the first enumeration pass through the switch. 974c70555b0SAlexandre Bounine */ 975c70555b0SAlexandre Bounine static void rio_update_route_tables(struct rio_mport *port) 976c70555b0SAlexandre Bounine { 977c70555b0SAlexandre Bounine struct rio_dev *rdev; 978c70555b0SAlexandre Bounine struct rio_switch *rswitch; 979c70555b0SAlexandre Bounine u8 sport; 980c70555b0SAlexandre Bounine u16 destid; 981c70555b0SAlexandre Bounine 982c70555b0SAlexandre Bounine list_for_each_entry(rdev, &rio_devices, global_list) { 983c70555b0SAlexandre Bounine 984c70555b0SAlexandre Bounine destid = (rio_is_switch(rdev))?rdev->rswitch->destid:rdev->destid; 985c70555b0SAlexandre Bounine 986c70555b0SAlexandre Bounine list_for_each_entry(rswitch, &rio_switches, node) { 987c70555b0SAlexandre Bounine 988c70555b0SAlexandre Bounine if (rio_is_switch(rdev) && (rdev->rswitch == rswitch)) 989c70555b0SAlexandre Bounine continue; 990c70555b0SAlexandre Bounine 991c70555b0SAlexandre Bounine if (RIO_INVALID_ROUTE == rswitch->route_table[destid]) { 99207590ff0SAlexandre Bounine /* Skip if destid ends in empty switch*/ 99307590ff0SAlexandre Bounine if (rswitch->destid == destid) 99407590ff0SAlexandre Bounine continue; 995c70555b0SAlexandre Bounine 996c70555b0SAlexandre Bounine sport = rio_get_swpinfo_inport(port, 997c70555b0SAlexandre Bounine rswitch->destid, rswitch->hopcount); 998c70555b0SAlexandre Bounine 999c70555b0SAlexandre Bounine if (rswitch->add_entry) { 1000818a04a0SAlexandre Bounine rio_route_add_entry(port, rswitch, 1001818a04a0SAlexandre Bounine RIO_GLOBAL_TABLE, destid, 1002818a04a0SAlexandre Bounine sport, 0); 1003c70555b0SAlexandre Bounine rswitch->route_table[destid] = sport; 1004c70555b0SAlexandre Bounine } 1005c70555b0SAlexandre Bounine } 1006c70555b0SAlexandre Bounine } 1007c70555b0SAlexandre Bounine } 1008c70555b0SAlexandre Bounine } 1009c70555b0SAlexandre Bounine 1010c70555b0SAlexandre Bounine /** 1011eb188d0eSMatt Porter * rio_enum_mport- Start enumeration through a master port 1012eb188d0eSMatt Porter * @mport: Master port to send transactions 1013eb188d0eSMatt Porter * 1014eb188d0eSMatt Porter * Starts the enumeration process. If somebody has enumerated our 1015eb188d0eSMatt Porter * master port device, then give up. If not and we have an active 1016eb188d0eSMatt Porter * link, then start recursive peer enumeration. Returns %0 if 1017eb188d0eSMatt Porter * enumeration succeeds or %-EBUSY if enumeration fails. 1018eb188d0eSMatt Porter */ 101937d33d15SAl Viro int __devinit rio_enum_mport(struct rio_mport *mport) 1020eb188d0eSMatt Porter { 1021eb188d0eSMatt Porter struct rio_net *net = NULL; 1022eb188d0eSMatt Porter int rc = 0; 1023eb188d0eSMatt Porter 1024eb188d0eSMatt Porter printk(KERN_INFO "RIO: enumerate master port %d, %s\n", mport->id, 1025eb188d0eSMatt Porter mport->name); 1026eb188d0eSMatt Porter /* If somebody else enumerated our master port device, bail. */ 1027eb188d0eSMatt Porter if (rio_enum_host(mport) < 0) { 1028eb188d0eSMatt Porter printk(KERN_INFO 1029eb188d0eSMatt Porter "RIO: master port %d device has been enumerated by a remote host\n", 1030eb188d0eSMatt Porter mport->id); 1031eb188d0eSMatt Porter rc = -EBUSY; 1032eb188d0eSMatt Porter goto out; 1033eb188d0eSMatt Porter } 1034eb188d0eSMatt Porter 1035eb188d0eSMatt Porter /* If master port has an active link, allocate net and enum peers */ 1036eb188d0eSMatt Porter if (rio_mport_is_active(mport)) { 1037eb188d0eSMatt Porter if (!(net = rio_alloc_net(mport))) { 1038eb188d0eSMatt Porter printk(KERN_ERR "RIO: failed to allocate new net\n"); 1039eb188d0eSMatt Porter rc = -ENOMEM; 1040eb188d0eSMatt Porter goto out; 1041eb188d0eSMatt Porter } 1042eb188d0eSMatt Porter if (rio_enum_peer(net, mport, 0) < 0) { 1043eb188d0eSMatt Porter /* A higher priority host won enumeration, bail. */ 1044eb188d0eSMatt Porter printk(KERN_INFO 1045eb188d0eSMatt Porter "RIO: master port %d device has lost enumeration to a remote host\n", 1046eb188d0eSMatt Porter mport->id); 1047eb188d0eSMatt Porter rio_clear_locks(mport); 1048eb188d0eSMatt Porter rc = -EBUSY; 1049eb188d0eSMatt Porter goto out; 1050eb188d0eSMatt Porter } 1051c70555b0SAlexandre Bounine rio_update_route_tables(mport); 1052eb188d0eSMatt Porter rio_clear_locks(mport); 1053eb188d0eSMatt Porter } else { 1054eb188d0eSMatt Porter printk(KERN_INFO "RIO: master port %d link inactive\n", 1055eb188d0eSMatt Porter mport->id); 1056eb188d0eSMatt Porter rc = -EINVAL; 1057eb188d0eSMatt Porter } 1058eb188d0eSMatt Porter 1059eb188d0eSMatt Porter out: 1060eb188d0eSMatt Porter return rc; 1061eb188d0eSMatt Porter } 1062eb188d0eSMatt Porter 1063eb188d0eSMatt Porter /** 1064eb188d0eSMatt Porter * rio_build_route_tables- Generate route tables from switch route entries 1065eb188d0eSMatt Porter * 1066eb188d0eSMatt Porter * For each switch device, generate a route table by copying existing 1067eb188d0eSMatt Porter * route entries from the switch. 1068eb188d0eSMatt Porter */ 1069eb188d0eSMatt Porter static void rio_build_route_tables(void) 1070eb188d0eSMatt Porter { 1071eb188d0eSMatt Porter struct rio_dev *rdev; 1072eb188d0eSMatt Porter int i; 1073eb188d0eSMatt Porter u8 sport; 1074eb188d0eSMatt Porter 1075eb188d0eSMatt Porter list_for_each_entry(rdev, &rio_devices, global_list) 1076818a04a0SAlexandre Bounine if (rio_is_switch(rdev)) { 1077818a04a0SAlexandre Bounine rio_lock_device(rdev->net->hport, rdev->rswitch->destid, 1078818a04a0SAlexandre Bounine rdev->rswitch->hopcount, 1000); 1079e0423236SZhang Wei for (i = 0; 1080e0423236SZhang Wei i < RIO_MAX_ROUTE_ENTRIES(rdev->net->hport->sys_size); 1081e0423236SZhang Wei i++) { 1082eb188d0eSMatt Porter if (rio_route_get_entry 1083818a04a0SAlexandre Bounine (rdev->net->hport, rdev->rswitch, 1084818a04a0SAlexandre Bounine RIO_GLOBAL_TABLE, i, &sport, 0) < 0) 1085eb188d0eSMatt Porter continue; 1086eb188d0eSMatt Porter rdev->rswitch->route_table[i] = sport; 1087eb188d0eSMatt Porter } 1088818a04a0SAlexandre Bounine 1089818a04a0SAlexandre Bounine rio_unlock_device(rdev->net->hport, 1090818a04a0SAlexandre Bounine rdev->rswitch->destid, 1091818a04a0SAlexandre Bounine rdev->rswitch->hopcount); 1092818a04a0SAlexandre Bounine } 1093eb188d0eSMatt Porter } 1094eb188d0eSMatt Porter 1095eb188d0eSMatt Porter /** 1096eb188d0eSMatt Porter * rio_enum_timeout- Signal that enumeration timed out 1097eb188d0eSMatt Porter * @data: Address of timeout flag. 1098eb188d0eSMatt Porter * 1099eb188d0eSMatt Porter * When the enumeration complete timer expires, set a flag that 1100eb188d0eSMatt Porter * signals to the discovery process that enumeration did not 1101eb188d0eSMatt Porter * complete in a sane amount of time. 1102eb188d0eSMatt Porter */ 1103eb188d0eSMatt Porter static void rio_enum_timeout(unsigned long data) 1104eb188d0eSMatt Porter { 1105eb188d0eSMatt Porter /* Enumeration timed out, set flag */ 1106eb188d0eSMatt Porter *(int *)data = 1; 1107eb188d0eSMatt Porter } 1108eb188d0eSMatt Porter 1109eb188d0eSMatt Porter /** 1110eb188d0eSMatt Porter * rio_disc_mport- Start discovery through a master port 1111eb188d0eSMatt Porter * @mport: Master port to send transactions 1112eb188d0eSMatt Porter * 1113eb188d0eSMatt Porter * Starts the discovery process. If we have an active link, 1114eb188d0eSMatt Porter * then wait for the signal that enumeration is complete. 1115eb188d0eSMatt Porter * When enumeration completion is signaled, start recursive 1116eb188d0eSMatt Porter * peer discovery. Returns %0 if discovery succeeds or %-EBUSY 1117eb188d0eSMatt Porter * on failure. 1118eb188d0eSMatt Porter */ 111937d33d15SAl Viro int __devinit rio_disc_mport(struct rio_mport *mport) 1120eb188d0eSMatt Porter { 1121eb188d0eSMatt Porter struct rio_net *net = NULL; 1122eb188d0eSMatt Porter int enum_timeout_flag = 0; 1123eb188d0eSMatt Porter 1124eb188d0eSMatt Porter printk(KERN_INFO "RIO: discover master port %d, %s\n", mport->id, 1125eb188d0eSMatt Porter mport->name); 1126eb188d0eSMatt Porter 1127eb188d0eSMatt Porter /* If master port has an active link, allocate net and discover peers */ 1128eb188d0eSMatt Porter if (rio_mport_is_active(mport)) { 1129eb188d0eSMatt Porter if (!(net = rio_alloc_net(mport))) { 1130eb188d0eSMatt Porter printk(KERN_ERR "RIO: Failed to allocate new net\n"); 1131eb188d0eSMatt Porter goto bail; 1132eb188d0eSMatt Porter } 1133eb188d0eSMatt Porter 1134eb188d0eSMatt Porter pr_debug("RIO: wait for enumeration complete..."); 1135eb188d0eSMatt Porter 1136eb188d0eSMatt Porter rio_enum_timer.expires = 1137eb188d0eSMatt Porter jiffies + CONFIG_RAPIDIO_DISC_TIMEOUT * HZ; 1138eb188d0eSMatt Porter rio_enum_timer.data = (unsigned long)&enum_timeout_flag; 1139eb188d0eSMatt Porter add_timer(&rio_enum_timer); 1140eb188d0eSMatt Porter while (!rio_enum_complete(mport)) { 1141eb188d0eSMatt Porter mdelay(1); 1142eb188d0eSMatt Porter if (enum_timeout_flag) { 1143eb188d0eSMatt Porter del_timer_sync(&rio_enum_timer); 1144eb188d0eSMatt Porter goto timeout; 1145eb188d0eSMatt Porter } 1146eb188d0eSMatt Porter } 1147eb188d0eSMatt Porter del_timer_sync(&rio_enum_timer); 1148eb188d0eSMatt Porter 1149eb188d0eSMatt Porter pr_debug("done\n"); 1150818a04a0SAlexandre Bounine 1151818a04a0SAlexandre Bounine /* Read DestID assigned by enumerator */ 1152818a04a0SAlexandre Bounine rio_local_read_config_32(mport, RIO_DID_CSR, 1153818a04a0SAlexandre Bounine &mport->host_deviceid); 1154818a04a0SAlexandre Bounine mport->host_deviceid = RIO_GET_DID(mport->sys_size, 1155818a04a0SAlexandre Bounine mport->host_deviceid); 1156818a04a0SAlexandre Bounine 1157e0423236SZhang Wei if (rio_disc_peer(net, mport, RIO_ANY_DESTID(mport->sys_size), 1158e0423236SZhang Wei 0) < 0) { 1159eb188d0eSMatt Porter printk(KERN_INFO 1160eb188d0eSMatt Porter "RIO: master port %d device has failed discovery\n", 1161eb188d0eSMatt Porter mport->id); 1162eb188d0eSMatt Porter goto bail; 1163eb188d0eSMatt Porter } 1164eb188d0eSMatt Porter 1165eb188d0eSMatt Porter rio_build_route_tables(); 1166eb188d0eSMatt Porter } 1167eb188d0eSMatt Porter 1168eb188d0eSMatt Porter return 0; 1169eb188d0eSMatt Porter 1170eb188d0eSMatt Porter timeout: 1171eb188d0eSMatt Porter pr_debug("timeout\n"); 1172eb188d0eSMatt Porter bail: 1173eb188d0eSMatt Porter return -EBUSY; 1174eb188d0eSMatt Porter } 1175