diff options
author | Dean Nelson <dcn@sgi.com> | 2008-07-30 01:34:07 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2008-07-30 12:41:49 -0400 |
commit | 33ba3c7724be79f7cdbfc611335572c056d9a05a (patch) | |
tree | db0371c031b0bbab13ccb2aeaf015424633cf2d8 /drivers/misc/sgi-xp/xpc_channel.c | |
parent | e17d416b1bc947df68499863f13b401fb42b48f6 (diff) |
sgi-xp: isolate xpc_vars structure to sn2 only
Isolate the xpc_vars structure of XPC's reserved page to sn2 only.
Signed-off-by: Dean Nelson <dcn@sgi.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'drivers/misc/sgi-xp/xpc_channel.c')
-rw-r--r-- | drivers/misc/sgi-xp/xpc_channel.c | 315 |
1 files changed, 2 insertions, 313 deletions
diff --git a/drivers/misc/sgi-xp/xpc_channel.c b/drivers/misc/sgi-xp/xpc_channel.c index 8081e8155dff..26c5e12c1220 100644 --- a/drivers/misc/sgi-xp/xpc_channel.c +++ b/drivers/misc/sgi-xp/xpc_channel.c | |||
@@ -1165,7 +1165,7 @@ xpc_disconnect_callout(struct xpc_channel *ch, enum xp_retval reason) | |||
1165 | * Wait for a message entry to become available for the specified channel, | 1165 | * Wait for a message entry to become available for the specified channel, |
1166 | * but don't wait any longer than 1 jiffy. | 1166 | * but don't wait any longer than 1 jiffy. |
1167 | */ | 1167 | */ |
1168 | static enum xp_retval | 1168 | enum xp_retval |
1169 | xpc_allocate_msg_wait(struct xpc_channel *ch) | 1169 | xpc_allocate_msg_wait(struct xpc_channel *ch) |
1170 | { | 1170 | { |
1171 | enum xp_retval ret; | 1171 | enum xp_retval ret; |
@@ -1193,96 +1193,6 @@ xpc_allocate_msg_wait(struct xpc_channel *ch) | |||
1193 | 1193 | ||
1194 | /* | 1194 | /* |
1195 | * Allocate an entry for a message from the message queue associated with the | 1195 | * Allocate an entry for a message from the message queue associated with the |
1196 | * specified channel. | ||
1197 | */ | ||
1198 | static enum xp_retval | ||
1199 | xpc_allocate_msg(struct xpc_channel *ch, u32 flags, | ||
1200 | struct xpc_msg **address_of_msg) | ||
1201 | { | ||
1202 | struct xpc_msg *msg; | ||
1203 | enum xp_retval ret; | ||
1204 | s64 put; | ||
1205 | |||
1206 | /* this reference will be dropped in xpc_send_msg() */ | ||
1207 | xpc_msgqueue_ref(ch); | ||
1208 | |||
1209 | if (ch->flags & XPC_C_DISCONNECTING) { | ||
1210 | xpc_msgqueue_deref(ch); | ||
1211 | return ch->reason; | ||
1212 | } | ||
1213 | if (!(ch->flags & XPC_C_CONNECTED)) { | ||
1214 | xpc_msgqueue_deref(ch); | ||
1215 | return xpNotConnected; | ||
1216 | } | ||
1217 | |||
1218 | /* | ||
1219 | * Get the next available message entry from the local message queue. | ||
1220 | * If none are available, we'll make sure that we grab the latest | ||
1221 | * GP values. | ||
1222 | */ | ||
1223 | ret = xpTimeout; | ||
1224 | |||
1225 | while (1) { | ||
1226 | |||
1227 | put = ch->w_local_GP.put; | ||
1228 | rmb(); /* guarantee that .put loads before .get */ | ||
1229 | if (put - ch->w_remote_GP.get < ch->local_nentries) { | ||
1230 | |||
1231 | /* There are available message entries. We need to try | ||
1232 | * to secure one for ourselves. We'll do this by trying | ||
1233 | * to increment w_local_GP.put as long as someone else | ||
1234 | * doesn't beat us to it. If they do, we'll have to | ||
1235 | * try again. | ||
1236 | */ | ||
1237 | if (cmpxchg(&ch->w_local_GP.put, put, put + 1) == put) { | ||
1238 | /* we got the entry referenced by put */ | ||
1239 | break; | ||
1240 | } | ||
1241 | continue; /* try again */ | ||
1242 | } | ||
1243 | |||
1244 | /* | ||
1245 | * There aren't any available msg entries at this time. | ||
1246 | * | ||
1247 | * In waiting for a message entry to become available, | ||
1248 | * we set a timeout in case the other side is not | ||
1249 | * sending completion IPIs. This lets us fake an IPI | ||
1250 | * that will cause the IPI handler to fetch the latest | ||
1251 | * GP values as if an IPI was sent by the other side. | ||
1252 | */ | ||
1253 | if (ret == xpTimeout) | ||
1254 | xpc_IPI_send_local_msgrequest(ch); | ||
1255 | |||
1256 | if (flags & XPC_NOWAIT) { | ||
1257 | xpc_msgqueue_deref(ch); | ||
1258 | return xpNoWait; | ||
1259 | } | ||
1260 | |||
1261 | ret = xpc_allocate_msg_wait(ch); | ||
1262 | if (ret != xpInterrupted && ret != xpTimeout) { | ||
1263 | xpc_msgqueue_deref(ch); | ||
1264 | return ret; | ||
1265 | } | ||
1266 | } | ||
1267 | |||
1268 | /* get the message's address and initialize it */ | ||
1269 | msg = (struct xpc_msg *)((u64)ch->local_msgqueue + | ||
1270 | (put % ch->local_nentries) * ch->msg_size); | ||
1271 | |||
1272 | DBUG_ON(msg->flags != 0); | ||
1273 | msg->number = put; | ||
1274 | |||
1275 | dev_dbg(xpc_chan, "w_local_GP.put changed to %ld; msg=0x%p, " | ||
1276 | "msg_number=%ld, partid=%d, channel=%d\n", put + 1, | ||
1277 | (void *)msg, msg->number, ch->partid, ch->number); | ||
1278 | |||
1279 | *address_of_msg = msg; | ||
1280 | |||
1281 | return xpSuccess; | ||
1282 | } | ||
1283 | |||
1284 | /* | ||
1285 | * Allocate an entry for a message from the message queue associated with the | ||
1286 | * specified channel. NOTE that this routine can sleep waiting for a message | 1196 | * specified channel. NOTE that this routine can sleep waiting for a message |
1287 | * entry to become available. To not sleep, pass in the XPC_NOWAIT flag. | 1197 | * entry to become available. To not sleep, pass in the XPC_NOWAIT flag. |
1288 | * | 1198 | * |
@@ -1318,144 +1228,6 @@ xpc_initiate_allocate(short partid, int ch_number, u32 flags, void **payload) | |||
1318 | } | 1228 | } |
1319 | 1229 | ||
1320 | /* | 1230 | /* |
1321 | * Now we actually send the messages that are ready to be sent by advancing | ||
1322 | * the local message queue's Put value and then send an IPI to the recipient | ||
1323 | * partition. | ||
1324 | */ | ||
1325 | static void | ||
1326 | xpc_send_msgs(struct xpc_channel *ch, s64 initial_put) | ||
1327 | { | ||
1328 | struct xpc_msg *msg; | ||
1329 | s64 put = initial_put + 1; | ||
1330 | int send_IPI = 0; | ||
1331 | |||
1332 | while (1) { | ||
1333 | |||
1334 | while (1) { | ||
1335 | if (put == ch->w_local_GP.put) | ||
1336 | break; | ||
1337 | |||
1338 | msg = (struct xpc_msg *)((u64)ch->local_msgqueue + | ||
1339 | (put % ch->local_nentries) * | ||
1340 | ch->msg_size); | ||
1341 | |||
1342 | if (!(msg->flags & XPC_M_READY)) | ||
1343 | break; | ||
1344 | |||
1345 | put++; | ||
1346 | } | ||
1347 | |||
1348 | if (put == initial_put) { | ||
1349 | /* nothing's changed */ | ||
1350 | break; | ||
1351 | } | ||
1352 | |||
1353 | if (cmpxchg_rel(&ch->local_GP->put, initial_put, put) != | ||
1354 | initial_put) { | ||
1355 | /* someone else beat us to it */ | ||
1356 | DBUG_ON(ch->local_GP->put < initial_put); | ||
1357 | break; | ||
1358 | } | ||
1359 | |||
1360 | /* we just set the new value of local_GP->put */ | ||
1361 | |||
1362 | dev_dbg(xpc_chan, "local_GP->put changed to %ld, partid=%d, " | ||
1363 | "channel=%d\n", put, ch->partid, ch->number); | ||
1364 | |||
1365 | send_IPI = 1; | ||
1366 | |||
1367 | /* | ||
1368 | * We need to ensure that the message referenced by | ||
1369 | * local_GP->put is not XPC_M_READY or that local_GP->put | ||
1370 | * equals w_local_GP.put, so we'll go have a look. | ||
1371 | */ | ||
1372 | initial_put = put; | ||
1373 | } | ||
1374 | |||
1375 | if (send_IPI) | ||
1376 | xpc_IPI_send_msgrequest(ch); | ||
1377 | } | ||
1378 | |||
1379 | /* | ||
1380 | * Common code that does the actual sending of the message by advancing the | ||
1381 | * local message queue's Put value and sends an IPI to the partition the | ||
1382 | * message is being sent to. | ||
1383 | */ | ||
1384 | static enum xp_retval | ||
1385 | xpc_send_msg(struct xpc_channel *ch, struct xpc_msg *msg, u8 notify_type, | ||
1386 | xpc_notify_func func, void *key) | ||
1387 | { | ||
1388 | enum xp_retval ret = xpSuccess; | ||
1389 | struct xpc_notify *notify = notify; | ||
1390 | s64 put, msg_number = msg->number; | ||
1391 | |||
1392 | DBUG_ON(notify_type == XPC_N_CALL && func == NULL); | ||
1393 | DBUG_ON((((u64)msg - (u64)ch->local_msgqueue) / ch->msg_size) != | ||
1394 | msg_number % ch->local_nentries); | ||
1395 | DBUG_ON(msg->flags & XPC_M_READY); | ||
1396 | |||
1397 | if (ch->flags & XPC_C_DISCONNECTING) { | ||
1398 | /* drop the reference grabbed in xpc_allocate_msg() */ | ||
1399 | xpc_msgqueue_deref(ch); | ||
1400 | return ch->reason; | ||
1401 | } | ||
1402 | |||
1403 | if (notify_type != 0) { | ||
1404 | /* | ||
1405 | * Tell the remote side to send an ACK interrupt when the | ||
1406 | * message has been delivered. | ||
1407 | */ | ||
1408 | msg->flags |= XPC_M_INTERRUPT; | ||
1409 | |||
1410 | atomic_inc(&ch->n_to_notify); | ||
1411 | |||
1412 | notify = &ch->notify_queue[msg_number % ch->local_nentries]; | ||
1413 | notify->func = func; | ||
1414 | notify->key = key; | ||
1415 | notify->type = notify_type; | ||
1416 | |||
1417 | /* >>> is a mb() needed here? */ | ||
1418 | |||
1419 | if (ch->flags & XPC_C_DISCONNECTING) { | ||
1420 | /* | ||
1421 | * An error occurred between our last error check and | ||
1422 | * this one. We will try to clear the type field from | ||
1423 | * the notify entry. If we succeed then | ||
1424 | * xpc_disconnect_channel() didn't already process | ||
1425 | * the notify entry. | ||
1426 | */ | ||
1427 | if (cmpxchg(¬ify->type, notify_type, 0) == | ||
1428 | notify_type) { | ||
1429 | atomic_dec(&ch->n_to_notify); | ||
1430 | ret = ch->reason; | ||
1431 | } | ||
1432 | |||
1433 | /* drop the reference grabbed in xpc_allocate_msg() */ | ||
1434 | xpc_msgqueue_deref(ch); | ||
1435 | return ret; | ||
1436 | } | ||
1437 | } | ||
1438 | |||
1439 | msg->flags |= XPC_M_READY; | ||
1440 | |||
1441 | /* | ||
1442 | * The preceding store of msg->flags must occur before the following | ||
1443 | * load of ch->local_GP->put. | ||
1444 | */ | ||
1445 | mb(); | ||
1446 | |||
1447 | /* see if the message is next in line to be sent, if so send it */ | ||
1448 | |||
1449 | put = ch->local_GP->put; | ||
1450 | if (put == msg_number) | ||
1451 | xpc_send_msgs(ch, put); | ||
1452 | |||
1453 | /* drop the reference grabbed in xpc_allocate_msg() */ | ||
1454 | xpc_msgqueue_deref(ch); | ||
1455 | return ret; | ||
1456 | } | ||
1457 | |||
1458 | /* | ||
1459 | * Send a message previously allocated using xpc_initiate_allocate() on the | 1231 | * Send a message previously allocated using xpc_initiate_allocate() on the |
1460 | * specified channel connected to the specified partition. | 1232 | * specified channel connected to the specified partition. |
1461 | * | 1233 | * |
@@ -1586,66 +1358,6 @@ xpc_deliver_msg(struct xpc_channel *ch) | |||
1586 | } | 1358 | } |
1587 | 1359 | ||
1588 | /* | 1360 | /* |
1589 | * Now we actually acknowledge the messages that have been delivered and ack'd | ||
1590 | * by advancing the cached remote message queue's Get value and if requested | ||
1591 | * send an IPI to the message sender's partition. | ||
1592 | */ | ||
1593 | static void | ||
1594 | xpc_acknowledge_msgs(struct xpc_channel *ch, s64 initial_get, u8 msg_flags) | ||
1595 | { | ||
1596 | struct xpc_msg *msg; | ||
1597 | s64 get = initial_get + 1; | ||
1598 | int send_IPI = 0; | ||
1599 | |||
1600 | while (1) { | ||
1601 | |||
1602 | while (1) { | ||
1603 | if (get == ch->w_local_GP.get) | ||
1604 | break; | ||
1605 | |||
1606 | msg = (struct xpc_msg *)((u64)ch->remote_msgqueue + | ||
1607 | (get % ch->remote_nentries) * | ||
1608 | ch->msg_size); | ||
1609 | |||
1610 | if (!(msg->flags & XPC_M_DONE)) | ||
1611 | break; | ||
1612 | |||
1613 | msg_flags |= msg->flags; | ||
1614 | get++; | ||
1615 | } | ||
1616 | |||
1617 | if (get == initial_get) { | ||
1618 | /* nothing's changed */ | ||
1619 | break; | ||
1620 | } | ||
1621 | |||
1622 | if (cmpxchg_rel(&ch->local_GP->get, initial_get, get) != | ||
1623 | initial_get) { | ||
1624 | /* someone else beat us to it */ | ||
1625 | DBUG_ON(ch->local_GP->get <= initial_get); | ||
1626 | break; | ||
1627 | } | ||
1628 | |||
1629 | /* we just set the new value of local_GP->get */ | ||
1630 | |||
1631 | dev_dbg(xpc_chan, "local_GP->get changed to %ld, partid=%d, " | ||
1632 | "channel=%d\n", get, ch->partid, ch->number); | ||
1633 | |||
1634 | send_IPI = (msg_flags & XPC_M_INTERRUPT); | ||
1635 | |||
1636 | /* | ||
1637 | * We need to ensure that the message referenced by | ||
1638 | * local_GP->get is not XPC_M_DONE or that local_GP->get | ||
1639 | * equals w_local_GP.get, so we'll go have a look. | ||
1640 | */ | ||
1641 | initial_get = get; | ||
1642 | } | ||
1643 | |||
1644 | if (send_IPI) | ||
1645 | xpc_IPI_send_msgrequest(ch); | ||
1646 | } | ||
1647 | |||
1648 | /* | ||
1649 | * Acknowledge receipt of a delivered message. | 1361 | * Acknowledge receipt of a delivered message. |
1650 | * | 1362 | * |
1651 | * If a message has XPC_M_INTERRUPT set, send an interrupt to the partition | 1363 | * If a message has XPC_M_INTERRUPT set, send an interrupt to the partition |
@@ -1668,35 +1380,12 @@ xpc_initiate_received(short partid, int ch_number, void *payload) | |||
1668 | struct xpc_partition *part = &xpc_partitions[partid]; | 1380 | struct xpc_partition *part = &xpc_partitions[partid]; |
1669 | struct xpc_channel *ch; | 1381 | struct xpc_channel *ch; |
1670 | struct xpc_msg *msg = XPC_MSG_ADDRESS(payload); | 1382 | struct xpc_msg *msg = XPC_MSG_ADDRESS(payload); |
1671 | s64 get, msg_number = msg->number; | ||
1672 | 1383 | ||
1673 | DBUG_ON(partid < 0 || partid >= xp_max_npartitions); | 1384 | DBUG_ON(partid < 0 || partid >= xp_max_npartitions); |
1674 | DBUG_ON(ch_number < 0 || ch_number >= part->nchannels); | 1385 | DBUG_ON(ch_number < 0 || ch_number >= part->nchannels); |
1675 | 1386 | ||
1676 | ch = &part->channels[ch_number]; | 1387 | ch = &part->channels[ch_number]; |
1677 | 1388 | xpc_received_msg(ch, msg); | |
1678 | dev_dbg(xpc_chan, "msg=0x%p, msg_number=%ld, partid=%d, channel=%d\n", | ||
1679 | (void *)msg, msg_number, ch->partid, ch->number); | ||
1680 | |||
1681 | DBUG_ON((((u64)msg - (u64)ch->remote_msgqueue) / ch->msg_size) != | ||
1682 | msg_number % ch->remote_nentries); | ||
1683 | DBUG_ON(msg->flags & XPC_M_DONE); | ||
1684 | |||
1685 | msg->flags |= XPC_M_DONE; | ||
1686 | |||
1687 | /* | ||
1688 | * The preceding store of msg->flags must occur before the following | ||
1689 | * load of ch->local_GP->get. | ||
1690 | */ | ||
1691 | mb(); | ||
1692 | |||
1693 | /* | ||
1694 | * See if this message is next in line to be acknowledged as having | ||
1695 | * been delivered. | ||
1696 | */ | ||
1697 | get = ch->local_GP->get; | ||
1698 | if (get == msg_number) | ||
1699 | xpc_acknowledge_msgs(ch, get, msg->flags); | ||
1700 | 1389 | ||
1701 | /* the call to xpc_msgqueue_ref() was done by xpc_deliver_msg() */ | 1390 | /* the call to xpc_msgqueue_ref() was done by xpc_deliver_msg() */ |
1702 | xpc_msgqueue_deref(ch); | 1391 | xpc_msgqueue_deref(ch); |