async_tx: trim dma_async_tx_descriptor in 'no channel switch' case
[safe/jmp/linux-2.6] / drivers / misc / sgi-xp / xpc_sn2.c
index 2e97576..7d71c04 100644 (file)
@@ -3,7 +3,7 @@
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
  *
- * Copyright (c) 2008 Silicon Graphics, Inc.  All Rights Reserved.
+ * Copyright (c) 2008-2009 Silicon Graphics, Inc.  All Rights Reserved.
  */
 
 /*
@@ -14,6 +14,7 @@
  */
 
 #include <linux/delay.h>
+#include <linux/slab.h>
 #include <asm/uncached.h>
 #include <asm/sn/mspec.h>
 #include <asm/sn/sn_sal.h>
@@ -60,12 +61,18 @@ static struct xpc_vars_sn2 *xpc_vars_sn2;
 static struct xpc_vars_part_sn2 *xpc_vars_part_sn2;
 
 static int
-xpc_setup_partitions_sn_sn2(void)
+xpc_setup_partitions_sn2(void)
 {
        /* nothing needs to be done */
        return 0;
 }
 
+static void
+xpc_teardown_partitions_sn2(void)
+{
+       /* nothing needs to be done */
+}
+
 /* SH_IPI_ACCESS shub register value on startup */
 static u64 xpc_sh1_IPI_access_sn2;
 static u64 xpc_sh2_IPI_access0_sn2;
@@ -273,7 +280,7 @@ xpc_check_for_sent_chctl_flags_sn2(struct xpc_partition *part)
        spin_unlock_irqrestore(&part->chctl_lock, irq_flags);
 
        dev_dbg(xpc_chan, "received notify IRQ from partid=%d, chctl.all_flags="
-               "0x%lx\n", XPC_PARTID(part), chctl.all_flags);
+               "0x%llx\n", XPC_PARTID(part), chctl.all_flags);
 
        xpc_wakeup_channel_mgr(part);
 }
@@ -425,6 +432,13 @@ xpc_send_chctl_openreply_sn2(struct xpc_channel *ch, unsigned long *irq_flags)
 }
 
 static void
+xpc_send_chctl_opencomplete_sn2(struct xpc_channel *ch,
+                               unsigned long *irq_flags)
+{
+       XPC_SEND_NOTIFY_IRQ_SN2(ch, XPC_CHCTL_OPENCOMPLETE, irq_flags);
+}
+
+static void
 xpc_send_chctl_msgrequest_sn2(struct xpc_channel *ch)
 {
        XPC_SEND_NOTIFY_IRQ_SN2(ch, XPC_CHCTL_MSGREQUEST, NULL);
@@ -436,11 +450,12 @@ xpc_send_chctl_local_msgrequest_sn2(struct xpc_channel *ch)
        XPC_SEND_LOCAL_NOTIFY_IRQ_SN2(ch, XPC_CHCTL_MSGREQUEST);
 }
 
-static void
+static enum xp_retval
 xpc_save_remote_msgqueue_pa_sn2(struct xpc_channel *ch,
                                unsigned long msgqueue_pa)
 {
        ch->sn.sn2.remote_msgqueue_pa = msgqueue_pa;
+       return xpSuccess;
 }
 
 /*
@@ -601,7 +616,8 @@ xpc_get_partition_rsvd_page_pa_sn2(void *buf, u64 *cookie, unsigned long *rp_pa,
        s64 status;
        enum xp_retval ret;
 
-       status = sn_partition_reserved_page_pa((u64)buf, cookie, rp_pa, len);
+       status = sn_partition_reserved_page_pa((u64)buf, cookie,
+                       (u64 *)rp_pa, (u64 *)len);
        if (status == SALRET_OK)
                ret = xpSuccess;
        else if (status == SALRET_MORE_PASSES)
@@ -614,7 +630,7 @@ xpc_get_partition_rsvd_page_pa_sn2(void *buf, u64 *cookie, unsigned long *rp_pa,
 
 
 static int
-xpc_setup_rsvd_page_sn_sn2(struct xpc_rsvd_page *rp)
+xpc_setup_rsvd_page_sn2(struct xpc_rsvd_page *rp)
 {
        struct amo *amos_page;
        int i;
@@ -622,7 +638,7 @@ xpc_setup_rsvd_page_sn_sn2(struct xpc_rsvd_page *rp)
 
        xpc_vars_sn2 = XPC_RP_VARS(rp);
 
-       rp->sn.vars_pa = xp_pa(xpc_vars_sn2);
+       rp->sn.sn2.vars_pa = xp_pa(xpc_vars_sn2);
 
        /* vars_part array follows immediately after vars */
        xpc_vars_part_sn2 = (struct xpc_vars_part_sn2 *)((u8 *)XPC_RP_VARS(rp) +
@@ -686,6 +702,33 @@ xpc_setup_rsvd_page_sn_sn2(struct xpc_rsvd_page *rp)
        return 0;
 }
 
