aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/rapidio
diff options
context:
space:
mode:
authorAlexandre Bounine <alexandre.bounine@idt.com>2012-10-04 20:16:13 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2012-10-05 14:05:23 -0400
commitde74e00a965177e8a0d44af0ba31971b80f2bf3f (patch)
tree2c4aec10d723df0a16c46546b222d9e97189f364 /drivers/rapidio
parent2fb717ec3ec76b0ca4cee9c4d802ce551750413d (diff)
rapidio: add destination ID allocation mechanism
Replace the single global destination ID counter with per-net allocation mechanism to allow independent destID management for each available RapidIO network. Using bitmap based mechanism instead of counters allows destination ID release and reuse in systems that support hot-swap. Signed-off-by: Alexandre Bounine <alexandre.bounine@idt.com> Cc: Matt Porter <mporter@kernel.crashing.org> Cc: Li Yang <leoli@freescale.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'drivers/rapidio')
-rw-r--r--drivers/rapidio/rio-scan.c205
1 files changed, 170 insertions, 35 deletions
diff --git a/drivers/rapidio/rio-scan.c b/drivers/rapidio/rio-scan.c
index 745670f535e8..48e9041dd1e2 100644
--- a/drivers/rapidio/rio-scan.c
+++ b/drivers/rapidio/rio-scan.c
@@ -54,6 +54,114 @@ static int rio_mport_phys_table[] = {
54 -1, 54 -1,
55}; 55};
56 56
57
58/*
59 * rio_destid_alloc - Allocate next available destID for given network
60 * net: RIO network
61 *
62 * Returns next available device destination ID for the specified RIO network.
63 * Marks allocated ID as one in use.
64 * Returns RIO_INVALID_DESTID if new destID is not available.
65 */
66static u16 rio_destid_alloc(struct rio_net *net)
67{
68 int destid;
69 struct rio_id_table *idtab = &net->destid_table;
70
71 spin_lock(&idtab->lock);
72 destid = find_next_zero_bit(idtab->table, idtab->max, idtab->next);
73 if (destid >= idtab->max)
74 destid = find_first_zero_bit(idtab->table, idtab->max);
75
76 if (destid < idtab->max) {
77 idtab->next = destid + 1;
78 if (idtab->next >= idtab->max)
79 idtab->next = 0;
80 set_bit(destid, idtab->table);
81 destid += idtab->start;
82 } else
83 destid = RIO_INVALID_DESTID;
84
85 spin_unlock(&idtab->lock);
86 return (u16)destid;
87}
88
89/*
90 * rio_destid_reserve - Reserve the specivied destID
91 * net: RIO network
92 * destid: destID to reserve
93 *
94 * Tries to reserve the specified destID.
95 * Returns 0 if successfull.
96 */
97static int rio_destid_reserve(struct rio_net *net, u16 destid)
98{
99 int oldbit;
100 struct rio_id_table *idtab = &net->destid_table;
101
102 destid -= idtab->start;
103 spin_lock(&idtab->lock);
104 oldbit = test_and_set_bit(destid, idtab->table);
105 spin_unlock(&idtab->lock);
106 return oldbit;
107}
108
109/*
110 * rio_destid_free - free a previously allocated destID
111 * net: RIO network
112 * destid: destID to free
113 *
114 * Makes the specified destID available for use.
115 */
116static void rio_destid_free(struct rio_net *net, u16 destid)
117{
118 struct rio_id_table *idtab = &net->destid_table;
119
120 destid -= idtab->start;
121 spin_lock(&idtab->lock);
122 clear_bit(destid, idtab->table);
123 spin_unlock(&idtab->lock);
124}
125
126/*
127 * rio_destid_first - return first destID in use
128 * net: RIO network
129 */
130static u16 rio_destid_first(struct rio_net *net)
131{
132 int destid;
133 struct rio_id_table *idtab = &net->destid_table;
134
135 spin_lock(&idtab->lock);
136 destid = find_first_bit(idtab->table, idtab->max);
137 if (destid >= idtab->max)
138 destid = RIO_INVALID_DESTID;
139 else
140 destid += idtab->start;
141 spin_unlock(&idtab->lock);
142 return (u16)destid;
143}
144
145/*
146 * rio_destid_next - return next destID in use
147 * net: RIO network
148 * from: destination ID from which search shall continue
149 */
150static u16 rio_destid_next(struct rio_net *net, u16 from)
151{
152 int destid;
153 struct rio_id_table *idtab = &net->destid_table;
154
155 spin_lock(&idtab->lock);
156 destid = find_next_bit(idtab->table, idtab->max, from);
157 if (destid >= idtab->max)
158 destid = RIO_INVALID_DESTID;
159 else
160 destid += idtab->start;
161 spin_unlock(&idtab->lock);
162 return (u16)destid;
163}
164
57/** 165/**
58 * rio_get_device_id - Get the base/extended device id for a device 166 * rio_get_device_id - Get the base/extended device id for a device
59 * @port: RIO master port 167 * @port: RIO master port
@@ -171,10 +279,6 @@ static int rio_enum_host(struct rio_mport *port)
171 279
172 /* Set master port destid and init destid ctr */ 280 /* Set master port destid and init destid ctr */
173 rio_local_set_device_id(port, port->host_deviceid); 281 rio_local_set_device_id(port, port->host_deviceid);
174
175 if (next_destid == port->host_deviceid)
176 next_destid++;
177
178 return 0; 282 return 0;
179} 283}
180 284
@@ -441,9 +545,8 @@ static struct rio_dev __devinit *rio_setup_device(struct rio_net *net,
441 if (rio_device_has_destid(port, rdev->src_ops, rdev->dst_ops)) { 545 if (rio_device_has_destid(port, rdev->src_ops, rdev->dst_ops)) {
442 if (do_enum) { 546 if (do_enum) {
443 rio_set_device_id(port, destid, hopcount, next_destid); 547 rio_set_device_id(port, destid, hopcount, next_destid);
444 rdev->destid = next_destid++; 548 rdev->destid = next_destid;
445 if (next_destid == port->host_deviceid) 549 next_destid = rio_destid_alloc(net);
446 next_destid++;
447 } else 550 } else
448 rdev->destid = rio_get_device_id(port, destid, hopcount); 551 rdev->destid = rio_get_device_id(port, destid, hopcount);
449 552
@@ -742,12 +845,7 @@ static u16 rio_get_host_deviceid_lock(struct rio_mport *port, u8 hopcount)
742static int __devinit rio_enum_peer(struct rio_net *net, struct rio_mport *port, 845static int __devinit rio_enum_peer(struct rio_net *net, struct rio_mport *port,
743 u8 hopcount, struct rio_dev *prev, int prev_port) 846 u8 hopcount, struct rio_dev *prev, int prev_port)
744{ 847{
745 int port_num;
746 int cur_destid;
747 int sw_destid;
748 int sw_inport;
749 struct rio_dev *rdev; 848 struct rio_dev *rdev;
750 u16 destid;
751 u32 regval; 849 u32 regval;
752 int tmp; 850 int tmp;
753 851
@@ -813,19 +911,26 @@ static int __devinit rio_enum_peer(struct rio_net *net, struct rio_mport *port,
813 return -1; 911 return -1;
814 912
815 if (rio_is_switch(rdev)) { 913 if (rio_is_switch(rdev)) {
914 int sw_destid;
915 int cur_destid;
916 int sw_inport;
917 u16 destid;
918 int port_num;
919
816 sw_inport = RIO_GET_PORT_NUM(rdev->swpinfo); 920 sw_inport = RIO_GET_PORT_NUM(rdev->swpinfo);
817 rio_route_add_entry(rdev, RIO_GLOBAL_TABLE, 921 rio_route_add_entry(rdev, RIO_GLOBAL_TABLE,
818 port->host_deviceid, sw_inport, 0); 922 port->host_deviceid, sw_inport, 0);
819 rdev->rswitch->route_table[port->host_deviceid] = sw_inport; 923 rdev->rswitch->route_table[port->host_deviceid] = sw_inport;
820 924
821 for (destid = 0; destid < next_destid; destid++) { 925 destid = rio_destid_first(net);
822 if (destid == port->host_deviceid) 926 while (destid != RIO_INVALID_DESTID && destid < next_destid) {
823 continue; 927 if (destid != port->host_deviceid) {
824 rio_route_add_entry(rdev, RIO_GLOBAL_TABLE, 928 rio_route_add_entry(rdev, RIO_GLOBAL_TABLE,
825 destid, sw_inport, 0); 929 destid, sw_inport, 0);
826 rdev->rswitch->route_table[destid] = sw_inport; 930 rdev->rswitch->route_table[destid] = sw_inport;
931 }
932 destid = rio_destid_next(net, destid + 1);
827 } 933 }
828
829 pr_debug( 934 pr_debug(
830 "RIO: found %s (vid %4.4x did %4.4x) with %d ports\n", 935 "RIO: found %s (vid %4.4x did %4.4x) with %d ports\n",
831 rio_name(rdev), rdev->vid, rdev->did, 936 rio_name(rdev), rdev->vid, rdev->did,
@@ -863,19 +968,22 @@ static int __devinit rio_enum_peer(struct rio_net *net, struct rio_mport *port,
863 return -1; 968 return -1;
864 969
865 /* Update routing tables */ 970 /* Update routing tables */
866 if (next_destid > cur_destid) { 971 destid = rio_destid_next(net, cur_destid + 1);
972 if (destid != RIO_INVALID_DESTID) {
867 for (destid = cur_destid; 973 for (destid = cur_destid;
868 destid < next_destid; destid++) { 974 destid < next_destid;) {
869 if (destid == port->host_deviceid) 975 if (destid != port->host_deviceid) {
870 continue; 976 rio_route_add_entry(rdev,
871 rio_route_add_entry(rdev,
872 RIO_GLOBAL_TABLE, 977 RIO_GLOBAL_TABLE,
873 destid, 978 destid,
874 port_num, 979 port_num,
875 0); 980 0);
876 rdev->rswitch-> 981 rdev->rswitch->
877 route_table[destid] = 982 route_table[destid] =
878 port_num; 983 port_num;
984 }
985 destid = rio_destid_next(net,
986 destid + 1);
879 } 987 }
880 } 988 }
881 } else { 989 } else {
@@ -901,11 +1009,8 @@ static int __devinit rio_enum_peer(struct rio_net *net, struct rio_mport *port,
901 rio_init_em(rdev); 1009 rio_init_em(rdev);
902 1010
903 /* Check for empty switch */ 1011 /* Check for empty switch */
904 if (next_destid == sw_destid) { 1012 if (next_destid == sw_destid)
905 next_destid++; 1013 next_destid = rio_destid_alloc(net);
906 if (next_destid == port->host_deviceid)
907 next_destid++;
908 }
909 1014
910 rdev->destid = sw_destid; 1015 rdev->destid = sw_destid;
911 } else 1016 } else
@@ -1043,17 +1148,39 @@ static int rio_mport_is_active(struct rio_mport *port)
1043/** 1148/**
1044 * rio_alloc_net- Allocate and configure a new RIO network 1149 * rio_alloc_net- Allocate and configure a new RIO network
1045 * @port: Master port associated with the RIO network 1150 * @port: Master port associated with the RIO network
1151 * @do_enum: Enumeration/Discovery mode flag
1152 * @start: logical minimal start id for new net
1046 * 1153 *
1047 * Allocates a RIO network structure, initializes per-network 1154 * Allocates a RIO network structure, initializes per-network
1048 * list heads, and adds the associated master port to the 1155 * list heads, and adds the associated master port to the
1049 * network list of associated master ports. Returns a 1156 * network list of associated master ports. Returns a
1050 * RIO network pointer on success or %NULL on failure. 1157 * RIO network pointer on success or %NULL on failure.
1051 */ 1158 */
1052static struct rio_net __devinit *rio_alloc_net(struct rio_mport *port) 1159static struct rio_net __devinit *rio_alloc_net(struct rio_mport *port,
1160 int do_enum, u16 start)
1053{ 1161{
1054 struct rio_net *net; 1162 struct rio_net *net;
1055 1163
1056 net = kzalloc(sizeof(struct rio_net), GFP_KERNEL); 1164 net = kzalloc(sizeof(struct rio_net), GFP_KERNEL);
1165 if (net && do_enum) {
1166 net->destid_table.table = kzalloc(
1167 BITS_TO_LONGS(RIO_MAX_ROUTE_ENTRIES(port->sys_size)) *
1168 sizeof(long),
1169 GFP_KERNEL);
1170
1171 if (net->destid_table.table == NULL) {
1172 pr_err("RIO: failed to allocate destID table\n");
1173 kfree(net);
1174 net = NULL;
1175 } else {
1176 net->destid_table.start = start;
1177 net->destid_table.next = 0;
1178 net->destid_table.max =
1179 RIO_MAX_ROUTE_ENTRIES(port->sys_size);
1180 spin_lock_init(&net->destid_table.lock);
1181 }
1182 }
1183
1057 if (net) { 1184 if (net) {
1058 INIT_LIST_HEAD(&net->node); 1185 INIT_LIST_HEAD(&net->node);
1059 INIT_LIST_HEAD(&net->devices); 1186 INIT_LIST_HEAD(&net->devices);
@@ -1163,12 +1290,16 @@ int __devinit rio_enum_mport(struct rio_mport *mport)
1163 1290
1164 /* If master port has an active link, allocate net and enum peers */ 1291 /* If master port has an active link, allocate net and enum peers */
1165 if (rio_mport_is_active(mport)) { 1292 if (rio_mport_is_active(mport)) {
1166 if (!(net = rio_alloc_net(mport))) { 1293 net = rio_alloc_net(mport, 1, 0);
1294 if (!net) {
1167 printk(KERN_ERR "RIO: failed to allocate new net\n"); 1295 printk(KERN_ERR "RIO: failed to allocate new net\n");
1168 rc = -ENOMEM; 1296 rc = -ENOMEM;
1169 goto out; 1297 goto out;
1170 } 1298 }
1171 1299
1300 /* reserve mport destID in new net */
1301 rio_destid_reserve(net, mport->host_deviceid);
1302
1172 /* Enable Input Output Port (transmitter reviever) */ 1303 /* Enable Input Output Port (transmitter reviever) */
1173 rio_enable_rx_tx_port(mport, 1, 0, 0, 0); 1304 rio_enable_rx_tx_port(mport, 1, 0, 0, 0);
1174 1305
@@ -1176,6 +1307,8 @@ int __devinit rio_enum_mport(struct rio_mport *mport)
1176 rio_local_write_config_32(mport, RIO_COMPONENT_TAG_CSR, 1307 rio_local_write_config_32(mport, RIO_COMPONENT_TAG_CSR,
1177 next_comptag++); 1308 next_comptag++);
1178 1309
1310 next_destid = rio_destid_alloc(net);
1311
1179 if (rio_enum_peer(net, mport, 0, NULL, 0) < 0) { 1312 if (rio_enum_peer(net, mport, 0, NULL, 0) < 0) {
1180 /* A higher priority host won enumeration, bail. */ 1313 /* A higher priority host won enumeration, bail. */
1181 printk(KERN_INFO 1314 printk(KERN_INFO
@@ -1185,6 +1318,8 @@ int __devinit rio_enum_mport(struct rio_mport *mport)
1185 rc = -EBUSY; 1318 rc = -EBUSY;
1186 goto out; 1319 goto out;
1187 } 1320 }
1321 /* free the last allocated destID (unused) */
1322 rio_destid_free(net, next_destid);
1188 rio_update_route_tables(net); 1323 rio_update_route_tables(net);
1189 rio_clear_locks(net); 1324 rio_clear_locks(net);
1190 rio_pw_enable(mport, 1); 1325 rio_pw_enable(mport, 1);
@@ -1265,7 +1400,7 @@ int __devinit rio_disc_mport(struct rio_mport *mport)
1265enum_done: 1400enum_done:
1266 pr_debug("RIO: ... enumeration done\n"); 1401 pr_debug("RIO: ... enumeration done\n");
1267 1402
1268 net = rio_alloc_net(mport); 1403 net = rio_alloc_net(mport, 0, 0);
1269 if (!net) { 1404 if (!net) {
1270 printk(KERN_ERR "RIO: Failed to allocate new net\n"); 1405 printk(KERN_ERR "RIO: Failed to allocate new net\n");
1271 goto bail; 1406 goto bail;