^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-or-later
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * RapidIO interconnect services
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * (RapidIO Interconnect Specification, http://www.rapidio.org)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * Copyright 2005 MontaVista Software, Inc.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * Matt Porter <mporter@kernel.crashing.org>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * Copyright 2009 - 2013 Integrated Device Technology, Inc.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) * Alex Bounine <alexandre.bounine@idt.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/types.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/delay.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <linux/rio.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <linux/rio_drv.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <linux/rio_ids.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include <linux/rio_regs.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include <linux/spinlock.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #include <linux/interrupt.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #include "rio.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) * struct rio_pwrite - RIO portwrite event
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) * @node: Node in list of doorbell events
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) * @pwcback: Doorbell event callback
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) * @context: Handler specific context to pass on event
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) struct rio_pwrite {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) struct list_head node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) int (*pwcback)(struct rio_mport *mport, void *context,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) union rio_pw_msg *msg, int step);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) void *context;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) MODULE_DESCRIPTION("RapidIO Subsystem Core");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) MODULE_AUTHOR("Matt Porter <mporter@kernel.crashing.org>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) MODULE_AUTHOR("Alexandre Bounine <alexandre.bounine@idt.com>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) MODULE_LICENSE("GPL");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) static int hdid[RIO_MAX_MPORTS];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) static int ids_num;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) module_param_array(hdid, int, &ids_num, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) MODULE_PARM_DESC(hdid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) "Destination ID assignment to local RapidIO controllers");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) static LIST_HEAD(rio_devices);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) static LIST_HEAD(rio_nets);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) static DEFINE_SPINLOCK(rio_global_list_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) static LIST_HEAD(rio_mports);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) static LIST_HEAD(rio_scans);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) static DEFINE_MUTEX(rio_mport_list_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) static unsigned char next_portid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) static DEFINE_SPINLOCK(rio_mmap_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) * rio_local_get_device_id - Get the base/extended device id for a port
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) * @port: RIO master port from which to get the deviceid
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) * Reads the base/extended device id from the local device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) * implementing the master port. Returns the 8/16-bit device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) * id.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) u16 rio_local_get_device_id(struct rio_mport *port)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) u32 result;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) rio_local_read_config_32(port, RIO_DID_CSR, &result);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) return (RIO_GET_DID(port->sys_size, result));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) EXPORT_SYMBOL_GPL(rio_local_get_device_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) * rio_query_mport - Query mport device attributes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) * @port: mport device to query
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) * @mport_attr: mport attributes data structure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) * Returns attributes of specified mport through the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) * pointer to attributes data structure.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) int rio_query_mport(struct rio_mport *port,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) struct rio_mport_attr *mport_attr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) if (!port->ops->query_mport)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) return -ENODATA;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) return port->ops->query_mport(port, mport_attr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) EXPORT_SYMBOL(rio_query_mport);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) * rio_alloc_net- Allocate and initialize a new RIO network data structure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) * @mport: Master port associated with the RIO network
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) * Allocates a RIO network structure, initializes per-network
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) * list heads, and adds the associated master port to the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) * network list of associated master ports. Returns a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) * RIO network pointer on success or %NULL on failure.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) struct rio_net *rio_alloc_net(struct rio_mport *mport)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) struct rio_net *net = kzalloc(sizeof(*net), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) if (net) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) INIT_LIST_HEAD(&net->node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) INIT_LIST_HEAD(&net->devices);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) INIT_LIST_HEAD(&net->switches);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) INIT_LIST_HEAD(&net->mports);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) mport->net = net;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) return net;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) EXPORT_SYMBOL_GPL(rio_alloc_net);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) int rio_add_net(struct rio_net *net)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) err = device_register(&net->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) spin_lock(&rio_global_list_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) list_add_tail(&net->node, &rio_nets);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) spin_unlock(&rio_global_list_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) EXPORT_SYMBOL_GPL(rio_add_net);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) void rio_free_net(struct rio_net *net)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) spin_lock(&rio_global_list_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) if (!list_empty(&net->node))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) list_del(&net->node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) spin_unlock(&rio_global_list_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) if (net->release)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) net->release(net);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) device_unregister(&net->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) EXPORT_SYMBOL_GPL(rio_free_net);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) * rio_local_set_device_id - Set the base/extended device id for a port
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) * @port: RIO master port
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) * @did: Device ID value to be written
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) * Writes the base/extended device id from a device.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) void rio_local_set_device_id(struct rio_mport *port, u16 did)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) rio_local_write_config_32(port, RIO_DID_CSR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) RIO_SET_DID(port->sys_size, did));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) EXPORT_SYMBOL_GPL(rio_local_set_device_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) * rio_add_device- Adds a RIO device to the device model
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) * @rdev: RIO device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) * Adds the RIO device to the global device list and adds the RIO
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) * device to the RIO device list. Creates the generic sysfs nodes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) * for an RIO device.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) int rio_add_device(struct rio_dev *rdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) atomic_set(&rdev->state, RIO_DEVICE_RUNNING);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) err = device_register(&rdev->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) spin_lock(&rio_global_list_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) list_add_tail(&rdev->global_list, &rio_devices);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) if (rdev->net) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) list_add_tail(&rdev->net_list, &rdev->net->devices);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) if (rdev->pef & RIO_PEF_SWITCH)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) list_add_tail(&rdev->rswitch->node,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) &rdev->net->switches);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) spin_unlock(&rio_global_list_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) EXPORT_SYMBOL_GPL(rio_add_device);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) * rio_del_device - removes a RIO device from the device model
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) * @rdev: RIO device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) * @state: device state to set during removal process
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) * Removes the RIO device to the kernel device list and subsystem's device list.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) * Clears sysfs entries for the removed device.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) void rio_del_device(struct rio_dev *rdev, enum rio_device_state state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) pr_debug("RIO: %s: removing %s\n", __func__, rio_name(rdev));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) atomic_set(&rdev->state, state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) spin_lock(&rio_global_list_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) list_del(&rdev->global_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) if (rdev->net) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) list_del(&rdev->net_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) if (rdev->pef & RIO_PEF_SWITCH) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) list_del(&rdev->rswitch->node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) kfree(rdev->rswitch->route_table);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) spin_unlock(&rio_global_list_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) device_unregister(&rdev->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) EXPORT_SYMBOL_GPL(rio_del_device);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) * rio_request_inb_mbox - request inbound mailbox service
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) * @mport: RIO master port from which to allocate the mailbox resource
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) * @dev_id: Device specific pointer to pass on event
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) * @mbox: Mailbox number to claim
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) * @entries: Number of entries in inbound mailbox queue
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) * @minb: Callback to execute when inbound message is received
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) * Requests ownership of an inbound mailbox resource and binds
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) * a callback function to the resource. Returns %0 on success.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) int rio_request_inb_mbox(struct rio_mport *mport,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) void *dev_id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) int mbox,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) int entries,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) void (*minb) (struct rio_mport * mport, void *dev_id, int mbox,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) int slot))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) int rc = -ENOSYS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) struct resource *res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) if (!mport->ops->open_inb_mbox)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) res = kzalloc(sizeof(*res), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) if (res) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) rio_init_mbox_res(res, mbox, mbox);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) /* Make sure this mailbox isn't in use */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) rc = request_resource(&mport->riores[RIO_INB_MBOX_RESOURCE],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) res);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) if (rc < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) kfree(res);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) mport->inb_msg[mbox].res = res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) /* Hook the inbound message callback */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) mport->inb_msg[mbox].mcback = minb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) rc = mport->ops->open_inb_mbox(mport, dev_id, mbox, entries);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) if (rc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) mport->inb_msg[mbox].mcback = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) mport->inb_msg[mbox].res = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) release_resource(res);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) kfree(res);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) rc = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) EXPORT_SYMBOL_GPL(rio_request_inb_mbox);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) * rio_release_inb_mbox - release inbound mailbox message service
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) * @mport: RIO master port from which to release the mailbox resource
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) * @mbox: Mailbox number to release
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) * Releases ownership of an inbound mailbox resource. Returns 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) * if the request has been satisfied.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) int rio_release_inb_mbox(struct rio_mport *mport, int mbox)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) if (!mport->ops->close_inb_mbox || !mport->inb_msg[mbox].res)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) mport->ops->close_inb_mbox(mport, mbox);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) mport->inb_msg[mbox].mcback = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) rc = release_resource(mport->inb_msg[mbox].res);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) kfree(mport->inb_msg[mbox].res);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) mport->inb_msg[mbox].res = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) EXPORT_SYMBOL_GPL(rio_release_inb_mbox);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) * rio_request_outb_mbox - request outbound mailbox service
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) * @mport: RIO master port from which to allocate the mailbox resource
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) * @dev_id: Device specific pointer to pass on event
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) * @mbox: Mailbox number to claim
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) * @entries: Number of entries in outbound mailbox queue
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) * @moutb: Callback to execute when outbound message is sent
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) * Requests ownership of an outbound mailbox resource and binds
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) * a callback function to the resource. Returns 0 on success.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) int rio_request_outb_mbox(struct rio_mport *mport,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) void *dev_id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) int mbox,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) int entries,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) void (*moutb) (struct rio_mport * mport, void *dev_id, int mbox, int slot))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) int rc = -ENOSYS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) struct resource *res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) if (!mport->ops->open_outb_mbox)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) res = kzalloc(sizeof(*res), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) if (res) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) rio_init_mbox_res(res, mbox, mbox);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) /* Make sure this outbound mailbox isn't in use */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) rc = request_resource(&mport->riores[RIO_OUTB_MBOX_RESOURCE],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) res);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) if (rc < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) kfree(res);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) mport->outb_msg[mbox].res = res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) /* Hook the inbound message callback */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) mport->outb_msg[mbox].mcback = moutb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) rc = mport->ops->open_outb_mbox(mport, dev_id, mbox, entries);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) if (rc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) mport->outb_msg[mbox].mcback = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) mport->outb_msg[mbox].res = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) release_resource(res);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) kfree(res);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) rc = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) EXPORT_SYMBOL_GPL(rio_request_outb_mbox);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) * rio_release_outb_mbox - release outbound mailbox message service
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) * @mport: RIO master port from which to release the mailbox resource
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) * @mbox: Mailbox number to release
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) * Releases ownership of an inbound mailbox resource. Returns 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) * if the request has been satisfied.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) int rio_release_outb_mbox(struct rio_mport *mport, int mbox)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) if (!mport->ops->close_outb_mbox || !mport->outb_msg[mbox].res)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) mport->ops->close_outb_mbox(mport, mbox);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) mport->outb_msg[mbox].mcback = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) rc = release_resource(mport->outb_msg[mbox].res);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) kfree(mport->outb_msg[mbox].res);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) mport->outb_msg[mbox].res = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) EXPORT_SYMBOL_GPL(rio_release_outb_mbox);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) * rio_setup_inb_dbell - bind inbound doorbell callback
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) * @mport: RIO master port to bind the doorbell callback
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) * @dev_id: Device specific pointer to pass on event
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) * @res: Doorbell message resource
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) * @dinb: Callback to execute when doorbell is received
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) * Adds a doorbell resource/callback pair into a port's
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) * doorbell event list. Returns 0 if the request has been
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) * satisfied.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) rio_setup_inb_dbell(struct rio_mport *mport, void *dev_id, struct resource *res,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) void (*dinb) (struct rio_mport * mport, void *dev_id, u16 src, u16 dst,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) u16 info))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) struct rio_dbell *dbell = kmalloc(sizeof(*dbell), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) if (!dbell)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) dbell->res = res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) dbell->dinb = dinb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) dbell->dev_id = dev_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) mutex_lock(&mport->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) list_add_tail(&dbell->node, &mport->dbells);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) mutex_unlock(&mport->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) * rio_request_inb_dbell - request inbound doorbell message service
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) * @mport: RIO master port from which to allocate the doorbell resource
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) * @dev_id: Device specific pointer to pass on event
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) * @start: Doorbell info range start
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) * @end: Doorbell info range end
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) * @dinb: Callback to execute when doorbell is received
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) * Requests ownership of an inbound doorbell resource and binds
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) * a callback function to the resource. Returns 0 if the request
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) * has been satisfied.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) int rio_request_inb_dbell(struct rio_mport *mport,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) void *dev_id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) u16 start,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) u16 end,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) void (*dinb) (struct rio_mport * mport, void *dev_id, u16 src,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) u16 dst, u16 info))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) struct resource *res = kzalloc(sizeof(*res), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) if (res) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) rio_init_dbell_res(res, start, end);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) /* Make sure these doorbells aren't in use */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) rc = request_resource(&mport->riores[RIO_DOORBELL_RESOURCE],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) res);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) if (rc < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) kfree(res);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) /* Hook the doorbell callback */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) rc = rio_setup_inb_dbell(mport, dev_id, res, dinb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) rc = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) EXPORT_SYMBOL_GPL(rio_request_inb_dbell);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) * rio_release_inb_dbell - release inbound doorbell message service
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) * @mport: RIO master port from which to release the doorbell resource
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) * @start: Doorbell info range start
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) * @end: Doorbell info range end
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) * Releases ownership of an inbound doorbell resource and removes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) * callback from the doorbell event list. Returns 0 if the request
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) * has been satisfied.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) int rio_release_inb_dbell(struct rio_mport *mport, u16 start, u16 end)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) int rc = 0, found = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) struct rio_dbell *dbell;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) mutex_lock(&mport->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) list_for_each_entry(dbell, &mport->dbells, node) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) if ((dbell->res->start == start) && (dbell->res->end == end)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) list_del(&dbell->node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) found = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) mutex_unlock(&mport->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) /* If we can't find an exact match, fail */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) if (!found) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) rc = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) /* Release the doorbell resource */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) rc = release_resource(dbell->res);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) /* Free the doorbell event */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) kfree(dbell);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) EXPORT_SYMBOL_GPL(rio_release_inb_dbell);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) * rio_request_outb_dbell - request outbound doorbell message range
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) * @rdev: RIO device from which to allocate the doorbell resource
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) * @start: Doorbell message range start
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) * @end: Doorbell message range end
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) * Requests ownership of a doorbell message range. Returns a resource
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) * if the request has been satisfied or %NULL on failure.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) struct resource *rio_request_outb_dbell(struct rio_dev *rdev, u16 start,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) u16 end)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) struct resource *res = kzalloc(sizeof(struct resource), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) if (res) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) rio_init_dbell_res(res, start, end);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) /* Make sure these doorbells aren't in use */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) if (request_resource(&rdev->riores[RIO_DOORBELL_RESOURCE], res)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) kfree(res);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) res = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) return res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) EXPORT_SYMBOL_GPL(rio_request_outb_dbell);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) * rio_release_outb_dbell - release outbound doorbell message range
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) * @rdev: RIO device from which to release the doorbell resource
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) * @res: Doorbell resource to be freed
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) * Releases ownership of a doorbell message range. Returns 0 if the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) * request has been satisfied.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) int rio_release_outb_dbell(struct rio_dev *rdev, struct resource *res)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) int rc = release_resource(res);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) kfree(res);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) EXPORT_SYMBOL_GPL(rio_release_outb_dbell);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) * rio_add_mport_pw_handler - add port-write message handler into the list
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) * of mport specific pw handlers
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) * @mport: RIO master port to bind the portwrite callback
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) * @context: Handler specific context to pass on event
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) * @pwcback: Callback to execute when portwrite is received
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) * Returns 0 if the request has been satisfied.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) int rio_add_mport_pw_handler(struct rio_mport *mport, void *context,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) int (*pwcback)(struct rio_mport *mport,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) void *context, union rio_pw_msg *msg, int step))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) struct rio_pwrite *pwrite = kzalloc(sizeof(*pwrite), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) if (!pwrite)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) pwrite->pwcback = pwcback;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) pwrite->context = context;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) mutex_lock(&mport->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) list_add_tail(&pwrite->node, &mport->pwrites);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) mutex_unlock(&mport->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) EXPORT_SYMBOL_GPL(rio_add_mport_pw_handler);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) * rio_del_mport_pw_handler - remove port-write message handler from the list
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) * of mport specific pw handlers
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) * @mport: RIO master port to bind the portwrite callback
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) * @context: Registered handler specific context to pass on event
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) * @pwcback: Registered callback function
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) * Returns 0 if the request has been satisfied.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) int rio_del_mport_pw_handler(struct rio_mport *mport, void *context,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) int (*pwcback)(struct rio_mport *mport,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) void *context, union rio_pw_msg *msg, int step))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) int rc = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) struct rio_pwrite *pwrite;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) mutex_lock(&mport->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) list_for_each_entry(pwrite, &mport->pwrites, node) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) if (pwrite->pwcback == pwcback && pwrite->context == context) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) list_del(&pwrite->node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) kfree(pwrite);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) rc = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) mutex_unlock(&mport->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) EXPORT_SYMBOL_GPL(rio_del_mport_pw_handler);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) * rio_request_inb_pwrite - request inbound port-write message service for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) * specific RapidIO device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) * @rdev: RIO device to which register inbound port-write callback routine
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) * @pwcback: Callback routine to execute when port-write is received
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) * Binds a port-write callback function to the RapidIO device.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) * Returns 0 if the request has been satisfied.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) int rio_request_inb_pwrite(struct rio_dev *rdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) int (*pwcback)(struct rio_dev *rdev, union rio_pw_msg *msg, int step))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) int rc = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) spin_lock(&rio_global_list_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) if (rdev->pwcback)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) rc = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) rdev->pwcback = pwcback;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) spin_unlock(&rio_global_list_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) EXPORT_SYMBOL_GPL(rio_request_inb_pwrite);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) * rio_release_inb_pwrite - release inbound port-write message service
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) * associated with specific RapidIO device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) * @rdev: RIO device which registered for inbound port-write callback
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) * Removes callback from the rio_dev structure. Returns 0 if the request
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) * has been satisfied.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) int rio_release_inb_pwrite(struct rio_dev *rdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) int rc = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) spin_lock(&rio_global_list_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) if (rdev->pwcback) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) rdev->pwcback = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) rc = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) spin_unlock(&rio_global_list_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) EXPORT_SYMBOL_GPL(rio_release_inb_pwrite);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) * rio_pw_enable - Enables/disables port-write handling by a master port
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) * @mport: Master port associated with port-write handling
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) * @enable: 1=enable, 0=disable
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) void rio_pw_enable(struct rio_mport *mport, int enable)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) if (mport->ops->pwenable) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) mutex_lock(&mport->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) if ((enable && ++mport->pwe_refcnt == 1) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) (!enable && mport->pwe_refcnt && --mport->pwe_refcnt == 0))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) mport->ops->pwenable(mport, enable);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) mutex_unlock(&mport->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) EXPORT_SYMBOL_GPL(rio_pw_enable);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) * rio_map_inb_region -- Map inbound memory region.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) * @mport: Master port.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) * @local: physical address of memory region to be mapped
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) * @rbase: RIO base address assigned to this window
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) * @size: Size of the memory region
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) * @rflags: Flags for mapping.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) * Return: 0 -- Success.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) * This function will create the mapping from RIO space to local memory.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) int rio_map_inb_region(struct rio_mport *mport, dma_addr_t local,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) u64 rbase, u32 size, u32 rflags)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) if (!mport->ops->map_inb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) spin_lock_irqsave(&rio_mmap_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) rc = mport->ops->map_inb(mport, local, rbase, size, rflags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) spin_unlock_irqrestore(&rio_mmap_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) EXPORT_SYMBOL_GPL(rio_map_inb_region);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) * rio_unmap_inb_region -- Unmap the inbound memory region
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) * @mport: Master port
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) * @lstart: physical address of memory region to be unmapped
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) void rio_unmap_inb_region(struct rio_mport *mport, dma_addr_t lstart)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) if (!mport->ops->unmap_inb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) spin_lock_irqsave(&rio_mmap_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) mport->ops->unmap_inb(mport, lstart);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) spin_unlock_irqrestore(&rio_mmap_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) EXPORT_SYMBOL_GPL(rio_unmap_inb_region);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) * rio_map_outb_region -- Map outbound memory region.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) * @mport: Master port.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) * @destid: destination id window points to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) * @rbase: RIO base address window translates to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) * @size: Size of the memory region
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) * @rflags: Flags for mapping.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) * @local: physical address of memory region mapped
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) * Return: 0 -- Success.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) * This function will create the mapping from RIO space to local memory.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) int rio_map_outb_region(struct rio_mport *mport, u16 destid, u64 rbase,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) u32 size, u32 rflags, dma_addr_t *local)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) if (!mport->ops->map_outb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) spin_lock_irqsave(&rio_mmap_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) rc = mport->ops->map_outb(mport, destid, rbase, size,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) rflags, local);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) spin_unlock_irqrestore(&rio_mmap_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) EXPORT_SYMBOL_GPL(rio_map_outb_region);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) * rio_unmap_inb_region -- Unmap the inbound memory region
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) * @mport: Master port
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) * @destid: destination id mapping points to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) * @rstart: RIO base address window translates to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) void rio_unmap_outb_region(struct rio_mport *mport, u16 destid, u64 rstart)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) if (!mport->ops->unmap_outb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) spin_lock_irqsave(&rio_mmap_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) mport->ops->unmap_outb(mport, destid, rstart);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) spin_unlock_irqrestore(&rio_mmap_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) EXPORT_SYMBOL_GPL(rio_unmap_outb_region);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) * rio_mport_get_physefb - Helper function that returns register offset
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) * for Physical Layer Extended Features Block.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) * @port: Master port to issue transaction
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) * @local: Indicate a local master port or remote device access
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) * @destid: Destination ID of the device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) * @hopcount: Number of switch hops to the device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) * @rmap: pointer to location to store register map type info
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) u32
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) rio_mport_get_physefb(struct rio_mport *port, int local,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) u16 destid, u8 hopcount, u32 *rmap)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) u32 ext_ftr_ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) u32 ftr_header;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) ext_ftr_ptr = rio_mport_get_efb(port, local, destid, hopcount, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) while (ext_ftr_ptr) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) if (local)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) rio_local_read_config_32(port, ext_ftr_ptr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) &ftr_header);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) rio_mport_read_config_32(port, destid, hopcount,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) ext_ftr_ptr, &ftr_header);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) ftr_header = RIO_GET_BLOCK_ID(ftr_header);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) switch (ftr_header) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) case RIO_EFB_SER_EP_ID:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) case RIO_EFB_SER_EP_REC_ID:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) case RIO_EFB_SER_EP_FREE_ID:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) case RIO_EFB_SER_EP_M1_ID:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) case RIO_EFB_SER_EP_SW_M1_ID:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) case RIO_EFB_SER_EPF_M1_ID:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) case RIO_EFB_SER_EPF_SW_M1_ID:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) *rmap = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) return ext_ftr_ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) case RIO_EFB_SER_EP_M2_ID:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) case RIO_EFB_SER_EP_SW_M2_ID:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) case RIO_EFB_SER_EPF_M2_ID:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) case RIO_EFB_SER_EPF_SW_M2_ID:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) *rmap = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) return ext_ftr_ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) ext_ftr_ptr = rio_mport_get_efb(port, local, destid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) hopcount, ext_ftr_ptr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) return ext_ftr_ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) EXPORT_SYMBOL_GPL(rio_mport_get_physefb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) * rio_get_comptag - Begin or continue searching for a RIO device by component tag
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) * @comp_tag: RIO component tag to match
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) * @from: Previous RIO device found in search, or %NULL for new search
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) * Iterates through the list of known RIO devices. If a RIO device is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) * found with a matching @comp_tag, a pointer to its device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) * structure is returned. Otherwise, %NULL is returned. A new search
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) * is initiated by passing %NULL to the @from argument. Otherwise, if
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) * @from is not %NULL, searches continue from next device on the global
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) * list.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) struct rio_dev *rio_get_comptag(u32 comp_tag, struct rio_dev *from)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) struct list_head *n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) struct rio_dev *rdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) spin_lock(&rio_global_list_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) n = from ? from->global_list.next : rio_devices.next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) while (n && (n != &rio_devices)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) rdev = rio_dev_g(n);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850) if (rdev->comp_tag == comp_tag)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) goto exit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) n = n->next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) rdev = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) exit:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856) spin_unlock(&rio_global_list_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) return rdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859) EXPORT_SYMBOL_GPL(rio_get_comptag);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862) * rio_set_port_lockout - Sets/clears LOCKOUT bit (RIO EM 1.3) for a switch port.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863) * @rdev: Pointer to RIO device control structure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) * @pnum: Switch port number to set LOCKOUT bit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865) * @lock: Operation : set (=1) or clear (=0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867) int rio_set_port_lockout(struct rio_dev *rdev, u32 pnum, int lock)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869) u32 regval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871) rio_read_config_32(rdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872) RIO_DEV_PORT_N_CTL_CSR(rdev, pnum),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) ®val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874) if (lock)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875) regval |= RIO_PORT_N_CTL_LOCKOUT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877) regval &= ~RIO_PORT_N_CTL_LOCKOUT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) rio_write_config_32(rdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880) RIO_DEV_PORT_N_CTL_CSR(rdev, pnum),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881) regval);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884) EXPORT_SYMBOL_GPL(rio_set_port_lockout);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887) * rio_enable_rx_tx_port - enable input receiver and output transmitter of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888) * given port
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889) * @port: Master port associated with the RIO network
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890) * @local: local=1 select local port otherwise a far device is reached
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891) * @destid: Destination ID of the device to check host bit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892) * @hopcount: Number of hops to reach the target
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893) * @port_num: Port (-number on switch) to enable on a far end device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895) * Returns 0 or 1 from on General Control Command and Status Register
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896) * (EXT_PTR+0x3C)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898) int rio_enable_rx_tx_port(struct rio_mport *port,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899) int local, u16 destid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900) u8 hopcount, u8 port_num)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902) #ifdef CONFIG_RAPIDIO_ENABLE_RX_TX_PORTS
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903) u32 regval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904) u32 ext_ftr_ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905) u32 rmap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908) * enable rx input tx output port
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910) pr_debug("rio_enable_rx_tx_port(local = %d, destid = %d, hopcount = "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911) "%d, port_num = %d)\n", local, destid, hopcount, port_num);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913) ext_ftr_ptr = rio_mport_get_physefb(port, local, destid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914) hopcount, &rmap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916) if (local) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917) rio_local_read_config_32(port,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918) ext_ftr_ptr + RIO_PORT_N_CTL_CSR(0, rmap),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919) ®val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921) if (rio_mport_read_config_32(port, destid, hopcount,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922) ext_ftr_ptr + RIO_PORT_N_CTL_CSR(port_num, rmap),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923) ®val) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927) regval = regval | RIO_PORT_N_CTL_EN_RX | RIO_PORT_N_CTL_EN_TX;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929) if (local) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930) rio_local_write_config_32(port,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931) ext_ftr_ptr + RIO_PORT_N_CTL_CSR(0, rmap), regval);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933) if (rio_mport_write_config_32(port, destid, hopcount,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934) ext_ftr_ptr + RIO_PORT_N_CTL_CSR(port_num, rmap),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935) regval) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941) EXPORT_SYMBOL_GPL(rio_enable_rx_tx_port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945) * rio_chk_dev_route - Validate route to the specified device.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946) * @rdev: RIO device failed to respond
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947) * @nrdev: Last active device on the route to rdev
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948) * @npnum: nrdev's port number on the route to rdev
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950) * Follows a route to the specified RIO device to determine the last available
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951) * device (and corresponding RIO port) on the route.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 954) rio_chk_dev_route(struct rio_dev *rdev, struct rio_dev **nrdev, int *npnum)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 955) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 956) u32 result;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 957) int p_port, rc = -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 958) struct rio_dev *prev = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 959)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 960) /* Find switch with failed RIO link */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 961) while (rdev->prev && (rdev->prev->pef & RIO_PEF_SWITCH)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 962) if (!rio_read_config_32(rdev->prev, RIO_DEV_ID_CAR, &result)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 963) prev = rdev->prev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 964) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 965) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 966) rdev = rdev->prev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 967) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 968)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 969) if (!prev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 970) goto err_out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 971)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 972) p_port = prev->rswitch->route_table[rdev->destid];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 973)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 974) if (p_port != RIO_INVALID_ROUTE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 975) pr_debug("RIO: link failed on [%s]-P%d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 976) rio_name(prev), p_port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 977) *nrdev = prev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 978) *npnum = p_port;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 979) rc = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 980) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 981) pr_debug("RIO: failed to trace route to %s\n", rio_name(rdev));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 982) err_out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 983) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 984) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 985)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 986) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 987) * rio_mport_chk_dev_access - Validate access to the specified device.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 988) * @mport: Master port to send transactions
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 989) * @destid: Device destination ID in network
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 990) * @hopcount: Number of hops into the network
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 991) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 992) int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 993) rio_mport_chk_dev_access(struct rio_mport *mport, u16 destid, u8 hopcount)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 994) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 995) int i = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 996) u32 tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 997)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 998) while (rio_mport_read_config_32(mport, destid, hopcount,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 999) RIO_DEV_ID_CAR, &tmp)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000) i++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001) if (i == RIO_MAX_CHK_RETRY)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003) mdelay(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008) EXPORT_SYMBOL_GPL(rio_mport_chk_dev_access);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011) * rio_chk_dev_access - Validate access to the specified device.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012) * @rdev: Pointer to RIO device control structure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014) static int rio_chk_dev_access(struct rio_dev *rdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016) return rio_mport_chk_dev_access(rdev->net->hport,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017) rdev->destid, rdev->hopcount);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021) * rio_get_input_status - Sends a Link-Request/Input-Status control symbol and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022) * returns link-response (if requested).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023) * @rdev: RIO devive to issue Input-status command
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024) * @pnum: Device port number to issue the command
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025) * @lnkresp: Response from a link partner
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028) rio_get_input_status(struct rio_dev *rdev, int pnum, u32 *lnkresp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030) u32 regval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031) int checkcount;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033) if (lnkresp) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034) /* Read from link maintenance response register
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035) * to clear valid bit */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036) rio_read_config_32(rdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037) RIO_DEV_PORT_N_MNT_RSP_CSR(rdev, pnum),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038) ®val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039) udelay(50);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042) /* Issue Input-status command */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043) rio_write_config_32(rdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044) RIO_DEV_PORT_N_MNT_REQ_CSR(rdev, pnum),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045) RIO_MNT_REQ_CMD_IS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047) /* Exit if the response is not expected */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048) if (!lnkresp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051) checkcount = 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052) while (checkcount--) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053) udelay(50);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1054) rio_read_config_32(rdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1055) RIO_DEV_PORT_N_MNT_RSP_CSR(rdev, pnum),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1056) ®val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1057) if (regval & RIO_PORT_N_MNT_RSP_RVAL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1058) *lnkresp = regval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1059) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1060) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1061) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1062)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1063) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1064) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1065)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1066) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1067) * rio_clr_err_stopped - Clears port Error-stopped states.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1068) * @rdev: Pointer to RIO device control structure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1069) * @pnum: Switch port number to clear errors
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1070) * @err_status: port error status (if 0 reads register from device)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1071) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1072) * TODO: Currently this routine is not compatible with recovery process
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1073) * specified for idt_gen3 RapidIO switch devices. It has to be reviewed
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1074) * to implement universal recovery process that is compatible full range
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1075) * off available devices.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1076) * IDT gen3 switch driver now implements HW-specific error handler that
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1077) * issues soft port reset to the port to reset ERR_STOP bits and ackIDs.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1078) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1079) static int rio_clr_err_stopped(struct rio_dev *rdev, u32 pnum, u32 err_status)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1080) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1081) struct rio_dev *nextdev = rdev->rswitch->nextdev[pnum];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1082) u32 regval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1083) u32 far_ackid, far_linkstat, near_ackid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1084)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1085) if (err_status == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1086) rio_read_config_32(rdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1087) RIO_DEV_PORT_N_ERR_STS_CSR(rdev, pnum),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1088) &err_status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1089)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1090) if (err_status & RIO_PORT_N_ERR_STS_OUT_ES) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1091) pr_debug("RIO_EM: servicing Output Error-Stopped state\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1092) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1093) * Send a Link-Request/Input-Status control symbol
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1094) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1095) if (rio_get_input_status(rdev, pnum, ®val)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1096) pr_debug("RIO_EM: Input-status response timeout\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1097) goto rd_err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1098) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1099)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1100) pr_debug("RIO_EM: SP%d Input-status response=0x%08x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1101) pnum, regval);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1102) far_ackid = (regval & RIO_PORT_N_MNT_RSP_ASTAT) >> 5;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1103) far_linkstat = regval & RIO_PORT_N_MNT_RSP_LSTAT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1104) rio_read_config_32(rdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1105) RIO_DEV_PORT_N_ACK_STS_CSR(rdev, pnum),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1106) ®val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1107) pr_debug("RIO_EM: SP%d_ACK_STS_CSR=0x%08x\n", pnum, regval);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1108) near_ackid = (regval & RIO_PORT_N_ACK_INBOUND) >> 24;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1109) pr_debug("RIO_EM: SP%d far_ackID=0x%02x far_linkstat=0x%02x" \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1110) " near_ackID=0x%02x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1111) pnum, far_ackid, far_linkstat, near_ackid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1112)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1113) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1114) * If required, synchronize ackIDs of near and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1115) * far sides.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1116) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1117) if ((far_ackid != ((regval & RIO_PORT_N_ACK_OUTSTAND) >> 8)) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1118) (far_ackid != (regval & RIO_PORT_N_ACK_OUTBOUND))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1119) /* Align near outstanding/outbound ackIDs with
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1120) * far inbound.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1121) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1122) rio_write_config_32(rdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1123) RIO_DEV_PORT_N_ACK_STS_CSR(rdev, pnum),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1124) (near_ackid << 24) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1125) (far_ackid << 8) | far_ackid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1126) /* Align far outstanding/outbound ackIDs with
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1127) * near inbound.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1128) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1129) far_ackid++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1130) if (!nextdev) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1131) pr_debug("RIO_EM: nextdev pointer == NULL\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1132) goto rd_err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1133) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1134)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1135) rio_write_config_32(nextdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1136) RIO_DEV_PORT_N_ACK_STS_CSR(nextdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1137) RIO_GET_PORT_NUM(nextdev->swpinfo)),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1138) (far_ackid << 24) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1139) (near_ackid << 8) | near_ackid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1140) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1141) rd_err:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1142) rio_read_config_32(rdev, RIO_DEV_PORT_N_ERR_STS_CSR(rdev, pnum),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1143) &err_status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1144) pr_debug("RIO_EM: SP%d_ERR_STS_CSR=0x%08x\n", pnum, err_status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1145) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1146)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1147) if ((err_status & RIO_PORT_N_ERR_STS_INP_ES) && nextdev) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1148) pr_debug("RIO_EM: servicing Input Error-Stopped state\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1149) rio_get_input_status(nextdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1150) RIO_GET_PORT_NUM(nextdev->swpinfo), NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1151) udelay(50);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1152)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1153) rio_read_config_32(rdev, RIO_DEV_PORT_N_ERR_STS_CSR(rdev, pnum),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1154) &err_status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1155) pr_debug("RIO_EM: SP%d_ERR_STS_CSR=0x%08x\n", pnum, err_status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1156) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1157)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1158) return (err_status & (RIO_PORT_N_ERR_STS_OUT_ES |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1159) RIO_PORT_N_ERR_STS_INP_ES)) ? 1 : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1160) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1161)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1162) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1163) * rio_inb_pwrite_handler - inbound port-write message handler
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1164) * @mport: mport device associated with port-write
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1165) * @pw_msg: pointer to inbound port-write message
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1166) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1167) * Processes an inbound port-write message. Returns 0 if the request
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1168) * has been satisfied.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1169) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1170) int rio_inb_pwrite_handler(struct rio_mport *mport, union rio_pw_msg *pw_msg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1171) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1172) struct rio_dev *rdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1173) u32 err_status, em_perrdet, em_ltlerrdet;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1174) int rc, portnum;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1175) struct rio_pwrite *pwrite;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1176)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1177) #ifdef DEBUG_PW
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1178) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1179) u32 i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1180)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1181) pr_debug("%s: PW to mport_%d:\n", __func__, mport->id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1182) for (i = 0; i < RIO_PW_MSG_SIZE / sizeof(u32); i = i + 4) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1183) pr_debug("0x%02x: %08x %08x %08x %08x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1184) i * 4, pw_msg->raw[i], pw_msg->raw[i + 1],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1185) pw_msg->raw[i + 2], pw_msg->raw[i + 3]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1186) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1187) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1188) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1189)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1190) rdev = rio_get_comptag((pw_msg->em.comptag & RIO_CTAG_UDEVID), NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1191) if (rdev) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1192) pr_debug("RIO: Port-Write message from %s\n", rio_name(rdev));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1193) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1194) pr_debug("RIO: %s No matching device for CTag 0x%08x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1195) __func__, pw_msg->em.comptag);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1196) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1197)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1198) /* Call a device-specific handler (if it is registered for the device).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1199) * This may be the service for endpoints that send device-specific
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1200) * port-write messages. End-point messages expected to be handled
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1201) * completely by EP specific device driver.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1202) * For switches rc==0 signals that no standard processing required.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1203) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1204) if (rdev && rdev->pwcback) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1205) rc = rdev->pwcback(rdev, pw_msg, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1206) if (rc == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1207) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1208) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1209)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1210) mutex_lock(&mport->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1211) list_for_each_entry(pwrite, &mport->pwrites, node)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1212) pwrite->pwcback(mport, pwrite->context, pw_msg, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1213) mutex_unlock(&mport->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1214)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1215) if (!rdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1216) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1217)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1218) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1219) * FIXME: The code below stays as it was before for now until we decide
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1220) * how to do default PW handling in combination with per-mport callbacks
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1221) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1222)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1223) portnum = pw_msg->em.is_port & 0xFF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1224)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1225) /* Check if device and route to it are functional:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1226) * Sometimes devices may send PW message(s) just before being
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1227) * powered down (or link being lost).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1228) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1229) if (rio_chk_dev_access(rdev)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1230) pr_debug("RIO: device access failed - get link partner\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1231) /* Scan route to the device and identify failed link.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1232) * This will replace device and port reported in PW message.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1233) * PW message should not be used after this point.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1234) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1235) if (rio_chk_dev_route(rdev, &rdev, &portnum)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1236) pr_err("RIO: Route trace for %s failed\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1237) rio_name(rdev));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1238) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1239) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1240) pw_msg = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1241) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1242)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1243) /* For End-point devices processing stops here */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1244) if (!(rdev->pef & RIO_PEF_SWITCH))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1245) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1246)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1247) if (rdev->phys_efptr == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1248) pr_err("RIO_PW: Bad switch initialization for %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1249) rio_name(rdev));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1250) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1251) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1252)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1253) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1254) * Process the port-write notification from switch
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1255) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1256) if (rdev->rswitch->ops && rdev->rswitch->ops->em_handle)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1257) rdev->rswitch->ops->em_handle(rdev, portnum);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1258)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1259) rio_read_config_32(rdev, RIO_DEV_PORT_N_ERR_STS_CSR(rdev, portnum),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1260) &err_status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1261) pr_debug("RIO_PW: SP%d_ERR_STS_CSR=0x%08x\n", portnum, err_status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1262)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1263) if (err_status & RIO_PORT_N_ERR_STS_PORT_OK) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1264)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1265) if (!(rdev->rswitch->port_ok & (1 << portnum))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1266) rdev->rswitch->port_ok |= (1 << portnum);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1267) rio_set_port_lockout(rdev, portnum, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1268) /* Schedule Insertion Service */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1269) pr_debug("RIO_PW: Device Insertion on [%s]-P%d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1270) rio_name(rdev), portnum);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1271) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1272)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1273) /* Clear error-stopped states (if reported).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1274) * Depending on the link partner state, two attempts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1275) * may be needed for successful recovery.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1276) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1277) if (err_status & (RIO_PORT_N_ERR_STS_OUT_ES |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1278) RIO_PORT_N_ERR_STS_INP_ES)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1279) if (rio_clr_err_stopped(rdev, portnum, err_status))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1280) rio_clr_err_stopped(rdev, portnum, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1281) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1282) } else { /* if (err_status & RIO_PORT_N_ERR_STS_PORT_UNINIT) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1283)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1284) if (rdev->rswitch->port_ok & (1 << portnum)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1285) rdev->rswitch->port_ok &= ~(1 << portnum);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1286) rio_set_port_lockout(rdev, portnum, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1287)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1288) if (rdev->phys_rmap == 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1289) rio_write_config_32(rdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1290) RIO_DEV_PORT_N_ACK_STS_CSR(rdev, portnum),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1291) RIO_PORT_N_ACK_CLEAR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1292) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1293) rio_write_config_32(rdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1294) RIO_DEV_PORT_N_OB_ACK_CSR(rdev, portnum),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1295) RIO_PORT_N_OB_ACK_CLEAR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1296) rio_write_config_32(rdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1297) RIO_DEV_PORT_N_IB_ACK_CSR(rdev, portnum),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1298) 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1299) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1300)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1301) /* Schedule Extraction Service */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1302) pr_debug("RIO_PW: Device Extraction on [%s]-P%d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1303) rio_name(rdev), portnum);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1304) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1305) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1306)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1307) rio_read_config_32(rdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1308) rdev->em_efptr + RIO_EM_PN_ERR_DETECT(portnum), &em_perrdet);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1309) if (em_perrdet) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1310) pr_debug("RIO_PW: RIO_EM_P%d_ERR_DETECT=0x%08x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1311) portnum, em_perrdet);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1312) /* Clear EM Port N Error Detect CSR */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1313) rio_write_config_32(rdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1314) rdev->em_efptr + RIO_EM_PN_ERR_DETECT(portnum), 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1315) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1316)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1317) rio_read_config_32(rdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1318) rdev->em_efptr + RIO_EM_LTL_ERR_DETECT, &em_ltlerrdet);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1319) if (em_ltlerrdet) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1320) pr_debug("RIO_PW: RIO_EM_LTL_ERR_DETECT=0x%08x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1321) em_ltlerrdet);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1322) /* Clear EM L/T Layer Error Detect CSR */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1323) rio_write_config_32(rdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1324) rdev->em_efptr + RIO_EM_LTL_ERR_DETECT, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1325) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1326)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1327) /* Clear remaining error bits and Port-Write Pending bit */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1328) rio_write_config_32(rdev, RIO_DEV_PORT_N_ERR_STS_CSR(rdev, portnum),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1329) err_status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1330)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1331) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1332) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1333) EXPORT_SYMBOL_GPL(rio_inb_pwrite_handler);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1334)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1335) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1336) * rio_mport_get_efb - get pointer to next extended features block
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1337) * @port: Master port to issue transaction
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1338) * @local: Indicate a local master port or remote device access
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1339) * @destid: Destination ID of the device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1340) * @hopcount: Number of switch hops to the device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1341) * @from: Offset of current Extended Feature block header (if 0 starts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1342) * from ExtFeaturePtr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1343) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1344) u32
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1345) rio_mport_get_efb(struct rio_mport *port, int local, u16 destid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1346) u8 hopcount, u32 from)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1347) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1348) u32 reg_val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1349)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1350) if (from == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1351) if (local)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1352) rio_local_read_config_32(port, RIO_ASM_INFO_CAR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1353) ®_val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1354) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1355) rio_mport_read_config_32(port, destid, hopcount,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1356) RIO_ASM_INFO_CAR, ®_val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1357) return reg_val & RIO_EXT_FTR_PTR_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1358) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1359) if (local)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1360) rio_local_read_config_32(port, from, ®_val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1361) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1362) rio_mport_read_config_32(port, destid, hopcount,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1363) from, ®_val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1364) return RIO_GET_BLOCK_ID(reg_val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1365) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1366) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1367) EXPORT_SYMBOL_GPL(rio_mport_get_efb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1368)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1369) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1370) * rio_mport_get_feature - query for devices' extended features
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1371) * @port: Master port to issue transaction
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1372) * @local: Indicate a local master port or remote device access
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1373) * @destid: Destination ID of the device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1374) * @hopcount: Number of switch hops to the device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1375) * @ftr: Extended feature code
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1376) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1377) * Tell if a device supports a given RapidIO capability.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1378) * Returns the offset of the requested extended feature
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1379) * block within the device's RIO configuration space or
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1380) * 0 in case the device does not support it.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1381) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1382) u32
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1383) rio_mport_get_feature(struct rio_mport * port, int local, u16 destid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1384) u8 hopcount, int ftr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1385) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1386) u32 asm_info, ext_ftr_ptr, ftr_header;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1387)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1388) if (local)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1389) rio_local_read_config_32(port, RIO_ASM_INFO_CAR, &asm_info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1390) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1391) rio_mport_read_config_32(port, destid, hopcount,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1392) RIO_ASM_INFO_CAR, &asm_info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1393)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1394) ext_ftr_ptr = asm_info & RIO_EXT_FTR_PTR_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1395)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1396) while (ext_ftr_ptr) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1397) if (local)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1398) rio_local_read_config_32(port, ext_ftr_ptr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1399) &ftr_header);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1400) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1401) rio_mport_read_config_32(port, destid, hopcount,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1402) ext_ftr_ptr, &ftr_header);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1403) if (RIO_GET_BLOCK_ID(ftr_header) == ftr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1404) return ext_ftr_ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1405)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1406) ext_ftr_ptr = RIO_GET_BLOCK_PTR(ftr_header);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1407) if (!ext_ftr_ptr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1408) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1409) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1410)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1411) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1412) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1413) EXPORT_SYMBOL_GPL(rio_mport_get_feature);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1414)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1415) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1416) * rio_get_asm - Begin or continue searching for a RIO device by vid/did/asm_vid/asm_did
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1417) * @vid: RIO vid to match or %RIO_ANY_ID to match all vids
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1418) * @did: RIO did to match or %RIO_ANY_ID to match all dids
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1419) * @asm_vid: RIO asm_vid to match or %RIO_ANY_ID to match all asm_vids
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1420) * @asm_did: RIO asm_did to match or %RIO_ANY_ID to match all asm_dids
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1421) * @from: Previous RIO device found in search, or %NULL for new search
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1422) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1423) * Iterates through the list of known RIO devices. If a RIO device is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1424) * found with a matching @vid, @did, @asm_vid, @asm_did, the reference
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1425) * count to the device is incrememted and a pointer to its device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1426) * structure is returned. Otherwise, %NULL is returned. A new search
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1427) * is initiated by passing %NULL to the @from argument. Otherwise, if
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1428) * @from is not %NULL, searches continue from next device on the global
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1429) * list. The reference count for @from is always decremented if it is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1430) * not %NULL.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1431) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1432) struct rio_dev *rio_get_asm(u16 vid, u16 did,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1433) u16 asm_vid, u16 asm_did, struct rio_dev *from)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1434) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1435) struct list_head *n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1436) struct rio_dev *rdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1437)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1438) WARN_ON(in_interrupt());
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1439) spin_lock(&rio_global_list_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1440) n = from ? from->global_list.next : rio_devices.next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1441)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1442) while (n && (n != &rio_devices)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1443) rdev = rio_dev_g(n);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1444) if ((vid == RIO_ANY_ID || rdev->vid == vid) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1445) (did == RIO_ANY_ID || rdev->did == did) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1446) (asm_vid == RIO_ANY_ID || rdev->asm_vid == asm_vid) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1447) (asm_did == RIO_ANY_ID || rdev->asm_did == asm_did))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1448) goto exit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1449) n = n->next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1450) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1451) rdev = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1452) exit:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1453) rio_dev_put(from);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1454) rdev = rio_dev_get(rdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1455) spin_unlock(&rio_global_list_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1456) return rdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1457) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1458) EXPORT_SYMBOL_GPL(rio_get_asm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1459)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1460) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1461) * rio_get_device - Begin or continue searching for a RIO device by vid/did
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1462) * @vid: RIO vid to match or %RIO_ANY_ID to match all vids
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1463) * @did: RIO did to match or %RIO_ANY_ID to match all dids
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1464) * @from: Previous RIO device found in search, or %NULL for new search
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1465) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1466) * Iterates through the list of known RIO devices. If a RIO device is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1467) * found with a matching @vid and @did, the reference count to the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1468) * device is incrememted and a pointer to its device structure is returned.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1469) * Otherwise, %NULL is returned. A new search is initiated by passing %NULL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1470) * to the @from argument. Otherwise, if @from is not %NULL, searches
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1471) * continue from next device on the global list. The reference count for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1472) * @from is always decremented if it is not %NULL.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1473) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1474) struct rio_dev *rio_get_device(u16 vid, u16 did, struct rio_dev *from)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1475) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1476) return rio_get_asm(vid, did, RIO_ANY_ID, RIO_ANY_ID, from);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1477) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1478) EXPORT_SYMBOL_GPL(rio_get_device);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1479)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1480) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1481) * rio_std_route_add_entry - Add switch route table entry using standard
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1482) * registers defined in RIO specification rev.1.3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1483) * @mport: Master port to issue transaction
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1484) * @destid: Destination ID of the device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1485) * @hopcount: Number of switch hops to the device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1486) * @table: routing table ID (global or port-specific)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1487) * @route_destid: destID entry in the RT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1488) * @route_port: destination port for specified destID
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1489) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1490) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1491) rio_std_route_add_entry(struct rio_mport *mport, u16 destid, u8 hopcount,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1492) u16 table, u16 route_destid, u8 route_port)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1493) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1494) if (table == RIO_GLOBAL_TABLE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1495) rio_mport_write_config_32(mport, destid, hopcount,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1496) RIO_STD_RTE_CONF_DESTID_SEL_CSR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1497) (u32)route_destid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1498) rio_mport_write_config_32(mport, destid, hopcount,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1499) RIO_STD_RTE_CONF_PORT_SEL_CSR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1500) (u32)route_port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1501) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1502)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1503) udelay(10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1504) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1505) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1506)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1507) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1508) * rio_std_route_get_entry - Read switch route table entry (port number)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1509) * associated with specified destID using standard registers defined in RIO
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1510) * specification rev.1.3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1511) * @mport: Master port to issue transaction
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1512) * @destid: Destination ID of the device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1513) * @hopcount: Number of switch hops to the device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1514) * @table: routing table ID (global or port-specific)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1515) * @route_destid: destID entry in the RT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1516) * @route_port: returned destination port for specified destID
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1517) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1518) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1519) rio_std_route_get_entry(struct rio_mport *mport, u16 destid, u8 hopcount,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1520) u16 table, u16 route_destid, u8 *route_port)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1521) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1522) u32 result;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1523)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1524) if (table == RIO_GLOBAL_TABLE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1525) rio_mport_write_config_32(mport, destid, hopcount,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1526) RIO_STD_RTE_CONF_DESTID_SEL_CSR, route_destid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1527) rio_mport_read_config_32(mport, destid, hopcount,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1528) RIO_STD_RTE_CONF_PORT_SEL_CSR, &result);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1529)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1530) *route_port = (u8)result;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1531) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1532)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1533) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1534) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1535)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1536) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1537) * rio_std_route_clr_table - Clear swotch route table using standard registers
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1538) * defined in RIO specification rev.1.3.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1539) * @mport: Master port to issue transaction
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1540) * @destid: Destination ID of the device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1541) * @hopcount: Number of switch hops to the device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1542) * @table: routing table ID (global or port-specific)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1543) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1544) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1545) rio_std_route_clr_table(struct rio_mport *mport, u16 destid, u8 hopcount,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1546) u16 table)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1547) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1548) u32 max_destid = 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1549) u32 i, pef, id_inc = 1, ext_cfg = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1550) u32 port_sel = RIO_INVALID_ROUTE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1551)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1552) if (table == RIO_GLOBAL_TABLE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1553) rio_mport_read_config_32(mport, destid, hopcount,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1554) RIO_PEF_CAR, &pef);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1555)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1556) if (mport->sys_size) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1557) rio_mport_read_config_32(mport, destid, hopcount,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1558) RIO_SWITCH_RT_LIMIT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1559) &max_destid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1560) max_destid &= RIO_RT_MAX_DESTID;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1561) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1562)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1563) if (pef & RIO_PEF_EXT_RT) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1564) ext_cfg = 0x80000000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1565) id_inc = 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1566) port_sel = (RIO_INVALID_ROUTE << 24) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1567) (RIO_INVALID_ROUTE << 16) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1568) (RIO_INVALID_ROUTE << 8) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1569) RIO_INVALID_ROUTE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1570) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1571)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1572) for (i = 0; i <= max_destid;) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1573) rio_mport_write_config_32(mport, destid, hopcount,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1574) RIO_STD_RTE_CONF_DESTID_SEL_CSR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1575) ext_cfg | i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1576) rio_mport_write_config_32(mport, destid, hopcount,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1577) RIO_STD_RTE_CONF_PORT_SEL_CSR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1578) port_sel);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1579) i += id_inc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1580) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1581) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1582)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1583) udelay(10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1584) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1585) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1586)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1587) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1588) * rio_lock_device - Acquires host device lock for specified device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1589) * @port: Master port to send transaction
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1590) * @destid: Destination ID for device/switch
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1591) * @hopcount: Hopcount to reach switch
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1592) * @wait_ms: Max wait time in msec (0 = no timeout)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1593) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1594) * Attepts to acquire host device lock for specified device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1595) * Returns 0 if device lock acquired or EINVAL if timeout expires.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1596) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1597) int rio_lock_device(struct rio_mport *port, u16 destid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1598) u8 hopcount, int wait_ms)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1599) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1600) u32 result;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1601) int tcnt = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1602)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1603) /* Attempt to acquire device lock */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1604) rio_mport_write_config_32(port, destid, hopcount,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1605) RIO_HOST_DID_LOCK_CSR, port->host_deviceid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1606) rio_mport_read_config_32(port, destid, hopcount,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1607) RIO_HOST_DID_LOCK_CSR, &result);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1608)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1609) while (result != port->host_deviceid) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1610) if (wait_ms != 0 && tcnt == wait_ms) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1611) pr_debug("RIO: timeout when locking device %x:%x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1612) destid, hopcount);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1613) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1614) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1615)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1616) /* Delay a bit */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1617) mdelay(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1618) tcnt++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1619) /* Try to acquire device lock again */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1620) rio_mport_write_config_32(port, destid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1621) hopcount,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1622) RIO_HOST_DID_LOCK_CSR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1623) port->host_deviceid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1624) rio_mport_read_config_32(port, destid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1625) hopcount,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1626) RIO_HOST_DID_LOCK_CSR, &result);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1627) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1628)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1629) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1630) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1631) EXPORT_SYMBOL_GPL(rio_lock_device);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1632)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1633) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1634) * rio_unlock_device - Releases host device lock for specified device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1635) * @port: Master port to send transaction
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1636) * @destid: Destination ID for device/switch
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1637) * @hopcount: Hopcount to reach switch
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1638) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1639) * Returns 0 if device lock released or EINVAL if fails.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1640) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1641) int rio_unlock_device(struct rio_mport *port, u16 destid, u8 hopcount)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1642) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1643) u32 result;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1644)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1645) /* Release device lock */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1646) rio_mport_write_config_32(port, destid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1647) hopcount,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1648) RIO_HOST_DID_LOCK_CSR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1649) port->host_deviceid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1650) rio_mport_read_config_32(port, destid, hopcount,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1651) RIO_HOST_DID_LOCK_CSR, &result);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1652) if ((result & 0xffff) != 0xffff) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1653) pr_debug("RIO: badness when releasing device lock %x:%x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1654) destid, hopcount);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1655) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1656) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1657)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1658) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1659) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1660) EXPORT_SYMBOL_GPL(rio_unlock_device);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1661)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1662) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1663) * rio_route_add_entry- Add a route entry to a switch routing table
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1664) * @rdev: RIO device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1665) * @table: Routing table ID
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1666) * @route_destid: Destination ID to be routed
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1667) * @route_port: Port number to be routed
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1668) * @lock: apply a hardware lock on switch device flag (1=lock, 0=no_lock)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1669) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1670) * If available calls the switch specific add_entry() method to add a route
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1671) * entry into a switch routing table. Otherwise uses standard RT update method
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1672) * as defined by RapidIO specification. A specific routing table can be selected
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1673) * using the @table argument if a switch has per port routing tables or
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1674) * the standard (or global) table may be used by passing
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1675) * %RIO_GLOBAL_TABLE in @table.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1676) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1677) * Returns %0 on success or %-EINVAL on failure.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1678) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1679) int rio_route_add_entry(struct rio_dev *rdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1680) u16 table, u16 route_destid, u8 route_port, int lock)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1681) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1682) int rc = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1683) struct rio_switch_ops *ops = rdev->rswitch->ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1684)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1685) if (lock) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1686) rc = rio_lock_device(rdev->net->hport, rdev->destid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1687) rdev->hopcount, 1000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1688) if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1689) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1690) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1691)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1692) spin_lock(&rdev->rswitch->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1693)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1694) if (!ops || !ops->add_entry) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1695) rc = rio_std_route_add_entry(rdev->net->hport, rdev->destid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1696) rdev->hopcount, table,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1697) route_destid, route_port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1698) } else if (try_module_get(ops->owner)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1699) rc = ops->add_entry(rdev->net->hport, rdev->destid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1700) rdev->hopcount, table, route_destid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1701) route_port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1702) module_put(ops->owner);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1703) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1704)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1705) spin_unlock(&rdev->rswitch->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1706)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1707) if (lock)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1708) rio_unlock_device(rdev->net->hport, rdev->destid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1709) rdev->hopcount);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1710)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1711) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1712) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1713) EXPORT_SYMBOL_GPL(rio_route_add_entry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1714)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1715) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1716) * rio_route_get_entry- Read an entry from a switch routing table
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1717) * @rdev: RIO device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1718) * @table: Routing table ID
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1719) * @route_destid: Destination ID to be routed
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1720) * @route_port: Pointer to read port number into
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1721) * @lock: apply a hardware lock on switch device flag (1=lock, 0=no_lock)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1722) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1723) * If available calls the switch specific get_entry() method to fetch a route
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1724) * entry from a switch routing table. Otherwise uses standard RT read method
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1725) * as defined by RapidIO specification. A specific routing table can be selected
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1726) * using the @table argument if a switch has per port routing tables or
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1727) * the standard (or global) table may be used by passing
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1728) * %RIO_GLOBAL_TABLE in @table.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1729) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1730) * Returns %0 on success or %-EINVAL on failure.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1731) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1732) int rio_route_get_entry(struct rio_dev *rdev, u16 table,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1733) u16 route_destid, u8 *route_port, int lock)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1734) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1735) int rc = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1736) struct rio_switch_ops *ops = rdev->rswitch->ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1737)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1738) if (lock) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1739) rc = rio_lock_device(rdev->net->hport, rdev->destid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1740) rdev->hopcount, 1000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1741) if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1742) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1743) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1744)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1745) spin_lock(&rdev->rswitch->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1746)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1747) if (!ops || !ops->get_entry) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1748) rc = rio_std_route_get_entry(rdev->net->hport, rdev->destid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1749) rdev->hopcount, table,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1750) route_destid, route_port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1751) } else if (try_module_get(ops->owner)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1752) rc = ops->get_entry(rdev->net->hport, rdev->destid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1753) rdev->hopcount, table, route_destid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1754) route_port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1755) module_put(ops->owner);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1756) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1757)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1758) spin_unlock(&rdev->rswitch->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1759)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1760) if (lock)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1761) rio_unlock_device(rdev->net->hport, rdev->destid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1762) rdev->hopcount);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1763) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1764) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1765) EXPORT_SYMBOL_GPL(rio_route_get_entry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1766)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1767) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1768) * rio_route_clr_table - Clear a switch routing table
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1769) * @rdev: RIO device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1770) * @table: Routing table ID
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1771) * @lock: apply a hardware lock on switch device flag (1=lock, 0=no_lock)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1772) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1773) * If available calls the switch specific clr_table() method to clear a switch
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1774) * routing table. Otherwise uses standard RT write method as defined by RapidIO
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1775) * specification. A specific routing table can be selected using the @table
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1776) * argument if a switch has per port routing tables or the standard (or global)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1777) * table may be used by passing %RIO_GLOBAL_TABLE in @table.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1778) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1779) * Returns %0 on success or %-EINVAL on failure.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1780) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1781) int rio_route_clr_table(struct rio_dev *rdev, u16 table, int lock)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1782) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1783) int rc = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1784) struct rio_switch_ops *ops = rdev->rswitch->ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1785)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1786) if (lock) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1787) rc = rio_lock_device(rdev->net->hport, rdev->destid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1788) rdev->hopcount, 1000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1789) if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1790) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1791) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1792)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1793) spin_lock(&rdev->rswitch->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1794)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1795) if (!ops || !ops->clr_table) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1796) rc = rio_std_route_clr_table(rdev->net->hport, rdev->destid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1797) rdev->hopcount, table);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1798) } else if (try_module_get(ops->owner)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1799) rc = ops->clr_table(rdev->net->hport, rdev->destid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1800) rdev->hopcount, table);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1801)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1802) module_put(ops->owner);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1803) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1804)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1805) spin_unlock(&rdev->rswitch->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1806)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1807) if (lock)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1808) rio_unlock_device(rdev->net->hport, rdev->destid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1809) rdev->hopcount);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1810)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1811) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1812) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1813) EXPORT_SYMBOL_GPL(rio_route_clr_table);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1814)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1815) #ifdef CONFIG_RAPIDIO_DMA_ENGINE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1816)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1817) static bool rio_chan_filter(struct dma_chan *chan, void *arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1818) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1819) struct rio_mport *mport = arg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1820)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1821) /* Check that DMA device belongs to the right MPORT */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1822) return mport == container_of(chan->device, struct rio_mport, dma);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1823) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1824)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1825) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1826) * rio_request_mport_dma - request RapidIO capable DMA channel associated
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1827) * with specified local RapidIO mport device.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1828) * @mport: RIO mport to perform DMA data transfers
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1829) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1830) * Returns pointer to allocated DMA channel or NULL if failed.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1831) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1832) struct dma_chan *rio_request_mport_dma(struct rio_mport *mport)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1833) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1834) dma_cap_mask_t mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1835)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1836) dma_cap_zero(mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1837) dma_cap_set(DMA_SLAVE, mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1838) return dma_request_channel(mask, rio_chan_filter, mport);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1839) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1840) EXPORT_SYMBOL_GPL(rio_request_mport_dma);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1841)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1842) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1843) * rio_request_dma - request RapidIO capable DMA channel that supports
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1844) * specified target RapidIO device.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1845) * @rdev: RIO device associated with DMA transfer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1846) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1847) * Returns pointer to allocated DMA channel or NULL if failed.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1848) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1849) struct dma_chan *rio_request_dma(struct rio_dev *rdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1850) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1851) return rio_request_mport_dma(rdev->net->hport);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1852) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1853) EXPORT_SYMBOL_GPL(rio_request_dma);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1854)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1855) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1856) * rio_release_dma - release specified DMA channel
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1857) * @dchan: DMA channel to release
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1858) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1859) void rio_release_dma(struct dma_chan *dchan)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1860) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1861) dma_release_channel(dchan);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1862) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1863) EXPORT_SYMBOL_GPL(rio_release_dma);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1864)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1865) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1866) * rio_dma_prep_xfer - RapidIO specific wrapper
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1867) * for device_prep_slave_sg callback defined by DMAENGINE.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1868) * @dchan: DMA channel to configure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1869) * @destid: target RapidIO device destination ID
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1870) * @data: RIO specific data descriptor
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1871) * @direction: DMA data transfer direction (TO or FROM the device)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1872) * @flags: dmaengine defined flags
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1873) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1874) * Initializes RapidIO capable DMA channel for the specified data transfer.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1875) * Uses DMA channel private extension to pass information related to remote
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1876) * target RIO device.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1877) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1878) * Returns: pointer to DMA transaction descriptor if successful,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1879) * error-valued pointer or NULL if failed.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1880) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1881) struct dma_async_tx_descriptor *rio_dma_prep_xfer(struct dma_chan *dchan,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1882) u16 destid, struct rio_dma_data *data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1883) enum dma_transfer_direction direction, unsigned long flags)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1884) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1885) struct rio_dma_ext rio_ext;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1886)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1887) if (!dchan->device->device_prep_slave_sg) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1888) pr_err("%s: prep_rio_sg == NULL\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1889) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1890) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1891)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1892) rio_ext.destid = destid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1893) rio_ext.rio_addr_u = data->rio_addr_u;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1894) rio_ext.rio_addr = data->rio_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1895) rio_ext.wr_type = data->wr_type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1896)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1897) return dmaengine_prep_rio_sg(dchan, data->sg, data->sg_len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1898) direction, flags, &rio_ext);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1899) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1900) EXPORT_SYMBOL_GPL(rio_dma_prep_xfer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1901)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1902) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1903) * rio_dma_prep_slave_sg - RapidIO specific wrapper
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1904) * for device_prep_slave_sg callback defined by DMAENGINE.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1905) * @rdev: RIO device control structure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1906) * @dchan: DMA channel to configure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1907) * @data: RIO specific data descriptor
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1908) * @direction: DMA data transfer direction (TO or FROM the device)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1909) * @flags: dmaengine defined flags
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1910) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1911) * Initializes RapidIO capable DMA channel for the specified data transfer.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1912) * Uses DMA channel private extension to pass information related to remote
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1913) * target RIO device.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1914) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1915) * Returns: pointer to DMA transaction descriptor if successful,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1916) * error-valued pointer or NULL if failed.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1917) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1918) struct dma_async_tx_descriptor *rio_dma_prep_slave_sg(struct rio_dev *rdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1919) struct dma_chan *dchan, struct rio_dma_data *data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1920) enum dma_transfer_direction direction, unsigned long flags)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1921) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1922) return rio_dma_prep_xfer(dchan, rdev->destid, data, direction, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1923) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1924) EXPORT_SYMBOL_GPL(rio_dma_prep_slave_sg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1925)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1926) #endif /* CONFIG_RAPIDIO_DMA_ENGINE */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1927)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1928) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1929) * rio_find_mport - find RIO mport by its ID
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1930) * @mport_id: number (ID) of mport device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1931) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1932) * Given a RIO mport number, the desired mport is located
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1933) * in the global list of mports. If the mport is found, a pointer to its
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1934) * data structure is returned. If no mport is found, %NULL is returned.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1935) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1936) struct rio_mport *rio_find_mport(int mport_id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1937) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1938) struct rio_mport *port;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1939)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1940) mutex_lock(&rio_mport_list_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1941) list_for_each_entry(port, &rio_mports, node) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1942) if (port->id == mport_id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1943) goto found;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1944) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1945) port = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1946) found:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1947) mutex_unlock(&rio_mport_list_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1948)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1949) return port;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1950) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1951)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1952) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1953) * rio_register_scan - enumeration/discovery method registration interface
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1954) * @mport_id: mport device ID for which fabric scan routine has to be set
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1955) * (RIO_MPORT_ANY = set for all available mports)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1956) * @scan_ops: enumeration/discovery operations structure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1957) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1958) * Registers enumeration/discovery operations with RapidIO subsystem and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1959) * attaches it to the specified mport device (or all available mports
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1960) * if RIO_MPORT_ANY is specified).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1961) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1962) * Returns error if the mport already has an enumerator attached to it.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1963) * In case of RIO_MPORT_ANY skips mports with valid scan routines (no error).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1964) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1965) int rio_register_scan(int mport_id, struct rio_scan *scan_ops)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1966) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1967) struct rio_mport *port;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1968) struct rio_scan_node *scan;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1969) int rc = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1970)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1971) pr_debug("RIO: %s for mport_id=%d\n", __func__, mport_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1972)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1973) if ((mport_id != RIO_MPORT_ANY && mport_id >= RIO_MAX_MPORTS) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1974) !scan_ops)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1975) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1976)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1977) mutex_lock(&rio_mport_list_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1978)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1979) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1980) * Check if there is another enumerator already registered for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1981) * the same mport ID (including RIO_MPORT_ANY). Multiple enumerators
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1982) * for the same mport ID are not supported.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1983) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1984) list_for_each_entry(scan, &rio_scans, node) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1985) if (scan->mport_id == mport_id) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1986) rc = -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1987) goto err_out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1988) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1989) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1990)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1991) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1992) * Allocate and initialize new scan registration node.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1993) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1994) scan = kzalloc(sizeof(*scan), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1995) if (!scan) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1996) rc = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1997) goto err_out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1998) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1999)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2000) scan->mport_id = mport_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2001) scan->ops = scan_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2002)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2003) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2004) * Traverse the list of registered mports to attach this new scan.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2005) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2006) * The new scan with matching mport ID overrides any previously attached
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2007) * scan assuming that old scan (if any) is the default one (based on the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2008) * enumerator registration check above).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2009) * If the new scan is the global one, it will be attached only to mports
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2010) * that do not have their own individual operations already attached.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2011) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2012) list_for_each_entry(port, &rio_mports, node) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2013) if (port->id == mport_id) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2014) port->nscan = scan_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2015) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2016) } else if (mport_id == RIO_MPORT_ANY && !port->nscan)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2017) port->nscan = scan_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2018) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2019)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2020) list_add_tail(&scan->node, &rio_scans);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2021)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2022) err_out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2023) mutex_unlock(&rio_mport_list_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2024)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2025) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2026) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2027) EXPORT_SYMBOL_GPL(rio_register_scan);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2028)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2029) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2030) * rio_unregister_scan - removes enumeration/discovery method from mport
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2031) * @mport_id: mport device ID for which fabric scan routine has to be
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2032) * unregistered (RIO_MPORT_ANY = apply to all mports that use
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2033) * the specified scan_ops)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2034) * @scan_ops: enumeration/discovery operations structure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2035) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2036) * Removes enumeration or discovery method assigned to the specified mport
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2037) * device. If RIO_MPORT_ANY is specified, removes the specified operations from
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2038) * all mports that have them attached.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2039) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2040) int rio_unregister_scan(int mport_id, struct rio_scan *scan_ops)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2041) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2042) struct rio_mport *port;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2043) struct rio_scan_node *scan;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2044)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2045) pr_debug("RIO: %s for mport_id=%d\n", __func__, mport_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2046)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2047) if (mport_id != RIO_MPORT_ANY && mport_id >= RIO_MAX_MPORTS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2048) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2049)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2050) mutex_lock(&rio_mport_list_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2051)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2052) list_for_each_entry(port, &rio_mports, node)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2053) if (port->id == mport_id ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2054) (mport_id == RIO_MPORT_ANY && port->nscan == scan_ops))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2055) port->nscan = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2056)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2057) list_for_each_entry(scan, &rio_scans, node) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2058) if (scan->mport_id == mport_id) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2059) list_del(&scan->node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2060) kfree(scan);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2061) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2062) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2063) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2064)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2065) mutex_unlock(&rio_mport_list_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2066)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2067) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2068) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2069) EXPORT_SYMBOL_GPL(rio_unregister_scan);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2070)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2071) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2072) * rio_mport_scan - execute enumeration/discovery on the specified mport
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2073) * @mport_id: number (ID) of mport device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2074) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2075) int rio_mport_scan(int mport_id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2076) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2077) struct rio_mport *port = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2078) int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2079)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2080) mutex_lock(&rio_mport_list_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2081) list_for_each_entry(port, &rio_mports, node) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2082) if (port->id == mport_id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2083) goto found;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2084) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2085) mutex_unlock(&rio_mport_list_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2086) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2087) found:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2088) if (!port->nscan) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2089) mutex_unlock(&rio_mport_list_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2090) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2091) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2092)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2093) if (!try_module_get(port->nscan->owner)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2094) mutex_unlock(&rio_mport_list_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2095) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2096) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2097)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2098) mutex_unlock(&rio_mport_list_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2099)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2100) if (port->host_deviceid >= 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2101) rc = port->nscan->enumerate(port, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2102) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2103) rc = port->nscan->discover(port, RIO_SCAN_ENUM_NO_WAIT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2104)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2105) module_put(port->nscan->owner);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2106) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2107) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2108)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2109) static void rio_fixup_device(struct rio_dev *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2110) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2111) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2112)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2113) static int rio_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2114) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2115) struct rio_dev *dev = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2116)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2117) while ((dev = rio_get_device(RIO_ANY_ID, RIO_ANY_ID, dev)) != NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2118) rio_fixup_device(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2119) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2120) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2121) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2122)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2123) static struct workqueue_struct *rio_wq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2124)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2125) struct rio_disc_work {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2126) struct work_struct work;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2127) struct rio_mport *mport;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2128) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2129)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2130) static void disc_work_handler(struct work_struct *_work)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2131) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2132) struct rio_disc_work *work;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2133)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2134) work = container_of(_work, struct rio_disc_work, work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2135) pr_debug("RIO: discovery work for mport %d %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2136) work->mport->id, work->mport->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2137) if (try_module_get(work->mport->nscan->owner)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2138) work->mport->nscan->discover(work->mport, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2139) module_put(work->mport->nscan->owner);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2140) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2141) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2142)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2143) int rio_init_mports(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2144) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2145) struct rio_mport *port;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2146) struct rio_disc_work *work;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2147) int n = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2148)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2149) if (!next_portid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2150) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2151)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2152) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2153) * First, run enumerations and check if we need to perform discovery
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2154) * on any of the registered mports.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2155) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2156) mutex_lock(&rio_mport_list_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2157) list_for_each_entry(port, &rio_mports, node) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2158) if (port->host_deviceid >= 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2159) if (port->nscan && try_module_get(port->nscan->owner)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2160) port->nscan->enumerate(port, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2161) module_put(port->nscan->owner);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2162) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2163) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2164) n++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2165) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2166) mutex_unlock(&rio_mport_list_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2167)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2168) if (!n)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2169) goto no_disc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2170)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2171) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2172) * If we have mports that require discovery schedule a discovery work
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2173) * for each of them. If the code below fails to allocate needed
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2174) * resources, exit without error to keep results of enumeration
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2175) * process (if any).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2176) * TODO: Implement restart of discovery process for all or
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2177) * individual discovering mports.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2178) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2179) rio_wq = alloc_workqueue("riodisc", 0, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2180) if (!rio_wq) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2181) pr_err("RIO: unable allocate rio_wq\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2182) goto no_disc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2183) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2184)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2185) work = kcalloc(n, sizeof *work, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2186) if (!work) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2187) destroy_workqueue(rio_wq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2188) goto no_disc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2189) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2190)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2191) n = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2192) mutex_lock(&rio_mport_list_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2193) list_for_each_entry(port, &rio_mports, node) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2194) if (port->host_deviceid < 0 && port->nscan) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2195) work[n].mport = port;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2196) INIT_WORK(&work[n].work, disc_work_handler);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2197) queue_work(rio_wq, &work[n].work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2198) n++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2199) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2200) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2201)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2202) flush_workqueue(rio_wq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2203) mutex_unlock(&rio_mport_list_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2204) pr_debug("RIO: destroy discovery workqueue\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2205) destroy_workqueue(rio_wq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2206) kfree(work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2207)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2208) no_disc:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2209) rio_init();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2210)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2211) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2212) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2213) EXPORT_SYMBOL_GPL(rio_init_mports);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2214)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2215) static int rio_get_hdid(int index)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2216) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2217) if (ids_num == 0 || ids_num <= index || index >= RIO_MAX_MPORTS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2218) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2219)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2220) return hdid[index];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2221) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2222)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2223) int rio_mport_initialize(struct rio_mport *mport)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2224) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2225) if (next_portid >= RIO_MAX_MPORTS) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2226) pr_err("RIO: reached specified max number of mports\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2227) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2228) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2229)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2230) atomic_set(&mport->state, RIO_DEVICE_INITIALIZING);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2231) mport->id = next_portid++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2232) mport->host_deviceid = rio_get_hdid(mport->id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2233) mport->nscan = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2234) mutex_init(&mport->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2235) mport->pwe_refcnt = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2236) INIT_LIST_HEAD(&mport->pwrites);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2237)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2238) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2239) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2240) EXPORT_SYMBOL_GPL(rio_mport_initialize);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2241)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2242) int rio_register_mport(struct rio_mport *port)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2243) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2244) struct rio_scan_node *scan = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2245) int res = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2246)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2247) mutex_lock(&rio_mport_list_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2248)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2249) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2250) * Check if there are any registered enumeration/discovery operations
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2251) * that have to be attached to the added mport.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2252) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2253) list_for_each_entry(scan, &rio_scans, node) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2254) if (port->id == scan->mport_id ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2255) scan->mport_id == RIO_MPORT_ANY) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2256) port->nscan = scan->ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2257) if (port->id == scan->mport_id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2258) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2259) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2260) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2261)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2262) list_add_tail(&port->node, &rio_mports);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2263) mutex_unlock(&rio_mport_list_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2264)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2265) dev_set_name(&port->dev, "rapidio%d", port->id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2266) port->dev.class = &rio_mport_class;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2267) atomic_set(&port->state, RIO_DEVICE_RUNNING);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2268)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2269) res = device_register(&port->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2270) if (res)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2271) dev_err(&port->dev, "RIO: mport%d registration failed ERR=%d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2272) port->id, res);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2273) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2274) dev_dbg(&port->dev, "RIO: registered mport%d\n", port->id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2275)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2276) return res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2277) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2278) EXPORT_SYMBOL_GPL(rio_register_mport);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2279)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2280) static int rio_mport_cleanup_callback(struct device *dev, void *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2281) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2282) struct rio_dev *rdev = to_rio_dev(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2283)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2284) if (dev->bus == &rio_bus_type)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2285) rio_del_device(rdev, RIO_DEVICE_SHUTDOWN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2286) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2287) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2288)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2289) static int rio_net_remove_children(struct rio_net *net)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2290) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2291) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2292) * Unregister all RapidIO devices residing on this net (this will
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2293) * invoke notification of registered subsystem interfaces as well).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2294) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2295) device_for_each_child(&net->dev, NULL, rio_mport_cleanup_callback);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2296) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2297) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2298)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2299) int rio_unregister_mport(struct rio_mport *port)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2300) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2301) pr_debug("RIO: %s %s id=%d\n", __func__, port->name, port->id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2302)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2303) /* Transition mport to the SHUTDOWN state */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2304) if (atomic_cmpxchg(&port->state,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2305) RIO_DEVICE_RUNNING,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2306) RIO_DEVICE_SHUTDOWN) != RIO_DEVICE_RUNNING) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2307) pr_err("RIO: %s unexpected state transition for mport %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2308) __func__, port->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2309) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2310)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2311) if (port->net && port->net->hport == port) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2312) rio_net_remove_children(port->net);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2313) rio_free_net(port->net);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2314) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2315)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2316) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2317) * Unregister all RapidIO devices attached to this mport (this will
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2318) * invoke notification of registered subsystem interfaces as well).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2319) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2320) mutex_lock(&rio_mport_list_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2321) list_del(&port->node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2322) mutex_unlock(&rio_mport_list_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2323) device_unregister(&port->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2324)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2325) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2326) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2327) EXPORT_SYMBOL_GPL(rio_unregister_mport);