+static int
+xpc_hb_allowed_sn2(short partid, void *heartbeating_to_mask)
+{
+       return test_bit(partid, heartbeating_to_mask);
+}
+
+static void
+xpc_allow_hb_sn2(short partid)
+{
+       DBUG_ON(xpc_vars_sn2 == NULL);
+       set_bit(partid, xpc_vars_sn2->heartbeating_to_mask);
+}
+
+static void
+xpc_disallow_hb_sn2(short partid)
+{
+       DBUG_ON(xpc_vars_sn2 == NULL);
+       clear_bit(partid, xpc_vars_sn2->heartbeating_to_mask);
+}
+
+static void
+xpc_disallow_all_hbs_sn2(void)
+{
+       DBUG_ON(xpc_vars_sn2 == NULL);
+       bitmap_zero(xpc_vars_sn2->heartbeating_to_mask, xp_max_npartitions);
+}
+
 static void
 xpc_increment_heartbeat_sn2(void)
 {
@@ -712,7 +755,6 @@ xpc_heartbeat_init_sn2(void)
        DBUG_ON(xpc_vars_sn2 == NULL);
 
        bitmap_zero(xpc_vars_sn2->heartbeating_to_mask, XP_MAX_NPARTITIONS_SN2);
-       xpc_heartbeating_to_mask = &xpc_vars_sn2->heartbeating_to_mask[0];
        xpc_online_heartbeat_sn2();
 }
 
@@ -737,16 +779,16 @@ xpc_get_remote_heartbeat_sn2(struct xpc_partition *part)
        if (ret != xpSuccess)
                return ret;
 
