aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/misc/sgi-xp/xpc_sn2.c
diff options
context:
space:
mode:
authorDean Nelson <dcn@sgi.com>2008-07-30 01:34:11 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2008-07-30 12:41:49 -0400
commit185c3a1b4bb4353529257f97caaeaac6c695e77d (patch)
tree4978f575ab63c5d040531f685871840aedff76c7 /drivers/misc/sgi-xp/xpc_sn2.c
parentc39838ce21ca8e05857ed7f4be5d289011561905 (diff)
sgi-xp: isolate allocation of XPC's msgqueues to sn2 only
Move the allocation of XPC's msgqueues to xpc_sn2.c. 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_sn2.c')
-rw-r--r--drivers/misc/sgi-xp/xpc_sn2.c205
1 files changed, 193 insertions, 12 deletions
diff --git a/drivers/misc/sgi-xp/xpc_sn2.c b/drivers/misc/sgi-xp/xpc_sn2.c
index 01dd40ec2a89..e5dc8c44c6fb 100644
--- a/drivers/misc/sgi-xp/xpc_sn2.c
+++ b/drivers/misc/sgi-xp/xpc_sn2.c
@@ -1049,6 +1049,30 @@ xpc_process_activate_IRQ_rcvd_sn2(int n_IRQs_expected)
1049} 1049}
1050 1050
1051/* 1051/*
1052 * Guarantee that the kzalloc'd memory is cacheline aligned.
1053 */
1054static void *
1055xpc_kzalloc_cacheline_aligned_sn2(size_t size, gfp_t flags, void **base)
1056{
1057 /* see if kzalloc will give us cachline aligned memory by default */
1058 *base = kzalloc(size, flags);
1059 if (*base == NULL)
1060 return NULL;
1061
1062 if ((u64)*base == L1_CACHE_ALIGN((u64)*base))
1063 return *base;
1064
1065 kfree(*base);
1066
1067 /* nope, we'll have to do it ourselves */
1068 *base = kzalloc(size + L1_CACHE_BYTES, flags);
1069 if (*base == NULL)
1070 return NULL;
1071
1072 return (void *)L1_CACHE_ALIGN((u64)*base);
1073}
1074
1075/*
1052 * Setup the infrastructure necessary to support XPartition Communication 1076 * Setup the infrastructure necessary to support XPartition Communication
1053 * between the specified remote partition and the local one. 1077 * between the specified remote partition and the local one.
1054 */ 1078 */
@@ -1078,10 +1102,9 @@ xpc_setup_infrastructure_sn2(struct xpc_partition *part)
1078 1102
1079 /* allocate all the required GET/PUT values */ 1103 /* allocate all the required GET/PUT values */
1080 1104
1081 part_sn2->local_GPs = xpc_kzalloc_cacheline_aligned(XPC_GP_SIZE, 1105 part_sn2->local_GPs =
1082 GFP_KERNEL, 1106 xpc_kzalloc_cacheline_aligned_sn2(XPC_GP_SIZE, GFP_KERNEL,
1083 &part_sn2-> 1107 &part_sn2->local_GPs_base);
1084 local_GPs_base);
1085 if (part_sn2->local_GPs == NULL) { 1108 if (part_sn2->local_GPs == NULL) {
1086 dev_err(xpc_chan, "can't get memory for local get/put " 1109 dev_err(xpc_chan, "can't get memory for local get/put "
1087 "values\n"); 1110 "values\n");
@@ -1089,10 +1112,9 @@ xpc_setup_infrastructure_sn2(struct xpc_partition *part)
1089 goto out_1; 1112 goto out_1;
1090 } 1113 }
1091 1114
1092 part_sn2->remote_GPs = xpc_kzalloc_cacheline_aligned(XPC_GP_SIZE, 1115 part_sn2->remote_GPs =
1093 GFP_KERNEL, 1116 xpc_kzalloc_cacheline_aligned_sn2(XPC_GP_SIZE, GFP_KERNEL,
1094 &part_sn2-> 1117 &part_sn2->remote_GPs_base);
1095 remote_GPs_base);
1096 if (part_sn2->remote_GPs == NULL) { 1118 if (part_sn2->remote_GPs == NULL) {
1097 dev_err(xpc_chan, "can't get memory for remote get/put " 1119 dev_err(xpc_chan, "can't get memory for remote get/put "
1098 "values\n"); 1120 "values\n");
@@ -1105,8 +1127,9 @@ xpc_setup_infrastructure_sn2(struct xpc_partition *part)
1105 /* allocate all the required open and close args */ 1127 /* allocate all the required open and close args */
1106 1128
1107 part->local_openclose_args = 1129 part->local_openclose_args =
1108 xpc_kzalloc_cacheline_aligned(XPC_OPENCLOSE_ARGS_SIZE, GFP_KERNEL, 1130 xpc_kzalloc_cacheline_aligned_sn2(XPC_OPENCLOSE_ARGS_SIZE,
1109 &part->local_openclose_args_base); 1131 GFP_KERNEL,
1132 &part->local_openclose_args_base);
1110 if (part->local_openclose_args == NULL) { 1133 if (part->local_openclose_args == NULL) {
1111 dev_err(xpc_chan, "can't get memory for local connect args\n"); 1134 dev_err(xpc_chan, "can't get memory for local connect args\n");
1112 retval = xpNoMemory; 1135 retval = xpNoMemory;
@@ -1114,8 +1137,9 @@ xpc_setup_infrastructure_sn2(struct xpc_partition *part)
1114 } 1137 }
1115 1138
1116 part->remote_openclose_args = 1139 part->remote_openclose_args =
1117 xpc_kzalloc_cacheline_aligned(XPC_OPENCLOSE_ARGS_SIZE, GFP_KERNEL, 1140 xpc_kzalloc_cacheline_aligned_sn2(XPC_OPENCLOSE_ARGS_SIZE,
1118 &part->remote_openclose_args_base); 1141 GFP_KERNEL,
1142 &part->remote_openclose_args_base);
1119 if (part->remote_openclose_args == NULL) { 1143 if (part->remote_openclose_args == NULL) {
1120 dev_err(xpc_chan, "can't get memory for remote connect args\n"); 1144 dev_err(xpc_chan, "can't get memory for remote connect args\n");
1121 retval = xpNoMemory; 1145 retval = xpNoMemory;
@@ -1528,6 +1552,161 @@ xpc_get_chctl_all_flags_sn2(struct xpc_partition *part)
1528} 1552}
1529 1553
1530/* 1554/*
1555 * Allocate the local message queue and the notify queue.
1556 */
1557static enum xp_retval
1558xpc_allocate_local_msgqueue_sn2(struct xpc_channel *ch)
1559{
1560 unsigned long irq_flags;
1561 int nentries;
1562 size_t nbytes;
1563
1564 for (nentries = ch->local_nentries; nentries > 0; nentries--) {
1565
1566 nbytes = nentries * ch->msg_size;
1567 ch->local_msgqueue =
1568 xpc_kzalloc_cacheline_aligned_sn2(nbytes, GFP_KERNEL,
1569 &ch->local_msgqueue_base);
1570 if (ch->local_msgqueue == NULL)
1571 continue;
1572
1573 nbytes = nentries * sizeof(struct xpc_notify);
1574 ch->notify_queue = kzalloc(nbytes, GFP_KERNEL);
1575 if (ch->notify_queue == NULL) {
1576 kfree(ch->local_msgqueue_base);
1577 ch->local_msgqueue = NULL;
1578 continue;
1579 }
1580
1581 spin_lock_irqsave(&ch->lock, irq_flags);
1582 if (nentries < ch->local_nentries) {
1583 dev_dbg(xpc_chan, "nentries=%d local_nentries=%d, "
1584 "partid=%d, channel=%d\n", nentries,
1585 ch->local_nentries, ch->partid, ch->number);
1586
1587 ch->local_nentries = nentries;
1588 }
1589 spin_unlock_irqrestore(&ch->lock, irq_flags);
1590 return xpSuccess;
1591 }
1592
1593 dev_dbg(xpc_chan, "can't get memory for local message queue and notify "
1594 "queue, partid=%d, channel=%d\n", ch->partid, ch->number);
1595 return xpNoMemory;
1596}
1597
1598/*
1599 * Allocate the cached remote message queue.
1600 */
1601static enum xp_retval
1602xpc_allocate_remote_msgqueue_sn2(struct xpc_channel *ch)
1603{
1604 unsigned long irq_flags;
1605 int nentries;
1606 size_t nbytes;
1607
1608 DBUG_ON(ch->remote_nentries <= 0);
1609
1610 for (nentries = ch->remote_nentries; nentries > 0; nentries--) {
1611
1612 nbytes = nentries * ch->msg_size;
1613 ch->remote_msgqueue =
1614 xpc_kzalloc_cacheline_aligned_sn2(nbytes, GFP_KERNEL,
1615 &ch->remote_msgqueue_base);
1616 if (ch->remote_msgqueue == NULL)
1617 continue;
1618
1619 spin_lock_irqsave(&ch->lock, irq_flags);
1620 if (nentries < ch->remote_nentries) {
1621 dev_dbg(xpc_chan, "nentries=%d remote_nentries=%d, "
1622 "partid=%d, channel=%d\n", nentries,
1623 ch->remote_nentries, ch->partid, ch->number);
1624
1625 ch->remote_nentries = nentries;
1626 }
1627 spin_unlock_irqrestore(&ch->lock, irq_flags);
1628 return xpSuccess;
1629 }
1630
1631 dev_dbg(xpc_chan, "can't get memory for cached remote message queue, "
1632 "partid=%d, channel=%d\n", ch->partid, ch->number);
1633 return xpNoMemory;
1634}
1635
1636/*
1637 * Allocate message queues and other stuff associated with a channel.
1638 *
1639 * Note: Assumes all of the channel sizes are filled in.
1640 */
1641static enum xp_retval
1642xpc_allocate_msgqueues_sn2(struct xpc_channel *ch)
1643{
1644 enum xp_retval ret;
1645
1646 DBUG_ON(ch->flags & XPC_C_SETUP);
1647
1648 ret = xpc_allocate_local_msgqueue_sn2(ch);
1649 if (ret == xpSuccess) {
1650
1651 ret = xpc_allocate_remote_msgqueue_sn2(ch);
1652 if (ret != xpSuccess) {
1653 kfree(ch->local_msgqueue_base);
1654 ch->local_msgqueue = NULL;
1655 kfree(ch->notify_queue);
1656 ch->notify_queue = NULL;
1657 }
1658 }
1659 return ret;
1660}
1661
1662/*
1663 * Free up message queues and other stuff that were allocated for the specified
1664 * channel.
1665 *
1666 * Note: ch->reason and ch->reason_line are left set for debugging purposes,
1667 * they're cleared when XPC_C_DISCONNECTED is cleared.
1668 */
1669static void
1670xpc_free_msgqueues_sn2(struct xpc_channel *ch)
1671{
1672 struct xpc_channel_sn2 *ch_sn2 = &ch->sn.sn2;
1673
1674 DBUG_ON(!spin_is_locked(&ch->lock));
1675 DBUG_ON(atomic_read(&ch->n_to_notify) != 0);
1676
1677 ch->remote_msgqueue_pa = 0;
1678 ch->func = NULL;
1679 ch->key = NULL;
1680 ch->msg_size = 0;
1681 ch->local_nentries = 0;
1682 ch->remote_nentries = 0;
1683 ch->kthreads_assigned_limit = 0;
1684 ch->kthreads_idle_limit = 0;
1685
1686 ch_sn2->local_GP->get = 0;
1687 ch_sn2->local_GP->put = 0;
1688 ch_sn2->remote_GP.get = 0;
1689 ch_sn2->remote_GP.put = 0;
1690 ch_sn2->w_local_GP.get = 0;
1691 ch_sn2->w_local_GP.put = 0;
1692 ch_sn2->w_remote_GP.get = 0;
1693 ch_sn2->w_remote_GP.put = 0;
1694 ch_sn2->next_msg_to_pull = 0;
1695
1696 if (ch->flags & XPC_C_SETUP) {
1697 dev_dbg(xpc_chan, "ch->flags=0x%x, partid=%d, channel=%d\n",
1698 ch->flags, ch->partid, ch->number);
1699
1700 kfree(ch->local_msgqueue_base);
1701 ch->local_msgqueue = NULL;
1702 kfree(ch->remote_msgqueue_base);
1703 ch->remote_msgqueue = NULL;
1704 kfree(ch->notify_queue);
1705 ch->notify_queue = NULL;
1706 }
1707}
1708
1709/*
1531 * Notify those who wanted to be notified upon delivery of their message. 1710 * Notify those who wanted to be notified upon delivery of their message.
1532 */ 1711 */
1533static void 1712static void
@@ -2177,6 +2356,8 @@ xpc_init_sn2(void)
2177 xpc_teardown_infrastructure = xpc_teardown_infrastructure_sn2; 2356 xpc_teardown_infrastructure = xpc_teardown_infrastructure_sn2;
2178 xpc_make_first_contact = xpc_make_first_contact_sn2; 2357 xpc_make_first_contact = xpc_make_first_contact_sn2;
2179 xpc_get_chctl_all_flags = xpc_get_chctl_all_flags_sn2; 2358 xpc_get_chctl_all_flags = xpc_get_chctl_all_flags_sn2;
2359 xpc_allocate_msgqueues = xpc_allocate_msgqueues_sn2;
2360 xpc_free_msgqueues = xpc_free_msgqueues_sn2;
2180 xpc_notify_senders_of_disconnect = xpc_notify_senders_of_disconnect_sn2; 2361 xpc_notify_senders_of_disconnect = xpc_notify_senders_of_disconnect_sn2;
2181 xpc_process_msg_chctl_flags = xpc_process_msg_chctl_flags_sn2; 2362 xpc_process_msg_chctl_flags = xpc_process_msg_chctl_flags_sn2;
2182 xpc_n_of_deliverable_msgs = xpc_n_of_deliverable_msgs_sn2; 2363 xpc_n_of_deliverable_msgs = xpc_n_of_deliverable_msgs_sn2;