1394b701cSMatt Porter /* 2394b701cSMatt Porter * RapidIO interconnect services 3394b701cSMatt Porter * (RapidIO Interconnect Specification, http://www.rapidio.org) 4394b701cSMatt Porter * 5394b701cSMatt Porter * Copyright 2005 MontaVista Software, Inc. 6394b701cSMatt Porter * Matt Porter <mporter@kernel.crashing.org> 7394b701cSMatt Porter * 8394b701cSMatt Porter * This program is free software; you can redistribute it and/or modify it 9394b701cSMatt Porter * under the terms of the GNU General Public License as published by the 10394b701cSMatt Porter * Free Software Foundation; either version 2 of the License, or (at your 11394b701cSMatt Porter * option) any later version. 12394b701cSMatt Porter */ 13394b701cSMatt Porter 14394b701cSMatt Porter #include <linux/types.h> 15394b701cSMatt Porter #include <linux/kernel.h> 16394b701cSMatt Porter 17394b701cSMatt Porter #include <linux/delay.h> 18394b701cSMatt Porter #include <linux/init.h> 19394b701cSMatt Porter #include <linux/rio.h> 20394b701cSMatt Porter #include <linux/rio_drv.h> 21394b701cSMatt Porter #include <linux/rio_ids.h> 22394b701cSMatt Porter #include <linux/rio_regs.h> 23394b701cSMatt Porter #include <linux/module.h> 24394b701cSMatt Porter #include <linux/spinlock.h> 25de25968cSTim Schmielau #include <linux/slab.h> 265febf1cdSKumar Gala #include <linux/interrupt.h> 27394b701cSMatt Porter 28394b701cSMatt Porter #include "rio.h" 29394b701cSMatt Porter 30394b701cSMatt Porter static LIST_HEAD(rio_mports); 31394b701cSMatt Porter 32394b701cSMatt Porter /** 33394b701cSMatt Porter * rio_local_get_device_id - Get the base/extended device id for a port 34394b701cSMatt Porter * @port: RIO master port from which to get the deviceid 35394b701cSMatt Porter * 36394b701cSMatt Porter * Reads the base/extended device id from the local device 37394b701cSMatt Porter * implementing the master port. Returns the 8/16-bit device 38394b701cSMatt Porter * id. 39394b701cSMatt Porter */ 40394b701cSMatt Porter u16 rio_local_get_device_id(struct rio_mport *port) 41394b701cSMatt Porter { 42394b701cSMatt Porter u32 result; 43394b701cSMatt Porter 44394b701cSMatt Porter rio_local_read_config_32(port, RIO_DID_CSR, &result); 45394b701cSMatt Porter 46e0423236SZhang Wei return (RIO_GET_DID(port->sys_size, result)); 47394b701cSMatt Porter } 48394b701cSMatt Porter 49394b701cSMatt Porter /** 50394b701cSMatt Porter * rio_request_inb_mbox - request inbound mailbox service 51394b701cSMatt Porter * @mport: RIO master port from which to allocate the mailbox resource 526978bbc0SMatt Porter * @dev_id: Device specific pointer to pass on event 53394b701cSMatt Porter * @mbox: Mailbox number to claim 54394b701cSMatt Porter * @entries: Number of entries in inbound mailbox queue 55394b701cSMatt Porter * @minb: Callback to execute when inbound message is received 56394b701cSMatt Porter * 57394b701cSMatt Porter * Requests ownership of an inbound mailbox resource and binds 58394b701cSMatt Porter * a callback function to the resource. Returns %0 on success. 59394b701cSMatt Porter */ 60394b701cSMatt Porter int rio_request_inb_mbox(struct rio_mport *mport, 616978bbc0SMatt Porter void *dev_id, 62394b701cSMatt Porter int mbox, 63394b701cSMatt Porter int entries, 646978bbc0SMatt Porter void (*minb) (struct rio_mport * mport, void *dev_id, int mbox, 65394b701cSMatt Porter int slot)) 66394b701cSMatt Porter { 67394b701cSMatt Porter int rc = 0; 68394b701cSMatt Porter 69394b701cSMatt Porter struct resource *res = kmalloc(sizeof(struct resource), GFP_KERNEL); 70394b701cSMatt Porter 71394b701cSMatt Porter if (res) { 72394b701cSMatt Porter rio_init_mbox_res(res, mbox, mbox); 73394b701cSMatt Porter 74394b701cSMatt Porter /* Make sure this mailbox isn't in use */ 75394b701cSMatt Porter if ((rc = 76394b701cSMatt Porter request_resource(&mport->riores[RIO_INB_MBOX_RESOURCE], 77394b701cSMatt Porter res)) < 0) { 78394b701cSMatt Porter kfree(res); 79394b701cSMatt Porter goto out; 80394b701cSMatt Porter } 81394b701cSMatt Porter 82394b701cSMatt Porter mport->inb_msg[mbox].res = res; 83394b701cSMatt Porter 84394b701cSMatt Porter /* Hook the inbound message callback */ 85394b701cSMatt Porter mport->inb_msg[mbox].mcback = minb; 86394b701cSMatt Porter 876978bbc0SMatt Porter rc = rio_open_inb_mbox(mport, dev_id, mbox, entries); 88394b701cSMatt Porter } else 89394b701cSMatt Porter rc = -ENOMEM; 90394b701cSMatt Porter 91394b701cSMatt Porter out: 92394b701cSMatt Porter return rc; 93394b701cSMatt Porter } 94394b701cSMatt Porter 95394b701cSMatt Porter /** 96394b701cSMatt Porter * rio_release_inb_mbox - release inbound mailbox message service 97394b701cSMatt Porter * @mport: RIO master port from which to release the mailbox resource 98394b701cSMatt Porter * @mbox: Mailbox number to release 99394b701cSMatt Porter * 100394b701cSMatt Porter * Releases ownership of an inbound mailbox resource. Returns 0 101394b701cSMatt Porter * if the request has been satisfied. 102394b701cSMatt Porter */ 103394b701cSMatt Porter int rio_release_inb_mbox(struct rio_mport *mport, int mbox) 104394b701cSMatt Porter { 105394b701cSMatt Porter rio_close_inb_mbox(mport, mbox); 106394b701cSMatt Porter 107394b701cSMatt Porter /* Release the mailbox resource */ 108394b701cSMatt Porter return release_resource(mport->inb_msg[mbox].res); 109394b701cSMatt Porter } 110394b701cSMatt Porter 111394b701cSMatt Porter /** 112394b701cSMatt Porter * rio_request_outb_mbox - request outbound mailbox service 113394b701cSMatt Porter * @mport: RIO master port from which to allocate the mailbox resource 1146978bbc0SMatt Porter * @dev_id: Device specific pointer to pass on event 115394b701cSMatt Porter * @mbox: Mailbox number to claim 116394b701cSMatt Porter * @entries: Number of entries in outbound mailbox queue 117394b701cSMatt Porter * @moutb: Callback to execute when outbound message is sent 118394b701cSMatt Porter * 119394b701cSMatt Porter * Requests ownership of an outbound mailbox resource and binds 120394b701cSMatt Porter * a callback function to the resource. Returns 0 on success. 121394b701cSMatt Porter */ 122394b701cSMatt Porter int rio_request_outb_mbox(struct rio_mport *mport, 1236978bbc0SMatt Porter void *dev_id, 124394b701cSMatt Porter int mbox, 125394b701cSMatt Porter int entries, 1266978bbc0SMatt Porter void (*moutb) (struct rio_mport * mport, void *dev_id, int mbox, int slot)) 127394b701cSMatt Porter { 128394b701cSMatt Porter int rc = 0; 129394b701cSMatt Porter 130394b701cSMatt Porter struct resource *res = kmalloc(sizeof(struct resource), GFP_KERNEL); 131394b701cSMatt Porter 132394b701cSMatt Porter if (res) { 133394b701cSMatt Porter rio_init_mbox_res(res, mbox, mbox); 134394b701cSMatt Porter 135394b701cSMatt Porter /* Make sure this outbound mailbox isn't in use */ 136394b701cSMatt Porter if ((rc = 137394b701cSMatt Porter request_resource(&mport->riores[RIO_OUTB_MBOX_RESOURCE], 138394b701cSMatt Porter res)) < 0) { 139394b701cSMatt Porter kfree(res); 140394b701cSMatt Porter goto out; 141394b701cSMatt Porter } 142394b701cSMatt Porter 143394b701cSMatt Porter mport->outb_msg[mbox].res = res; 144394b701cSMatt Porter 145394b701cSMatt Porter /* Hook the inbound message callback */ 146394b701cSMatt Porter mport->outb_msg[mbox].mcback = moutb; 147394b701cSMatt Porter 1486978bbc0SMatt Porter rc = rio_open_outb_mbox(mport, dev_id, mbox, entries); 149394b701cSMatt Porter } else 150394b701cSMatt Porter rc = -ENOMEM; 151394b701cSMatt Porter 152394b701cSMatt Porter out: 153394b701cSMatt Porter return rc; 154394b701cSMatt Porter } 155394b701cSMatt Porter 156394b701cSMatt Porter /** 157394b701cSMatt Porter * rio_release_outb_mbox - release outbound mailbox message service 158394b701cSMatt Porter * @mport: RIO master port from which to release the mailbox resource 159394b701cSMatt Porter * @mbox: Mailbox number to release 160394b701cSMatt Porter * 161394b701cSMatt Porter * Releases ownership of an inbound mailbox resource. Returns 0 162394b701cSMatt Porter * if the request has been satisfied. 163394b701cSMatt Porter */ 164394b701cSMatt Porter int rio_release_outb_mbox(struct rio_mport *mport, int mbox) 165394b701cSMatt Porter { 166394b701cSMatt Porter rio_close_outb_mbox(mport, mbox); 167394b701cSMatt Porter 168394b701cSMatt Porter /* Release the mailbox resource */ 169394b701cSMatt Porter return release_resource(mport->outb_msg[mbox].res); 170394b701cSMatt Porter } 171394b701cSMatt Porter 172394b701cSMatt Porter /** 173394b701cSMatt Porter * rio_setup_inb_dbell - bind inbound doorbell callback 174394b701cSMatt Porter * @mport: RIO master port to bind the doorbell callback 1756978bbc0SMatt Porter * @dev_id: Device specific pointer to pass on event 176394b701cSMatt Porter * @res: Doorbell message resource 177394b701cSMatt Porter * @dinb: Callback to execute when doorbell is received 178394b701cSMatt Porter * 179394b701cSMatt Porter * Adds a doorbell resource/callback pair into a port's 180394b701cSMatt Porter * doorbell event list. Returns 0 if the request has been 181394b701cSMatt Porter * satisfied. 182394b701cSMatt Porter */ 183394b701cSMatt Porter static int 1846978bbc0SMatt Porter rio_setup_inb_dbell(struct rio_mport *mport, void *dev_id, struct resource *res, 1856978bbc0SMatt Porter void (*dinb) (struct rio_mport * mport, void *dev_id, u16 src, u16 dst, 186394b701cSMatt Porter u16 info)) 187394b701cSMatt Porter { 188394b701cSMatt Porter int rc = 0; 189394b701cSMatt Porter struct rio_dbell *dbell; 190394b701cSMatt Porter 191394b701cSMatt Porter if (!(dbell = kmalloc(sizeof(struct rio_dbell), GFP_KERNEL))) { 192394b701cSMatt Porter rc = -ENOMEM; 193394b701cSMatt Porter goto out; 194394b701cSMatt Porter } 195394b701cSMatt Porter 196394b701cSMatt Porter dbell->res = res; 197394b701cSMatt Porter dbell->dinb = dinb; 1986978bbc0SMatt Porter dbell->dev_id = dev_id; 199394b701cSMatt Porter 200394b701cSMatt Porter list_add_tail(&dbell->node, &mport->dbells); 201394b701cSMatt Porter 202394b701cSMatt Porter out: 203394b701cSMatt Porter return rc; 204394b701cSMatt Porter } 205394b701cSMatt Porter 206394b701cSMatt Porter /** 207394b701cSMatt Porter * rio_request_inb_dbell - request inbound doorbell message service 208394b701cSMatt Porter * @mport: RIO master port from which to allocate the doorbell resource 2096978bbc0SMatt Porter * @dev_id: Device specific pointer to pass on event 210394b701cSMatt Porter * @start: Doorbell info range start 211394b701cSMatt Porter * @end: Doorbell info range end 212394b701cSMatt Porter * @dinb: Callback to execute when doorbell is received 213394b701cSMatt Porter * 214394b701cSMatt Porter * Requests ownership of an inbound doorbell resource and binds 215394b701cSMatt Porter * a callback function to the resource. Returns 0 if the request 216394b701cSMatt Porter * has been satisfied. 217394b701cSMatt Porter */ 218394b701cSMatt Porter int rio_request_inb_dbell(struct rio_mport *mport, 2196978bbc0SMatt Porter void *dev_id, 220394b701cSMatt Porter u16 start, 221394b701cSMatt Porter u16 end, 2226978bbc0SMatt Porter void (*dinb) (struct rio_mport * mport, void *dev_id, u16 src, 223394b701cSMatt Porter u16 dst, u16 info)) 224394b701cSMatt Porter { 225394b701cSMatt Porter int rc = 0; 226394b701cSMatt Porter 227394b701cSMatt Porter struct resource *res = kmalloc(sizeof(struct resource), GFP_KERNEL); 228394b701cSMatt Porter 229394b701cSMatt Porter if (res) { 230394b701cSMatt Porter rio_init_dbell_res(res, start, end); 231394b701cSMatt Porter 232394b701cSMatt Porter /* Make sure these doorbells aren't in use */ 233394b701cSMatt Porter if ((rc = 234394b701cSMatt Porter request_resource(&mport->riores[RIO_DOORBELL_RESOURCE], 235394b701cSMatt Porter res)) < 0) { 236394b701cSMatt Porter kfree(res); 237394b701cSMatt Porter goto out; 238394b701cSMatt Porter } 239394b701cSMatt Porter 240394b701cSMatt Porter /* Hook the doorbell callback */ 2416978bbc0SMatt Porter rc = rio_setup_inb_dbell(mport, dev_id, res, dinb); 242394b701cSMatt Porter } else 243394b701cSMatt Porter rc = -ENOMEM; 244394b701cSMatt Porter 245394b701cSMatt Porter out: 246394b701cSMatt Porter return rc; 247394b701cSMatt Porter } 248394b701cSMatt Porter 249394b701cSMatt Porter /** 250394b701cSMatt Porter * rio_release_inb_dbell - release inbound doorbell message service 251394b701cSMatt Porter * @mport: RIO master port from which to release the doorbell resource 252394b701cSMatt Porter * @start: Doorbell info range start 253394b701cSMatt Porter * @end: Doorbell info range end 254394b701cSMatt Porter * 255394b701cSMatt Porter * Releases ownership of an inbound doorbell resource and removes 256394b701cSMatt Porter * callback from the doorbell event list. Returns 0 if the request 257394b701cSMatt Porter * has been satisfied. 258394b701cSMatt Porter */ 259394b701cSMatt Porter int rio_release_inb_dbell(struct rio_mport *mport, u16 start, u16 end) 260394b701cSMatt Porter { 261394b701cSMatt Porter int rc = 0, found = 0; 262394b701cSMatt Porter struct rio_dbell *dbell; 263394b701cSMatt Porter 264394b701cSMatt Porter list_for_each_entry(dbell, &mport->dbells, node) { 265394b701cSMatt Porter if ((dbell->res->start == start) && (dbell->res->end == end)) { 266394b701cSMatt Porter found = 1; 267394b701cSMatt Porter break; 268394b701cSMatt Porter } 269394b701cSMatt Porter } 270394b701cSMatt Porter 271394b701cSMatt Porter /* If we can't find an exact match, fail */ 272394b701cSMatt Porter if (!found) { 273394b701cSMatt Porter rc = -EINVAL; 274394b701cSMatt Porter goto out; 275394b701cSMatt Porter } 276394b701cSMatt Porter 277394b701cSMatt Porter /* Delete from list */ 278394b701cSMatt Porter list_del(&dbell->node); 279394b701cSMatt Porter 280394b701cSMatt Porter /* Release the doorbell resource */ 281394b701cSMatt Porter rc = release_resource(dbell->res); 282394b701cSMatt Porter 283394b701cSMatt Porter /* Free the doorbell event */ 284394b701cSMatt Porter kfree(dbell); 285394b701cSMatt Porter 286394b701cSMatt Porter out: 287394b701cSMatt Porter return rc; 288394b701cSMatt Porter } 289394b701cSMatt Porter 290394b701cSMatt Porter /** 291394b701cSMatt Porter * rio_request_outb_dbell - request outbound doorbell message range 292394b701cSMatt Porter * @rdev: RIO device from which to allocate the doorbell resource 293394b701cSMatt Porter * @start: Doorbell message range start 294394b701cSMatt Porter * @end: Doorbell message range end 295394b701cSMatt Porter * 296394b701cSMatt Porter * Requests ownership of a doorbell message range. Returns a resource 297394b701cSMatt Porter * if the request has been satisfied or %NULL on failure. 298394b701cSMatt Porter */ 299394b701cSMatt Porter struct resource *rio_request_outb_dbell(struct rio_dev *rdev, u16 start, 300394b701cSMatt Porter u16 end) 301394b701cSMatt Porter { 302394b701cSMatt Porter struct resource *res = kmalloc(sizeof(struct resource), GFP_KERNEL); 303394b701cSMatt Porter 304394b701cSMatt Porter if (res) { 305394b701cSMatt Porter rio_init_dbell_res(res, start, end); 306394b701cSMatt Porter 307394b701cSMatt Porter /* Make sure these doorbells aren't in use */ 308394b701cSMatt Porter if (request_resource(&rdev->riores[RIO_DOORBELL_RESOURCE], res) 309394b701cSMatt Porter < 0) { 310394b701cSMatt Porter kfree(res); 311394b701cSMatt Porter res = NULL; 312394b701cSMatt Porter } 313394b701cSMatt Porter } 314394b701cSMatt Porter 315394b701cSMatt Porter return res; 316394b701cSMatt Porter } 317394b701cSMatt Porter 318394b701cSMatt Porter /** 319394b701cSMatt Porter * rio_release_outb_dbell - release outbound doorbell message range 320394b701cSMatt Porter * @rdev: RIO device from which to release the doorbell resource 321394b701cSMatt Porter * @res: Doorbell resource to be freed 322394b701cSMatt Porter * 323394b701cSMatt Porter * Releases ownership of a doorbell message range. Returns 0 if the 324394b701cSMatt Porter * request has been satisfied. 325394b701cSMatt Porter */ 326394b701cSMatt Porter int rio_release_outb_dbell(struct rio_dev *rdev, struct resource *res) 327394b701cSMatt Porter { 328394b701cSMatt Porter int rc = release_resource(res); 329394b701cSMatt Porter 330394b701cSMatt Porter kfree(res); 331394b701cSMatt Porter 332394b701cSMatt Porter return rc; 333394b701cSMatt Porter } 334394b701cSMatt Porter 335394b701cSMatt Porter /** 336394b701cSMatt Porter * rio_mport_get_feature - query for devices' extended features 337394b701cSMatt Porter * @port: Master port to issue transaction 338394b701cSMatt Porter * @local: Indicate a local master port or remote device access 339394b701cSMatt Porter * @destid: Destination ID of the device 340394b701cSMatt Porter * @hopcount: Number of switch hops to the device 341394b701cSMatt Porter * @ftr: Extended feature code 342394b701cSMatt Porter * 343394b701cSMatt Porter * Tell if a device supports a given RapidIO capability. 344394b701cSMatt Porter * Returns the offset of the requested extended feature 345394b701cSMatt Porter * block within the device's RIO configuration space or 346394b701cSMatt Porter * 0 in case the device does not support it. Possible 347394b701cSMatt Porter * values for @ftr: 348394b701cSMatt Porter * 349394b701cSMatt Porter * %RIO_EFB_PAR_EP_ID LP/LVDS EP Devices 350394b701cSMatt Porter * 351394b701cSMatt Porter * %RIO_EFB_PAR_EP_REC_ID LP/LVDS EP Recovery Devices 352394b701cSMatt Porter * 353394b701cSMatt Porter * %RIO_EFB_PAR_EP_FREE_ID LP/LVDS EP Free Devices 354394b701cSMatt Porter * 355394b701cSMatt Porter * %RIO_EFB_SER_EP_ID LP/Serial EP Devices 356394b701cSMatt Porter * 357394b701cSMatt Porter * %RIO_EFB_SER_EP_REC_ID LP/Serial EP Recovery Devices 358394b701cSMatt Porter * 359394b701cSMatt Porter * %RIO_EFB_SER_EP_FREE_ID LP/Serial EP Free Devices 360394b701cSMatt Porter */ 361394b701cSMatt Porter u32 362394b701cSMatt Porter rio_mport_get_feature(struct rio_mport * port, int local, u16 destid, 363394b701cSMatt Porter u8 hopcount, int ftr) 364394b701cSMatt Porter { 365394b701cSMatt Porter u32 asm_info, ext_ftr_ptr, ftr_header; 366394b701cSMatt Porter 367394b701cSMatt Porter if (local) 368394b701cSMatt Porter rio_local_read_config_32(port, RIO_ASM_INFO_CAR, &asm_info); 369394b701cSMatt Porter else 370394b701cSMatt Porter rio_mport_read_config_32(port, destid, hopcount, 371394b701cSMatt Porter RIO_ASM_INFO_CAR, &asm_info); 372394b701cSMatt Porter 373394b701cSMatt Porter ext_ftr_ptr = asm_info & RIO_EXT_FTR_PTR_MASK; 374394b701cSMatt Porter 375394b701cSMatt Porter while (ext_ftr_ptr) { 376394b701cSMatt Porter if (local) 377394b701cSMatt Porter rio_local_read_config_32(port, ext_ftr_ptr, 378394b701cSMatt Porter &ftr_header); 379394b701cSMatt Porter else 380394b701cSMatt Porter rio_mport_read_config_32(port, destid, hopcount, 381394b701cSMatt Porter ext_ftr_ptr, &ftr_header); 382394b701cSMatt Porter if (RIO_GET_BLOCK_ID(ftr_header) == ftr) 383394b701cSMatt Porter return ext_ftr_ptr; 384394b701cSMatt Porter if (!(ext_ftr_ptr = RIO_GET_BLOCK_PTR(ftr_header))) 385394b701cSMatt Porter break; 386394b701cSMatt Porter } 387394b701cSMatt Porter 388394b701cSMatt Porter return 0; 389394b701cSMatt Porter } 390394b701cSMatt Porter 391394b701cSMatt Porter /** 392394b701cSMatt Porter * rio_get_asm - Begin or continue searching for a RIO device by vid/did/asm_vid/asm_did 393394b701cSMatt Porter * @vid: RIO vid to match or %RIO_ANY_ID to match all vids 394394b701cSMatt Porter * @did: RIO did to match or %RIO_ANY_ID to match all dids 395394b701cSMatt Porter * @asm_vid: RIO asm_vid to match or %RIO_ANY_ID to match all asm_vids 396394b701cSMatt Porter * @asm_did: RIO asm_did to match or %RIO_ANY_ID to match all asm_dids 397394b701cSMatt Porter * @from: Previous RIO device found in search, or %NULL for new search 398394b701cSMatt Porter * 399394b701cSMatt Porter * Iterates through the list of known RIO devices. If a RIO device is 400394b701cSMatt Porter * found with a matching @vid, @did, @asm_vid, @asm_did, the reference 401394b701cSMatt Porter * count to the device is incrememted and a pointer to its device 402394b701cSMatt Porter * structure is returned. Otherwise, %NULL is returned. A new search 403394b701cSMatt Porter * is initiated by passing %NULL to the @from argument. Otherwise, if 404394b701cSMatt Porter * @from is not %NULL, searches continue from next device on the global 405394b701cSMatt Porter * list. The reference count for @from is always decremented if it is 406394b701cSMatt Porter * not %NULL. 407394b701cSMatt Porter */ 408394b701cSMatt Porter struct rio_dev *rio_get_asm(u16 vid, u16 did, 409394b701cSMatt Porter u16 asm_vid, u16 asm_did, struct rio_dev *from) 410394b701cSMatt Porter { 411394b701cSMatt Porter struct list_head *n; 412394b701cSMatt Porter struct rio_dev *rdev; 413394b701cSMatt Porter 414394b701cSMatt Porter WARN_ON(in_interrupt()); 415394b701cSMatt Porter spin_lock(&rio_global_list_lock); 416394b701cSMatt Porter n = from ? from->global_list.next : rio_devices.next; 417394b701cSMatt Porter 418394b701cSMatt Porter while (n && (n != &rio_devices)) { 419394b701cSMatt Porter rdev = rio_dev_g(n); 420394b701cSMatt Porter if ((vid == RIO_ANY_ID || rdev->vid == vid) && 421394b701cSMatt Porter (did == RIO_ANY_ID || rdev->did == did) && 422394b701cSMatt Porter (asm_vid == RIO_ANY_ID || rdev->asm_vid == asm_vid) && 423394b701cSMatt Porter (asm_did == RIO_ANY_ID || rdev->asm_did == asm_did)) 424394b701cSMatt Porter goto exit; 425394b701cSMatt Porter n = n->next; 426394b701cSMatt Porter } 427394b701cSMatt Porter rdev = NULL; 428394b701cSMatt Porter exit: 429394b701cSMatt Porter rio_dev_put(from); 430394b701cSMatt Porter rdev = rio_dev_get(rdev); 431394b701cSMatt Porter spin_unlock(&rio_global_list_lock); 432394b701cSMatt Porter return rdev; 433394b701cSMatt Porter } 434394b701cSMatt Porter 435394b701cSMatt Porter /** 436394b701cSMatt Porter * rio_get_device - Begin or continue searching for a RIO device by vid/did 437394b701cSMatt Porter * @vid: RIO vid to match or %RIO_ANY_ID to match all vids 438394b701cSMatt Porter * @did: RIO did to match or %RIO_ANY_ID to match all dids 439394b701cSMatt Porter * @from: Previous RIO device found in search, or %NULL for new search 440394b701cSMatt Porter * 441394b701cSMatt Porter * Iterates through the list of known RIO devices. If a RIO device is 442394b701cSMatt Porter * found with a matching @vid and @did, the reference count to the 443394b701cSMatt Porter * device is incrememted and a pointer to its device structure is returned. 444394b701cSMatt Porter * Otherwise, %NULL is returned. A new search is initiated by passing %NULL 445394b701cSMatt Porter * to the @from argument. Otherwise, if @from is not %NULL, searches 446394b701cSMatt Porter * continue from next device on the global list. The reference count for 447394b701cSMatt Porter * @from is always decremented if it is not %NULL. 448394b701cSMatt Porter */ 449394b701cSMatt Porter struct rio_dev *rio_get_device(u16 vid, u16 did, struct rio_dev *from) 450394b701cSMatt Porter { 451394b701cSMatt Porter return rio_get_asm(vid, did, RIO_ANY_ID, RIO_ANY_ID, from); 452394b701cSMatt Porter } 453394b701cSMatt Porter 454394b701cSMatt Porter static void rio_fixup_device(struct rio_dev *dev) 455394b701cSMatt Porter { 456394b701cSMatt Porter } 457394b701cSMatt Porter 458394b701cSMatt Porter static int __devinit rio_init(void) 459394b701cSMatt Porter { 460394b701cSMatt Porter struct rio_dev *dev = NULL; 461394b701cSMatt Porter 462394b701cSMatt Porter while ((dev = rio_get_device(RIO_ANY_ID, RIO_ANY_ID, dev)) != NULL) { 463394b701cSMatt Porter rio_fixup_device(dev); 464394b701cSMatt Porter } 465394b701cSMatt Porter return 0; 466394b701cSMatt Porter } 467394b701cSMatt Porter 468394b701cSMatt Porter device_initcall(rio_init); 469394b701cSMatt Porter 47037d33d15SAl Viro int __devinit rio_init_mports(void) 471394b701cSMatt Porter { 472394b701cSMatt Porter int rc = 0; 473394b701cSMatt Porter struct rio_mport *port; 474394b701cSMatt Porter 475394b701cSMatt Porter list_for_each_entry(port, &rio_mports, node) { 476394b701cSMatt Porter if (!request_mem_region(port->iores.start, 477394b701cSMatt Porter port->iores.end - port->iores.start, 478394b701cSMatt Porter port->name)) { 479394b701cSMatt Porter printk(KERN_ERR 4805febf1cdSKumar Gala "RIO: Error requesting master port region 0x%016llx-0x%016llx\n", 4815febf1cdSKumar Gala (u64)port->iores.start, (u64)port->iores.end - 1); 482394b701cSMatt Porter rc = -ENOMEM; 483394b701cSMatt Porter goto out; 484394b701cSMatt Porter } 485394b701cSMatt Porter 486394b701cSMatt Porter if (port->host_deviceid >= 0) 487394b701cSMatt Porter rio_enum_mport(port); 488394b701cSMatt Porter else 489394b701cSMatt Porter rio_disc_mport(port); 490394b701cSMatt Porter } 491394b701cSMatt Porter 492394b701cSMatt Porter out: 493394b701cSMatt Porter return rc; 494394b701cSMatt Porter } 495394b701cSMatt Porter 496394b701cSMatt Porter void rio_register_mport(struct rio_mport *port) 497394b701cSMatt Porter { 498394b701cSMatt Porter list_add_tail(&port->node, &rio_mports); 499394b701cSMatt Porter } 500394b701cSMatt Porter 501394b701cSMatt Porter EXPORT_SYMBOL_GPL(rio_local_get_device_id); 502394b701cSMatt Porter EXPORT_SYMBOL_GPL(rio_get_device); 503394b701cSMatt Porter EXPORT_SYMBOL_GPL(rio_get_asm); 504394b701cSMatt Porter EXPORT_SYMBOL_GPL(rio_request_inb_dbell); 505394b701cSMatt Porter EXPORT_SYMBOL_GPL(rio_release_inb_dbell); 506394b701cSMatt Porter EXPORT_SYMBOL_GPL(rio_request_outb_dbell); 507394b701cSMatt Porter EXPORT_SYMBOL_GPL(rio_release_outb_dbell); 508394b701cSMatt Porter EXPORT_SYMBOL_GPL(rio_request_inb_mbox); 509394b701cSMatt Porter EXPORT_SYMBOL_GPL(rio_release_inb_mbox); 510394b701cSMatt Porter EXPORT_SYMBOL_GPL(rio_request_outb_mbox); 511394b701cSMatt Porter EXPORT_SYMBOL_GPL(rio_release_outb_mbox); 512