-       dev_dbg(xpc_part, "partid=%d, heartbeat=%ld, last_heartbeat=%ld, "
-               "heartbeat_offline=%ld, HB_mask[0]=0x%lx\n", XPC_PARTID(part),
+       dev_dbg(xpc_part, "partid=%d, heartbeat=%lld, last_heartbeat=%lld, "
+               "heartbeat_offline=%lld, HB_mask[0]=0x%lx\n", XPC_PARTID(part),
                remote_vars->heartbeat, part->last_heartbeat,
                remote_vars->heartbeat_offline,
                remote_vars->heartbeating_to_mask[0]);
 
        if ((remote_vars->heartbeat == part->last_heartbeat &&
-           remote_vars->heartbeat_offline == 0) ||
-           !xpc_hb_allowed(sn_partition_id,
-                           &remote_vars->heartbeating_to_mask)) {
+           !remote_vars->heartbeat_offline) ||
+           !xpc_hb_allowed_sn2(sn_partition_id,
+                               remote_vars->heartbeating_to_mask)) {
                ret = xpNoHeartbeat;
        } else {
                part->last_heartbeat = remote_vars->heartbeat;
@@ -900,7 +942,7 @@ xpc_update_partition_info_sn2(struct xpc_partition *part, u8 remote_rp_version,
                part_sn2->remote_vars_pa);
 
        part->last_heartbeat = remote_vars->heartbeat - 1;
-       dev_dbg(xpc_part, "  last_heartbeat = 0x%016lx\n",
+       dev_dbg(xpc_part, "  last_heartbeat = 0x%016llx\n",
                part->last_heartbeat);
 
        part_sn2->remote_vars_part_pa = remote_vars->vars_part_pa;
@@ -965,7 +1007,7 @@ xpc_identify_activate_IRQ_req_sn2(int nasid)
                return;
        }
 
-       remote_vars_pa = remote_rp->sn.vars_pa;
+       remote_vars_pa = remote_rp->sn.sn2.vars_pa;
        remote_rp_version = remote_rp->version;
        remote_rp_ts_jiffies = remote_rp->ts_jiffies;
 
@@ -989,7 +1031,8 @@ xpc_identify_activate_IRQ_req_sn2(int nasid)
        part->activate_IRQ_rcvd++;
 
        dev_dbg(xpc_part, "partid for nasid %d is %d; IRQs = %d; HB = "
-               "%ld:0x%lx\n", (int)nasid, (int)partid, part->activate_IRQ_rcvd,
+               "%lld:0x%lx\n", (int)nasid, (int)partid,
+               part->activate_IRQ_rcvd,
                remote_vars->heartbeat, remote_vars->heartbeating_to_mask[0]);
 
        if (xpc_partition_disengaged(part) &&
@@ -1089,7 +1132,7 @@ xpc_identify_activate_IRQ_sender_sn2(void)
                do {
                        n_IRQs_detected++;
                        nasid = (l * BITS_PER_LONG + b) * 2;
-                       dev_dbg(xpc_part, "interrupt from nasid %ld\n", nasid);
+                       dev_dbg(xpc_part, "interrupt from nasid %lld\n", nasid);
                        xpc_identify_activate_IRQ_req_sn2(nasid);
 
                        b = find_next_bit(&nasid_mask_long, BITS_PER_LONG,
@@ -1122,7 +1165,7 @@ xpc_process_activate_IRQ_rcvd_sn2(void)
  * Setup the channel structures that are sn2 specific.
  */
 static enum xp_retval
-xpc_setup_ch_structures_sn_sn2(struct xpc_partition *part)
+xpc_setup_ch_structures_sn2(struct xpc_partition *part)
 {
        struct xpc_partition_sn2 *part_sn2 = &part->sn.sn2;
        struct xpc_channel_sn2 *ch_sn2;
@@ -1244,7 +1287,7 @@ out_1:
  * Teardown the channel structures that are sn2 specific.
  */
 static void
-xpc_teardown_ch_structures_sn_sn2(struct xpc_partition *part)
+xpc_teardown_ch_structures_sn2(struct xpc_partition *part)
 {
        struct xpc_partition_sn2 *part_sn2 = &part->sn.sn2;
        short partid = XPC_PARTID(part);
@@ -1346,7 +1389,7 @@ xpc_pull_remote_vars_part_sn2(struct xpc_partition *part)
 
                if (pulled_entry->magic != 0) {
                        dev_dbg(xpc_chan, "partition %d's XPC vars_part for "
-                               "partition %d has bad magic value (=0x%lx)\n",
+                               "partition %d has bad magic value (=0x%llx)\n",
                                partid, sn_partition_id, pulled_entry->magic);
                        return xpBadMagic;
                }
@@ -1690,14 +1733,14 @@ xpc_notify_senders_sn2(struct xpc_channel *ch, enum xp_retval reason, s64 put)
 
                if (notify->func != NULL) {
                        dev_dbg(xpc_chan, "notify->func() called, notify=0x%p "
-                               "msg_number=%ld partid=%d channel=%d\n",
+                               "msg_number=%lld partid=%d channel=%d\n",
                                (void *)notify, get, ch->partid, ch->number);
 
                        notify->func(reason, ch->partid, ch->number,
                                     notify->key);
 
                        dev_dbg(xpc_chan, "notify->func() returned, notify=0x%p"
-                               " msg_number=%ld partid=%d channel=%d\n",
+                               " msg_number=%lld partid=%d channel=%d\n",
                                (void *)notify, get, ch->partid, ch->number);
                }
        }
@@ -1737,20 +1780,20 @@ xpc_clear_remote_msgqueue_flags_sn2(struct xpc_channel *ch)
 {
        struct xpc_channel_sn2 *ch_sn2 = &ch->sn.sn2;
        struct xpc_msg_sn2 *msg;
-       s64 put;
+       s64 put, remote_nentries = ch->remote_nentries;
 
        /* flags are zeroed when the buffer is allocated */
-       if (ch_sn2->remote_GP.put < ch->remote_nentries)
+       if (ch_sn2->remote_GP.put < remote_nentries)
                return;
 
-       put = max(ch_sn2->w_remote_GP.put, ch->remote_nentries);
+       put = max(ch_sn2->w_remote_GP.put, remote_nentries);
        do {
                msg = (struct xpc_msg_sn2 *)((u64)ch_sn2->remote_msgqueue +
-                                            (put % ch->remote_nentries) *
+                                            (put % remote_nentries) *
                                             ch->entry_size);
                DBUG_ON(!(msg->flags & XPC_M_SN2_READY));
                DBUG_ON(!(msg->flags & XPC_M_SN2_DONE));
-               DBUG_ON(msg->number != put - ch->remote_nentries);
+               DBUG_ON(msg->number != put - remote_nentries);
                msg->flags = 0;
        } while (++put < ch_sn2->remote_GP.put);
 }
@@ -1818,7 +1861,7 @@ xpc_process_msg_chctl_flags_sn2(struct xpc_partition *part, int ch_number)
 
                ch_sn2->w_remote_GP.get = ch_sn2->remote_GP.get;
 
-               dev_dbg(xpc_chan, "w_remote_GP.get changed to %ld, partid=%d, "
+               dev_dbg(xpc_chan, "w_remote_GP.get changed to %lld, partid=%d, "
                        "channel=%d\n", ch_sn2->w_remote_GP.get, ch->partid,
                        ch->number);
 
@@ -1845,7 +1888,7 @@ xpc_process_msg_chctl_flags_sn2(struct xpc_partition *part, int ch_number)
                smp_wmb(); /* ensure flags have been cleared before bte_copy */
                ch_sn2->w_remote_GP.put = ch_sn2->remote_GP.put;
 
-               dev_dbg(xpc_chan, "w_remote_GP.put changed to %ld, partid=%d, "
+               dev_dbg(xpc_chan, "w_remote_GP.put changed to %lld, partid=%d, "
                        "channel=%d\n", ch_sn2->w_remote_GP.put, ch->partid,
                        ch->number);
 
@@ -1903,7 +1946,7 @@ xpc_pull_remote_msg_sn2(struct xpc_channel *ch, s64 get)
                if (ret != xpSuccess) {
 
                        dev_dbg(xpc_chan, "failed to pull %d msgs starting with"
-                               " msg %ld from partition %d, channel=%d, "
+                               " msg %lld from partition %d, channel=%d, "
                                "ret=%d\n", nmsgs, ch_sn2->next_msg_to_pull,
                                ch->partid, ch->number, ret);
 
@@ -1955,7 +1998,7 @@ xpc_get_deliverable_payload_sn2(struct xpc_channel *ch)
                if (cmpxchg(&ch_sn2->w_local_GP.get, get, get + 1) == get) {
                        /* we got the entry referenced by get */
 
-                       dev_dbg(xpc_chan, "w_local_GP.get changed to %ld, "
+                       dev_dbg(xpc_chan, "w_local_GP.get changed to %lld, "
                                "partid=%d, channel=%d\n", get + 1,
                                ch->partid, ch->number);
 
@@ -2022,7 +2065,7 @@ xpc_send_msgs_sn2(struct xpc_channel *ch, s64 initial_put)
 
                /* we just set the new value of local_GP->put */
 
-               dev_dbg(xpc_chan, "local_GP->put changed to %ld, partid=%d, "
+               dev_dbg(xpc_chan, "local_GP->put changed to %lld, partid=%d, "
                        "channel=%d\n", put, ch->partid, ch->number);
 
                send_msgrequest = 1;
@@ -2107,8 +2150,8 @@ xpc_allocate_msg_sn2(struct xpc_channel *ch, u32 flags,
        DBUG_ON(msg->flags != 0);
        msg->number = put;
 
-       dev_dbg(xpc_chan, "w_local_GP.put changed to %ld; msg=0x%p, "
-               "msg_number=%ld, partid=%d, channel=%d\n", put + 1,
+       dev_dbg(xpc_chan, "w_local_GP.put changed to %lld; msg=0x%p, "
+               "msg_number=%lld, partid=%d, channel=%d\n", put + 1,
                (void *)msg, msg->number, ch->partid, ch->number);
 
        *address_of_msg = msg;
@@ -2256,7 +2299,7 @@ xpc_acknowledge_msgs_sn2(struct xpc_channel *ch, s64 initial_get, u8 msg_flags)
 
                /* we just set the new value of local_GP->get */
 
-               dev_dbg(xpc_chan, "local_GP->get changed to %ld, partid=%d, "
+               dev_dbg(xpc_chan, "local_GP->get changed to %lld, partid=%d, "
                        "channel=%d\n", get, ch->partid, ch->number);
 
                send_msgrequest = (msg_flags & XPC_M_SN2_INTERRUPT);
@@ -2283,7 +2326,7 @@ xpc_received_payload_sn2(struct xpc_channel *ch, void *payload)
        msg = container_of(payload, struct xpc_msg_sn2, payload);
        msg_number = msg->number;
 
-       dev_dbg(xpc_chan, "msg=0x%p, msg_number=%ld, partid=%d, channel=%d\n",
+       dev_dbg(xpc_chan, "msg=0x%p, msg_number=%lld, partid=%d, channel=%d\n",
                (void *)msg, msg_number, ch->partid, ch->number);
 
        DBUG_ON((((u64)msg - (u64)ch->sn.sn2.remote_msgqueue) / ch->entry_size) !=
@@ -2308,60 +2351,70 @@ xpc_received_payload_sn2(struct xpc_channel *ch, void *payload)
                xpc_acknowledge_msgs_sn2(ch, get, msg->flags);
 }
 
+static struct xpc_arch_operations xpc_arch_ops_sn2 = {
+       .setup_partitions = xpc_setup_partitions_sn2,
+       .teardown_partitions = xpc_teardown_partitions_sn2,
+       .process_activate_IRQ_rcvd = xpc_process_activate_IRQ_rcvd_sn2,
+       .get_partition_rsvd_page_pa = xpc_get_partition_rsvd_page_pa_sn2,
+       .setup_rsvd_page = xpc_setup_rsvd_page_sn2,
+
+       .allow_hb = xpc_allow_hb_sn2,
+       .disallow_hb = xpc_disallow_hb_sn2,
+       .disallow_all_hbs = xpc_disallow_all_hbs_sn2,
+       .increment_heartbeat = xpc_increment_heartbeat_sn2,
+       .offline_heartbeat = xpc_offline_heartbeat_sn2,
+       .online_heartbeat = xpc_online_heartbeat_sn2,
+       .heartbeat_init = xpc_heartbeat_init_sn2,
+       .heartbeat_exit = xpc_heartbeat_exit_sn2,
+       .get_remote_heartbeat = xpc_get_remote_heartbeat_sn2,
+
+       .request_partition_activation =
+               xpc_request_partition_activation_sn2,
+       .request_partition_reactivation =
+               xpc_request_partition_reactivation_sn2,
+       .request_partition_deactivation =
+               xpc_request_partition_deactivation_sn2,
+       .cancel_partition_deactivation_request =
+               xpc_cancel_partition_deactivation_request_sn2,
+
+       .setup_ch_structures = xpc_setup_ch_structures_sn2,
+       .teardown_ch_structures = xpc_teardown_ch_structures_sn2,
+
+       .make_first_contact = xpc_make_first_contact_sn2,
+
+       .get_chctl_all_flags = xpc_get_chctl_all_flags_sn2,
+       .send_chctl_closerequest = xpc_send_chctl_closerequest_sn2,
+       .send_chctl_closereply = xpc_send_chctl_closereply_sn2,
+       .send_chctl_openrequest = xpc_send_chctl_openrequest_sn2,
+       .send_chctl_openreply = xpc_send_chctl_openreply_sn2,
+       .send_chctl_opencomplete = xpc_send_chctl_opencomplete_sn2,
+       .process_msg_chctl_flags = xpc_process_msg_chctl_flags_sn2,
+
+       .save_remote_msgqueue_pa = xpc_save_remote_msgqueue_pa_sn2,
+
+       .setup_msg_structures = xpc_setup_msg_structures_sn2,
+       .teardown_msg_structures = xpc_teardown_msg_structures_sn2,
+
+       .indicate_partition_engaged = xpc_indicate_partition_engaged_sn2,
+       .indicate_partition_disengaged = xpc_indicate_partition_disengaged_sn2,
+       .partition_engaged = xpc_partition_engaged_sn2,
+       .any_partition_engaged = xpc_any_partition_engaged_sn2,
+       .assume_partition_disengaged = xpc_assume_partition_disengaged_sn2,
+
+       .n_of_deliverable_payloads = xpc_n_of_deliverable_payloads_sn2,
+       .send_payload = xpc_send_payload_sn2,
+       .get_deliverable_payload = xpc_get_deliverable_payload_sn2,
+       .received_payload = xpc_received_payload_sn2,
+       .notify_senders_of_disconnect = xpc_notify_senders_of_disconnect_sn2,
+};
+
 int
 xpc_init_sn2(void)
 {
        int ret;
        size_t buf_size;
 
-       xpc_setup_partitions_sn = xpc_setup_partitions_sn_sn2;
-       xpc_get_partition_rsvd_page_pa = xpc_get_partition_rsvd_page_pa_sn2;
-       xpc_setup_rsvd_page_sn = xpc_setup_rsvd_page_sn_sn2;
-       xpc_increment_heartbeat = xpc_increment_heartbeat_sn2;
-       xpc_offline_heartbeat = xpc_offline_heartbeat_sn2;
-       xpc_online_heartbeat = xpc_online_heartbeat_sn2;
-       xpc_heartbeat_init = xpc_heartbeat_init_sn2;
-       xpc_heartbeat_exit = xpc_heartbeat_exit_sn2;
-       xpc_get_remote_heartbeat = xpc_get_remote_heartbeat_sn2;
-
-       xpc_request_partition_activation = xpc_request_partition_activation_sn2;
-       xpc_request_partition_reactivation =
-           xpc_request_partition_reactivation_sn2;
-       xpc_request_partition_deactivation =
-           xpc_request_partition_deactivation_sn2;
-       xpc_cancel_partition_deactivation_request =
-           xpc_cancel_partition_deactivation_request_sn2;
-
-       xpc_process_activate_IRQ_rcvd = xpc_process_activate_IRQ_rcvd_sn2;
-       xpc_setup_ch_structures_sn = xpc_setup_ch_structures_sn_sn2;
-       xpc_teardown_ch_structures_sn = xpc_teardown_ch_structures_sn_sn2;
-       xpc_make_first_contact = xpc_make_first_contact_sn2;
-
-       xpc_get_chctl_all_flags = xpc_get_chctl_all_flags_sn2;
-       xpc_send_chctl_closerequest = xpc_send_chctl_closerequest_sn2;
-       xpc_send_chctl_closereply = xpc_send_chctl_closereply_sn2;
-       xpc_send_chctl_openrequest = xpc_send_chctl_openrequest_sn2;
-       xpc_send_chctl_openreply = xpc_send_chctl_openreply_sn2;
-
-       xpc_save_remote_msgqueue_pa = xpc_save_remote_msgqueue_pa_sn2;
-
-       xpc_setup_msg_structures = xpc_setup_msg_structures_sn2;
-       xpc_teardown_msg_structures = xpc_teardown_msg_structures_sn2;
-
-       xpc_notify_senders_of_disconnect = xpc_notify_senders_of_disconnect_sn2;
-       xpc_process_msg_chctl_flags = xpc_process_msg_chctl_flags_sn2;
-       xpc_n_of_deliverable_payloads = xpc_n_of_deliverable_payloads_sn2;
-       xpc_get_deliverable_payload = xpc_get_deliverable_payload_sn2;
-
-       xpc_indicate_partition_engaged = xpc_indicate_partition_engaged_sn2;
-       xpc_indicate_partition_disengaged =
-           xpc_indicate_partition_disengaged_sn2;
-       xpc_partition_engaged = xpc_partition_engaged_sn2;
-       xpc_any_partition_engaged = xpc_any_partition_engaged_sn2;
-       xpc_assume_partition_disengaged = xpc_assume_partition_disengaged_sn2;
-
-       xpc_send_payload = xpc_send_payload_sn2;
-       xpc_received_payload = xpc_received_payload_sn2;
+       xpc_arch_ops = xpc_arch_ops_sn2;
 
        if (offsetof(struct xpc_msg_sn2, payload) > XPC_MSG_HDR_MAX_SIZE) {
                dev_err(xpc_part, "header portion of struct xpc_msg_sn2 is "