Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 7fb5e59d authored by Dean Nelson's avatar Dean Nelson Committed by Linus Torvalds
Browse files

sgi-xp: separate chctl_flags from XPC's notify IRQ



Tie current IPI references to either XPC's notify IRQ or channel control
flags.

Signed-off-by: default avatarDean Nelson <dcn@sgi.com>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent a47d5dac
Loading
Loading
Loading
Loading
+75 −49
Original line number Original line Diff line number Diff line
@@ -186,9 +186,10 @@ struct xpc_vars_part_sn2 {
	u64 openclose_args_pa;	/* physical address of open and close args */
	u64 openclose_args_pa;	/* physical address of open and close args */
	u64 GPs_pa;		/* physical address of Get/Put values */
	u64 GPs_pa;		/* physical address of Get/Put values */


	u64 IPI_amo_pa;		/* physical address of IPI AMO_t structure */
	u64 chctl_amo_pa;	/* physical address of chctl flags' AMO_t */
	int IPI_nasid;		/* nasid of where to send IPIs */

	int IPI_phys_cpuid;	/* physical CPU ID of where to send IPIs */
	int notify_IRQ_nasid;	/* nasid of where to send notify IRQs */
	int notify_IRQ_phys_cpuid;	/* CPUID of where to send notify IRQs */


	u8 nchannels;		/* #of defined channels supported */
	u8 nchannels;		/* #of defined channels supported */


@@ -407,7 +408,7 @@ struct xpc_channel {
	atomic_t n_on_msg_allocate_wq;	/* #on msg allocation wait queue */
	atomic_t n_on_msg_allocate_wq;	/* #on msg allocation wait queue */
	wait_queue_head_t msg_allocate_wq;	/* msg allocation wait queue */
	wait_queue_head_t msg_allocate_wq;	/* msg allocation wait queue */


	u8 delayed_IPI_flags;	/* IPI flags received, but delayed */
	u8 delayed_chctl_flags;	/* chctl flags received, but delayed */
				/* action until channel disconnected */
				/* action until channel disconnected */


	/* queue of msg senders who want to be notified when msg received */
	/* queue of msg senders who want to be notified when msg received */
@@ -469,6 +470,54 @@ struct xpc_channel {
				0x00020000 /* disconnecting callout completed */
				0x00020000 /* disconnecting callout completed */
#define	XPC_C_WDISCONNECT	0x00040000  /* waiting for channel disconnect */
#define	XPC_C_WDISCONNECT	0x00040000  /* waiting for channel disconnect */


/*
 * The channel control flags (chctl) union consists of a 64-bit variable which
 * is divided up into eight bytes, ordered from right to left. Byte zero
 * pertains to channel 0, byte one to channel 1, and so on. Each channel's byte
 * can have one or more of the chctl flags set in it.
 */

union xpc_channel_ctl_flags {
	u64 all_flags;
	u8 flags[XPC_MAX_NCHANNELS];
};

/* chctl flags */
#define	XPC_CHCTL_CLOSEREQUEST	0x01
#define	XPC_CHCTL_CLOSEREPLY	0x02
#define	XPC_CHCTL_OPENREQUEST	0x04
#define	XPC_CHCTL_OPENREPLY	0x08
#define	XPC_CHCTL_MSGREQUEST	0x10

#define XPC_OPENCLOSE_CHCTL_FLAGS \
			(XPC_CHCTL_CLOSEREQUEST | XPC_CHCTL_CLOSEREPLY | \
			 XPC_CHCTL_OPENREQUEST | XPC_CHCTL_OPENREPLY)
#define XPC_MSG_CHCTL_FLAGS	XPC_CHCTL_MSGREQUEST

static inline int
xpc_any_openclose_chctl_flags_set(union xpc_channel_ctl_flags *chctl)
{
	int ch_number;

	for (ch_number = 0; ch_number < XPC_MAX_NCHANNELS; ch_number++) {
		if (chctl->flags[ch_number] & XPC_OPENCLOSE_CHCTL_FLAGS)
			return 1;
	}
	return 0;
}

static inline int
xpc_any_msg_chctl_flags_set(union xpc_channel_ctl_flags *chctl)
{
	int ch_number;

	for (ch_number = 0; ch_number < XPC_MAX_NCHANNELS; ch_number++) {
		if (chctl->flags[ch_number] & XPC_MSG_CHCTL_FLAGS)
			return 1;
	}
	return 0;
}

/*
/*
 * Manages channels on a partition basis. There is one of these structures
 * Manages channels on a partition basis. There is one of these structures
 * for each partition (a partition will never utilize the structure that
 * for each partition (a partition will never utilize the structure that
@@ -494,12 +543,12 @@ struct xpc_partition_sn2 {


	u64 remote_openclose_args_pa;	/* phys addr of remote's args */
	u64 remote_openclose_args_pa;	/* phys addr of remote's args */


	int remote_IPI_nasid;	/* nasid of where to send IPIs */
	int notify_IRQ_nasid;	/* nasid of where to send notify IRQs */
	int remote_IPI_phys_cpuid;	/* phys CPU ID of where to send IPIs */
	int notify_IRQ_phys_cpuid;	/* CPUID of where to send notify IRQs */
	char IPI_owner[8];	/* IPI owner's name */
	char notify_IRQ_owner[8];	/* notify IRQ's owner's name */


	AMO_t *remote_IPI_amo_va;    /* address of remote IPI AMO_t structure */
	AMO_t *remote_chctl_amo_va; /* address of remote chctl flags' AMO_t */
	AMO_t *local_IPI_amo_va;	/* address of IPI AMO_t structure */
	AMO_t *local_chctl_amo_va;	/* address of chctl flags' AMO_t */


	struct timer_list dropped_notify_IRQ_timer;	/* dropped IRQ timer */
	struct timer_list dropped_notify_IRQ_timer;	/* dropped IRQ timer */
};
};
@@ -536,7 +585,10 @@ struct xpc_partition {
	atomic_t nchannels_engaged;  /* #of channels engaged with remote part */
	atomic_t nchannels_engaged;  /* #of channels engaged with remote part */
	struct xpc_channel *channels;	/* array of channel structures */
	struct xpc_channel *channels;	/* array of channel structures */


	/* fields used to pass args when opening or closing a channel */
	/* fields used for managing channel avialability and activity */

	union xpc_channel_ctl_flags chctl; /* chctl flags yet to be processed */
	spinlock_t chctl_lock;	/* chctl flags lock */


	void *local_openclose_args_base;   /* base address of kmalloc'd space */
	void *local_openclose_args_base;   /* base address of kmalloc'd space */
	struct xpc_openclose_args *local_openclose_args;      /* local's args */
	struct xpc_openclose_args *local_openclose_args;      /* local's args */
@@ -544,11 +596,6 @@ struct xpc_partition {
	struct xpc_openclose_args *remote_openclose_args; /* copy of remote's */
	struct xpc_openclose_args *remote_openclose_args; /* copy of remote's */
							  /* args */
							  /* args */


	/* IPI sending, receiving and handling related fields */

	u64 local_IPI_amo;	/* IPI amo flags yet to be handled */
	spinlock_t IPI_lock;	/* IPI handler lock */

	/* channel manager related fields */
	/* channel manager related fields */


	atomic_t channel_mgr_requests;	/* #of requests to activate chan mgr */
	atomic_t channel_mgr_requests;	/* #of requests to activate chan mgr */
@@ -580,11 +627,12 @@ struct xpc_partition {
#define XPC_P_TORNDOWN		0x03	/* infrastructure is torndown */
#define XPC_P_TORNDOWN		0x03	/* infrastructure is torndown */


/*
/*
 * struct xpc_partition IPI_timer #of seconds to wait before checking for
 * struct xpc_partition_sn2's dropped notify IRQ timer is set to wait the
 * dropped IPIs. These occur whenever an IPI amo write doesn't complete until
 * following interval #of seconds before checking for dropped notify IRQs.
 * after the IPI was received.
 * These can occur whenever an IRQ's associated amo write doesn't complete
 * until after the IRQ was received.
 */
 */
#define XPC_P_DROPPED_IPI_WAIT_INTERVAL	(0.25 * HZ)
#define XPC_DROPPED_NOTIFY_IRQ_WAIT_INTERVAL	(0.25 * HZ)


/* number of seconds to wait for other partitions to disengage */
/* number of seconds to wait for other partitions to disengage */
#define XPC_DISENGAGE_DEFAULT_TIMELIMIT		90
#define XPC_DISENGAGE_DEFAULT_TIMELIMIT		90
@@ -617,9 +665,9 @@ extern void (*xpc_offline_heartbeat) (void);
extern void (*xpc_online_heartbeat) (void);
extern void (*xpc_online_heartbeat) (void);
extern void (*xpc_check_remote_hb) (void);
extern void (*xpc_check_remote_hb) (void);
extern enum xp_retval (*xpc_make_first_contact) (struct xpc_partition *);
extern enum xp_retval (*xpc_make_first_contact) (struct xpc_partition *);
extern u64 (*xpc_get_IPI_flags) (struct xpc_partition *);
extern u64 (*xpc_get_chctl_all_flags) (struct xpc_partition *);
extern void (*xpc_notify_senders_of_disconnect) (struct xpc_channel *);
extern void (*xpc_notify_senders_of_disconnect) (struct xpc_channel *);
extern void (*xpc_process_msg_IPI) (struct xpc_partition *, int);
extern void (*xpc_process_msg_chctl_flags) (struct xpc_partition *, int);
extern int (*xpc_n_of_deliverable_msgs) (struct xpc_channel *);
extern int (*xpc_n_of_deliverable_msgs) (struct xpc_channel *);
extern struct xpc_msg *(*xpc_get_deliverable_msg) (struct xpc_channel *);
extern struct xpc_msg *(*xpc_get_deliverable_msg) (struct xpc_channel *);
extern void (*xpc_request_partition_activation) (struct xpc_rsvd_page *, u64,
extern void (*xpc_request_partition_activation) (struct xpc_rsvd_page *, u64,
@@ -638,14 +686,13 @@ extern int (*xpc_any_partition_engaged) (void);
extern void (*xpc_indicate_partition_disengaged) (struct xpc_partition *);
extern void (*xpc_indicate_partition_disengaged) (struct xpc_partition *);
extern void (*xpc_assume_partition_disengaged) (short);
extern void (*xpc_assume_partition_disengaged) (short);


extern void (*xpc_send_channel_closerequest) (struct xpc_channel *,
extern void (*xpc_send_chctl_closerequest) (struct xpc_channel *,
					    unsigned long *);
					    unsigned long *);
extern void (*xpc_send_channel_closereply) (struct xpc_channel *,
extern void (*xpc_send_chctl_closereply) (struct xpc_channel *,
					  unsigned long *);
					  unsigned long *);
extern void (*xpc_send_channel_openrequest) (struct xpc_channel *,
extern void (*xpc_send_chctl_openrequest) (struct xpc_channel *,
					     unsigned long *);
extern void (*xpc_send_channel_openreply) (struct xpc_channel *,
					   unsigned long *);
					   unsigned long *);
extern void (*xpc_send_chctl_openreply) (struct xpc_channel *, unsigned long *);


extern enum xp_retval (*xpc_send_msg) (struct xpc_channel *, u32, void *, u16,
extern enum xp_retval (*xpc_send_msg) (struct xpc_channel *, u32, void *, u16,
				       u8, xpc_notify_func, void *);
				       u8, xpc_notify_func, void *);
@@ -689,7 +736,7 @@ extern enum xp_retval xpc_initiate_send(short, int, u32, void *, u16);
extern enum xp_retval xpc_initiate_send_notify(short, int, u32, void *, u16,
extern enum xp_retval xpc_initiate_send_notify(short, int, u32, void *, u16,
					       xpc_notify_func, void *);
					       xpc_notify_func, void *);
extern void xpc_initiate_received(short, int, void *);
extern void xpc_initiate_received(short, int, void *);
extern void xpc_process_channel_activity(struct xpc_partition *);
extern void xpc_process_sent_chctl_flags(struct xpc_partition *);
extern void xpc_connected_callout(struct xpc_channel *);
extern void xpc_connected_callout(struct xpc_channel *);
extern void xpc_deliver_msg(struct xpc_channel *);
extern void xpc_deliver_msg(struct xpc_channel *);
extern void xpc_disconnect_channel(const int, struct xpc_channel *,
extern void xpc_disconnect_channel(const int, struct xpc_channel *,
@@ -799,25 +846,4 @@ xpc_part_ref(struct xpc_partition *part)
		(_p)->reason_line = _line; \
		(_p)->reason_line = _line; \
	}
	}


/*
 * The sending and receiving of IPIs includes the setting of an >>>AMO variable
 * to indicate the reason the IPI was sent. The 64-bit variable is divided
 * up into eight bytes, ordered from right to left. Byte zero pertains to
 * channel 0, byte one to channel 1, and so on. Each byte is described by
 * the following IPI flags.
 */

#define	XPC_IPI_CLOSEREQUEST	0x01
#define	XPC_IPI_CLOSEREPLY	0x02
#define	XPC_IPI_OPENREQUEST	0x04
#define	XPC_IPI_OPENREPLY	0x08
#define	XPC_IPI_MSGREQUEST	0x10

/* given an >>>AMO variable and a channel#, get its associated IPI flags */
#define XPC_GET_IPI_FLAGS(_amo, _c)	((u8) (((_amo) >> ((_c) * 8)) & 0xff))
#define XPC_SET_IPI_FLAGS(_amo, _c, _f)	(_amo) |= ((u64) (_f) << ((_c) * 8))

#define	XPC_ANY_OPENCLOSE_IPI_FLAGS_SET(_amo) ((_amo) & 0x0f0f0f0f0f0f0f0fUL)
#define XPC_ANY_MSG_IPI_FLAGS_SET(_amo)       ((_amo) & 0x1010101010101010UL)

#endif /* _DRIVERS_MISC_SGIXP_XPC_H */
#endif /* _DRIVERS_MISC_SGIXP_XPC_H */
+66 −69
Original line number Original line Diff line number Diff line
@@ -201,7 +201,7 @@ xpc_process_connect(struct xpc_channel *ch, unsigned long *irq_flags)


	if (!(ch->flags & XPC_C_OPENREPLY)) {
	if (!(ch->flags & XPC_C_OPENREPLY)) {
		ch->flags |= XPC_C_OPENREPLY;
		ch->flags |= XPC_C_OPENREPLY;
		xpc_send_channel_openreply(ch, irq_flags);
		xpc_send_chctl_openreply(ch, irq_flags);
	}
	}


	if (!(ch->flags & XPC_C_ROPENREPLY))
	if (!(ch->flags & XPC_C_ROPENREPLY))
@@ -307,7 +307,7 @@ xpc_process_disconnect(struct xpc_channel *ch, unsigned long *irq_flags)


		if (!(ch->flags & XPC_C_CLOSEREPLY)) {
		if (!(ch->flags & XPC_C_CLOSEREPLY)) {
			ch->flags |= XPC_C_CLOSEREPLY;
			ch->flags |= XPC_C_CLOSEREPLY;
			xpc_send_channel_closereply(ch, irq_flags);
			xpc_send_chctl_closereply(ch, irq_flags);
		}
		}


		if (!(ch->flags & XPC_C_RCLOSEREPLY))
		if (!(ch->flags & XPC_C_RCLOSEREPLY))
@@ -344,15 +344,15 @@ xpc_process_disconnect(struct xpc_channel *ch, unsigned long *irq_flags)
	if (ch->flags & XPC_C_WDISCONNECT) {
	if (ch->flags & XPC_C_WDISCONNECT) {
		/* we won't lose the CPU since we're holding ch->lock */
		/* we won't lose the CPU since we're holding ch->lock */
		complete(&ch->wdisconnect_wait);
		complete(&ch->wdisconnect_wait);
	} else if (ch->delayed_IPI_flags) {
	} else if (ch->delayed_chctl_flags) {
		if (part->act_state != XPC_P_DEACTIVATING) {
		if (part->act_state != XPC_P_DEACTIVATING) {
			/* time to take action on any delayed IPI flags */
			/* time to take action on any delayed chctl flags */
			spin_lock(&part->IPI_lock);
			spin_lock(&part->chctl_lock);
			XPC_SET_IPI_FLAGS(part->local_IPI_amo, ch->number,
			part->chctl.flags[ch->number] |=
					  ch->delayed_IPI_flags);
			    ch->delayed_chctl_flags;
			spin_unlock(&part->IPI_lock);
			spin_unlock(&part->chctl_lock);
		}
		}
		ch->delayed_IPI_flags = 0;
		ch->delayed_chctl_flags = 0;
	}
	}
}
}


@@ -360,8 +360,8 @@ xpc_process_disconnect(struct xpc_channel *ch, unsigned long *irq_flags)
 * Process a change in the channel's remote connection state.
 * Process a change in the channel's remote connection state.
 */
 */
static void
static void
xpc_process_openclose_IPI(struct xpc_partition *part, int ch_number,
xpc_process_openclose_chctl_flags(struct xpc_partition *part, int ch_number,
			  u8 IPI_flags)
				  u8 chctl_flags)
{
{
	unsigned long irq_flags;
	unsigned long irq_flags;
	struct xpc_openclose_args *args =
	struct xpc_openclose_args *args =
@@ -376,24 +376,24 @@ xpc_process_openclose_IPI(struct xpc_partition *part, int ch_number,
	if ((ch->flags & XPC_C_DISCONNECTED) &&
	if ((ch->flags & XPC_C_DISCONNECTED) &&
	    (ch->flags & XPC_C_WDISCONNECT)) {
	    (ch->flags & XPC_C_WDISCONNECT)) {
		/*
		/*
		 * Delay processing IPI flags until thread waiting disconnect
		 * Delay processing chctl flags until thread waiting disconnect
		 * has had a chance to see that the channel is disconnected.
		 * has had a chance to see that the channel is disconnected.
		 */
		 */
		ch->delayed_IPI_flags |= IPI_flags;
		ch->delayed_chctl_flags |= chctl_flags;
		spin_unlock_irqrestore(&ch->lock, irq_flags);
		spin_unlock_irqrestore(&ch->lock, irq_flags);
		return;
		return;
	}
	}


	if (IPI_flags & XPC_IPI_CLOSEREQUEST) {
	if (chctl_flags & XPC_CHCTL_CLOSEREQUEST) {


		dev_dbg(xpc_chan, "XPC_IPI_CLOSEREQUEST (reason=%d) received "
		dev_dbg(xpc_chan, "XPC_CHCTL_CLOSEREQUEST (reason=%d) received "
			"from partid=%d, channel=%d\n", args->reason,
			"from partid=%d, channel=%d\n", args->reason,
			ch->partid, ch->number);
			ch->partid, ch->number);


		/*
		/*
		 * If RCLOSEREQUEST is set, we're probably waiting for
		 * If RCLOSEREQUEST is set, we're probably waiting for
		 * RCLOSEREPLY. We should find it and a ROPENREQUEST packed
		 * RCLOSEREPLY. We should find it and a ROPENREQUEST packed
		 * with this RCLOSEREQUEST in the IPI_flags.
		 * with this RCLOSEREQUEST in the chctl_flags.
		 */
		 */


		if (ch->flags & XPC_C_RCLOSEREQUEST) {
		if (ch->flags & XPC_C_RCLOSEREQUEST) {
@@ -402,8 +402,8 @@ xpc_process_openclose_IPI(struct xpc_partition *part, int ch_number,
			DBUG_ON(!(ch->flags & XPC_C_CLOSEREPLY));
			DBUG_ON(!(ch->flags & XPC_C_CLOSEREPLY));
			DBUG_ON(ch->flags & XPC_C_RCLOSEREPLY);
			DBUG_ON(ch->flags & XPC_C_RCLOSEREPLY);


			DBUG_ON(!(IPI_flags & XPC_IPI_CLOSEREPLY));
			DBUG_ON(!(chctl_flags & XPC_CHCTL_CLOSEREPLY));
			IPI_flags &= ~XPC_IPI_CLOSEREPLY;
			chctl_flags &= ~XPC_CHCTL_CLOSEREPLY;
			ch->flags |= XPC_C_RCLOSEREPLY;
			ch->flags |= XPC_C_RCLOSEREPLY;


			/* both sides have finished disconnecting */
			/* both sides have finished disconnecting */
@@ -413,17 +413,15 @@ xpc_process_openclose_IPI(struct xpc_partition *part, int ch_number,
		}
		}


		if (ch->flags & XPC_C_DISCONNECTED) {
		if (ch->flags & XPC_C_DISCONNECTED) {
			if (!(IPI_flags & XPC_IPI_OPENREQUEST)) {
			if (!(chctl_flags & XPC_CHCTL_OPENREQUEST)) {
				if ((XPC_GET_IPI_FLAGS(part->local_IPI_amo,
				if (part->chctl.flags[ch_number] &
						       ch_number) &
				    XPC_CHCTL_OPENREQUEST) {
				     XPC_IPI_OPENREQUEST)) {


					DBUG_ON(ch->delayed_chctl_flags != 0);
					DBUG_ON(ch->delayed_IPI_flags != 0);
					spin_lock(&part->chctl_lock);
					spin_lock(&part->IPI_lock);
					part->chctl.flags[ch_number] |=
					XPC_SET_IPI_FLAGS(part->local_IPI_amo,
					    XPC_CHCTL_CLOSEREQUEST;
							  ch_number,
					spin_unlock(&part->chctl_lock);
							  XPC_IPI_CLOSEREQUEST);
					spin_unlock(&part->IPI_lock);
				}
				}
				spin_unlock_irqrestore(&ch->lock, irq_flags);
				spin_unlock_irqrestore(&ch->lock, irq_flags);
				return;
				return;
@@ -436,7 +434,7 @@ xpc_process_openclose_IPI(struct xpc_partition *part, int ch_number,
			ch->flags |= (XPC_C_CONNECTING | XPC_C_ROPENREQUEST);
			ch->flags |= (XPC_C_CONNECTING | XPC_C_ROPENREQUEST);
		}
		}


		IPI_flags &= ~(XPC_IPI_OPENREQUEST | XPC_IPI_OPENREPLY);
		chctl_flags &= ~(XPC_CHCTL_OPENREQUEST | XPC_CHCTL_OPENREPLY);


		/*
		/*
		 * The meaningful CLOSEREQUEST connection state fields are:
		 * The meaningful CLOSEREQUEST connection state fields are:
@@ -454,7 +452,7 @@ xpc_process_openclose_IPI(struct xpc_partition *part, int ch_number,


			XPC_DISCONNECT_CHANNEL(ch, reason, &irq_flags);
			XPC_DISCONNECT_CHANNEL(ch, reason, &irq_flags);


			DBUG_ON(IPI_flags & XPC_IPI_CLOSEREPLY);
			DBUG_ON(chctl_flags & XPC_CHCTL_CLOSEREPLY);
			spin_unlock_irqrestore(&ch->lock, irq_flags);
			spin_unlock_irqrestore(&ch->lock, irq_flags);
			return;
			return;
		}
		}
@@ -462,10 +460,10 @@ xpc_process_openclose_IPI(struct xpc_partition *part, int ch_number,
		xpc_process_disconnect(ch, &irq_flags);
		xpc_process_disconnect(ch, &irq_flags);
	}
	}


	if (IPI_flags & XPC_IPI_CLOSEREPLY) {
	if (chctl_flags & XPC_CHCTL_CLOSEREPLY) {


		dev_dbg(xpc_chan, "XPC_IPI_CLOSEREPLY received from partid=%d,"
		dev_dbg(xpc_chan, "XPC_CHCTL_CLOSEREPLY received from partid="
			" channel=%d\n", ch->partid, ch->number);
			"%d, channel=%d\n", ch->partid, ch->number);


		if (ch->flags & XPC_C_DISCONNECTED) {
		if (ch->flags & XPC_C_DISCONNECTED) {
			DBUG_ON(part->act_state != XPC_P_DEACTIVATING);
			DBUG_ON(part->act_state != XPC_P_DEACTIVATING);
@@ -476,15 +474,14 @@ xpc_process_openclose_IPI(struct xpc_partition *part, int ch_number,
		DBUG_ON(!(ch->flags & XPC_C_CLOSEREQUEST));
		DBUG_ON(!(ch->flags & XPC_C_CLOSEREQUEST));


		if (!(ch->flags & XPC_C_RCLOSEREQUEST)) {
		if (!(ch->flags & XPC_C_RCLOSEREQUEST)) {
			if ((XPC_GET_IPI_FLAGS(part->local_IPI_amo, ch_number)
			if (part->chctl.flags[ch_number] &
			     & XPC_IPI_CLOSEREQUEST)) {
			    XPC_CHCTL_CLOSEREQUEST) {


				DBUG_ON(ch->delayed_IPI_flags != 0);
				DBUG_ON(ch->delayed_chctl_flags != 0);
				spin_lock(&part->IPI_lock);
				spin_lock(&part->chctl_lock);
				XPC_SET_IPI_FLAGS(part->local_IPI_amo,
				part->chctl.flags[ch_number] |=
						  ch_number,
				    XPC_CHCTL_CLOSEREPLY;
						  XPC_IPI_CLOSEREPLY);
				spin_unlock(&part->chctl_lock);
				spin_unlock(&part->IPI_lock);
			}
			}
			spin_unlock_irqrestore(&ch->lock, irq_flags);
			spin_unlock_irqrestore(&ch->lock, irq_flags);
			return;
			return;
@@ -498,9 +495,9 @@ xpc_process_openclose_IPI(struct xpc_partition *part, int ch_number,
		}
		}
	}
	}


	if (IPI_flags & XPC_IPI_OPENREQUEST) {
	if (chctl_flags & XPC_CHCTL_OPENREQUEST) {


		dev_dbg(xpc_chan, "XPC_IPI_OPENREQUEST (msg_size=%d, "
		dev_dbg(xpc_chan, "XPC_CHCTL_OPENREQUEST (msg_size=%d, "
			"local_nentries=%d) received from partid=%d, "
			"local_nentries=%d) received from partid=%d, "
			"channel=%d\n", args->msg_size, args->local_nentries,
			"channel=%d\n", args->msg_size, args->local_nentries,
			ch->partid, ch->number);
			ch->partid, ch->number);
@@ -512,7 +509,7 @@ xpc_process_openclose_IPI(struct xpc_partition *part, int ch_number,
		}
		}


		if (ch->flags & (XPC_C_DISCONNECTING | XPC_C_WDISCONNECT)) {
		if (ch->flags & (XPC_C_DISCONNECTING | XPC_C_WDISCONNECT)) {
			ch->delayed_IPI_flags |= XPC_IPI_OPENREQUEST;
			ch->delayed_chctl_flags |= XPC_CHCTL_OPENREQUEST;
			spin_unlock_irqrestore(&ch->lock, irq_flags);
			spin_unlock_irqrestore(&ch->lock, irq_flags);
			return;
			return;
		}
		}
@@ -554,13 +551,13 @@ xpc_process_openclose_IPI(struct xpc_partition *part, int ch_number,
		xpc_process_connect(ch, &irq_flags);
		xpc_process_connect(ch, &irq_flags);
	}
	}


	if (IPI_flags & XPC_IPI_OPENREPLY) {
	if (chctl_flags & XPC_CHCTL_OPENREPLY) {


		dev_dbg(xpc_chan, "XPC_IPI_OPENREPLY (local_msgqueue_pa=0x%lx, "
		dev_dbg(xpc_chan, "XPC_CHCTL_OPENREPLY (local_msgqueue_pa="
			"local_nentries=%d, remote_nentries=%d) received from "
			"0x%lx, local_nentries=%d, remote_nentries=%d) "
			"partid=%d, channel=%d\n", args->local_msgqueue_pa,
			"received from partid=%d, channel=%d\n",
			args->local_nentries, args->remote_nentries,
			args->local_msgqueue_pa, args->local_nentries,
			ch->partid, ch->number);
			args->remote_nentries, ch->partid, ch->number);


		if (ch->flags & (XPC_C_DISCONNECTING | XPC_C_DISCONNECTED)) {
		if (ch->flags & (XPC_C_DISCONNECTING | XPC_C_DISCONNECTED)) {
			spin_unlock_irqrestore(&ch->lock, irq_flags);
			spin_unlock_irqrestore(&ch->lock, irq_flags);
@@ -591,7 +588,7 @@ xpc_process_openclose_IPI(struct xpc_partition *part, int ch_number,
		ch->remote_msgqueue_pa = args->local_msgqueue_pa;
		ch->remote_msgqueue_pa = args->local_msgqueue_pa;


		if (args->local_nentries < ch->remote_nentries) {
		if (args->local_nentries < ch->remote_nentries) {
			dev_dbg(xpc_chan, "XPC_IPI_OPENREPLY: new "
			dev_dbg(xpc_chan, "XPC_CHCTL_OPENREPLY: new "
				"remote_nentries=%d, old remote_nentries=%d, "
				"remote_nentries=%d, old remote_nentries=%d, "
				"partid=%d, channel=%d\n",
				"partid=%d, channel=%d\n",
				args->local_nentries, ch->remote_nentries,
				args->local_nentries, ch->remote_nentries,
@@ -600,7 +597,7 @@ xpc_process_openclose_IPI(struct xpc_partition *part, int ch_number,
			ch->remote_nentries = args->local_nentries;
			ch->remote_nentries = args->local_nentries;
		}
		}
		if (args->remote_nentries < ch->local_nentries) {
		if (args->remote_nentries < ch->local_nentries) {
			dev_dbg(xpc_chan, "XPC_IPI_OPENREPLY: new "
			dev_dbg(xpc_chan, "XPC_CHCTL_OPENREPLY: new "
				"local_nentries=%d, old local_nentries=%d, "
				"local_nentries=%d, old local_nentries=%d, "
				"partid=%d, channel=%d\n",
				"partid=%d, channel=%d\n",
				args->remote_nentries, ch->local_nentries,
				args->remote_nentries, ch->local_nentries,
@@ -690,7 +687,7 @@ xpc_connect_channel(struct xpc_channel *ch)
	/* initiate the connection */
	/* initiate the connection */


	ch->flags |= (XPC_C_OPENREQUEST | XPC_C_CONNECTING);
	ch->flags |= (XPC_C_OPENREQUEST | XPC_C_CONNECTING);
	xpc_send_channel_openrequest(ch, &irq_flags);
	xpc_send_chctl_openrequest(ch, &irq_flags);


	xpc_process_connect(ch, &irq_flags);
	xpc_process_connect(ch, &irq_flags);


@@ -700,15 +697,15 @@ xpc_connect_channel(struct xpc_channel *ch)
}
}


void
void
xpc_process_channel_activity(struct xpc_partition *part)
xpc_process_sent_chctl_flags(struct xpc_partition *part)
{
{
	unsigned long irq_flags;
	unsigned long irq_flags;
	u64 IPI_amo, IPI_flags;
	union xpc_channel_ctl_flags chctl;
	struct xpc_channel *ch;
	struct xpc_channel *ch;
	int ch_number;
	int ch_number;
	u32 ch_flags;
	u32 ch_flags;


	IPI_amo = xpc_get_IPI_flags(part);
	chctl.all_flags = xpc_get_chctl_all_flags(part);


	/*
	/*
	 * Initiate channel connections for registered channels.
	 * Initiate channel connections for registered channels.
@@ -721,14 +718,14 @@ xpc_process_channel_activity(struct xpc_partition *part)
		ch = &part->channels[ch_number];
		ch = &part->channels[ch_number];


		/*
		/*
		 * Process any open or close related IPI flags, and then deal
		 * Process any open or close related chctl flags, and then deal
		 * with connecting or disconnecting the channel as required.
		 * with connecting or disconnecting the channel as required.
		 */
		 */


		IPI_flags = XPC_GET_IPI_FLAGS(IPI_amo, ch_number);
		if (chctl.flags[ch_number] & XPC_OPENCLOSE_CHCTL_FLAGS) {

			xpc_process_openclose_chctl_flags(part, ch_number,
		if (XPC_ANY_OPENCLOSE_IPI_FLAGS_SET(IPI_flags))
							chctl.flags[ch_number]);
			xpc_process_openclose_IPI(part, ch_number, IPI_flags);
		}


		ch_flags = ch->flags;	/* need an atomic snapshot of flags */
		ch_flags = ch->flags;	/* need an atomic snapshot of flags */


@@ -755,13 +752,13 @@ xpc_process_channel_activity(struct xpc_partition *part)
		}
		}


		/*
		/*
		 * Process any message related IPI flags, this may involve the
		 * Process any message related chctl flags, this may involve
		 * activation of kthreads to deliver any pending messages sent
		 * the activation of kthreads to deliver any pending messages
		 * from the other partition.
		 * sent from the other partition.
		 */
		 */


		if (XPC_ANY_MSG_IPI_FLAGS_SET(IPI_flags))
		if (chctl.flags[ch_number] & XPC_MSG_CHCTL_FLAGS)
			xpc_process_msg_IPI(part, ch_number);
			xpc_process_msg_chctl_flags(part, ch_number);
	}
	}
}
}


@@ -937,7 +934,7 @@ xpc_disconnect_channel(const int line, struct xpc_channel *ch,
		       XPC_C_ROPENREQUEST | XPC_C_ROPENREPLY |
		       XPC_C_ROPENREQUEST | XPC_C_ROPENREPLY |
		       XPC_C_CONNECTING | XPC_C_CONNECTED);
		       XPC_C_CONNECTING | XPC_C_CONNECTED);


	xpc_send_channel_closerequest(ch, irq_flags);
	xpc_send_chctl_closerequest(ch, irq_flags);


	if (channel_was_connected)
	if (channel_was_connected)
		ch->flags |= XPC_C_WASCONNECTED;
		ch->flags |= XPC_C_WASCONNECTED;
+29 −30
Original line number Original line Diff line number Diff line
@@ -25,18 +25,18 @@
 *
 *
 *	Caveats:
 *	Caveats:
 *
 *
 *	  . We currently have no way to determine which nasid an IPI came
 *	  . Currently on sn2, we have no way to determine which nasid an IRQ
 *	    from. Thus, >>> xpc_IPI_send() does a remote AMO write followed by
 *	    came from. Thus, xpc_send_IRQ_sn2() does a remote AMO write
 *	    an IPI. The AMO indicates where data is to be pulled from, so
 *	    followed by an IPI. The AMO indicates where data is to be pulled
 *	    after the IPI arrives, the remote partition checks the AMO word.
 *	    from, so after the IPI arrives, the remote partition checks the AMO
 *	    The IPI can actually arrive before the AMO however, so other code
 *	    word. The IPI can actually arrive before the AMO however, so other
 *	    must periodically check for this case. Also, remote AMO operations
 *	    code must periodically check for this case. Also, remote AMO
 *	    do not reliably time out. Thus we do a remote PIO read solely to
 *	    operations do not reliably time out. Thus we do a remote PIO read
 *	    know whether the remote partition is down and whether we should
 *	    solely to know whether the remote partition is down and whether we
 *	    stop sending IPIs to it. This remote PIO read operation is set up
 *	    should stop sending IPIs to it. This remote PIO read operation is
 *	    in a special nofault region so SAL knows to ignore (and cleanup)
 *	    set up in a special nofault region so SAL knows to ignore (and
 *	    any errors due to the remote AMO write, PIO read, and/or PIO
 *	    cleanup) any errors due to the remote AMO write, PIO read, and/or
 *	    write operations.
 *	    PIO write operations.
 *
 *
 *	    If/when new hardware solves this IPI problem, we should abandon
 *	    If/when new hardware solves this IPI problem, we should abandon
 *	    the current approach.
 *	    the current approach.
@@ -185,8 +185,8 @@ void (*xpc_check_remote_hb) (void);


enum xp_retval (*xpc_make_first_contact) (struct xpc_partition *part);
enum xp_retval (*xpc_make_first_contact) (struct xpc_partition *part);
void (*xpc_notify_senders_of_disconnect) (struct xpc_channel *ch);
void (*xpc_notify_senders_of_disconnect) (struct xpc_channel *ch);
u64 (*xpc_get_IPI_flags) (struct xpc_partition *part);
u64 (*xpc_get_chctl_all_flags) (struct xpc_partition *part);
void (*xpc_process_msg_IPI) (struct xpc_partition *part, int ch_number);
void (*xpc_process_msg_chctl_flags) (struct xpc_partition *part, int ch_number);
int (*xpc_n_of_deliverable_msgs) (struct xpc_channel *ch);
int (*xpc_n_of_deliverable_msgs) (struct xpc_channel *ch);
struct xpc_msg *(*xpc_get_deliverable_msg) (struct xpc_channel *ch);
struct xpc_msg *(*xpc_get_deliverable_msg) (struct xpc_channel *ch);


@@ -206,13 +206,13 @@ int (*xpc_any_partition_engaged) (void);
void (*xpc_indicate_partition_disengaged) (struct xpc_partition *part);
void (*xpc_indicate_partition_disengaged) (struct xpc_partition *part);
void (*xpc_assume_partition_disengaged) (short partid);
void (*xpc_assume_partition_disengaged) (short partid);


void (*xpc_send_channel_closerequest) (struct xpc_channel *ch,
void (*xpc_send_chctl_closerequest) (struct xpc_channel *ch,
				     unsigned long *irq_flags);
				     unsigned long *irq_flags);
void (*xpc_send_channel_closereply) (struct xpc_channel *ch,
void (*xpc_send_chctl_closereply) (struct xpc_channel *ch,
				   unsigned long *irq_flags);
				   unsigned long *irq_flags);
void (*xpc_send_channel_openrequest) (struct xpc_channel *ch,
void (*xpc_send_chctl_openrequest) (struct xpc_channel *ch,
				    unsigned long *irq_flags);
				    unsigned long *irq_flags);
void (*xpc_send_channel_openreply) (struct xpc_channel *ch,
void (*xpc_send_chctl_openreply) (struct xpc_channel *ch,
				  unsigned long *irq_flags);
				  unsigned long *irq_flags);


enum xp_retval (*xpc_send_msg) (struct xpc_channel *ch, u32 flags,
enum xp_retval (*xpc_send_msg) (struct xpc_channel *ch, u32 flags,
@@ -302,7 +302,7 @@ xpc_hb_checker(void *ignore)


			/*
			/*
			 * We need to periodically recheck to ensure no
			 * We need to periodically recheck to ensure no
			 * IPI/AMO pairs have been missed.  That check
			 * IRQ/AMO pairs have been missed.  That check
			 * must always reset xpc_hb_check_timeout.
			 * must always reset xpc_hb_check_timeout.
			 */
			 */
			force_IRQ = 1;
			force_IRQ = 1;
@@ -378,7 +378,7 @@ xpc_channel_mgr(struct xpc_partition *part)
	       atomic_read(&part->nchannels_active) > 0 ||
	       atomic_read(&part->nchannels_active) > 0 ||
	       !xpc_partition_disengaged(part)) {
	       !xpc_partition_disengaged(part)) {


		xpc_process_channel_activity(part);
		xpc_process_sent_chctl_flags(part);


		/*
		/*
		 * Wait until we've been requested to activate kthreads or
		 * Wait until we've been requested to activate kthreads or
@@ -396,7 +396,7 @@ xpc_channel_mgr(struct xpc_partition *part)
		atomic_dec(&part->channel_mgr_requests);
		atomic_dec(&part->channel_mgr_requests);
		(void)wait_event_interruptible(part->channel_mgr_wq,
		(void)wait_event_interruptible(part->channel_mgr_wq,
				(atomic_read(&part->channel_mgr_requests) > 0 ||
				(atomic_read(&part->channel_mgr_requests) > 0 ||
				 part->local_IPI_amo != 0 ||
				 part->chctl.all_flags != 0 ||
				 (part->act_state == XPC_P_DEACTIVATING &&
				 (part->act_state == XPC_P_DEACTIVATING &&
				 atomic_read(&part->nchannels_active) == 0 &&
				 atomic_read(&part->nchannels_active) == 0 &&
				 xpc_partition_disengaged(part))));
				 xpc_partition_disengaged(part))));
@@ -753,16 +753,15 @@ xpc_disconnect_wait(int ch_number)
		DBUG_ON(!(ch->flags & XPC_C_DISCONNECTED));
		DBUG_ON(!(ch->flags & XPC_C_DISCONNECTED));
		wakeup_channel_mgr = 0;
		wakeup_channel_mgr = 0;


		if (ch->delayed_IPI_flags) {
		if (ch->delayed_chctl_flags) {
			if (part->act_state != XPC_P_DEACTIVATING) {
			if (part->act_state != XPC_P_DEACTIVATING) {
				spin_lock(&part->IPI_lock);
				spin_lock(&part->chctl_lock);
				XPC_SET_IPI_FLAGS(part->local_IPI_amo,
				part->chctl.flags[ch->number] |=
						  ch->number,
				    ch->delayed_chctl_flags;
						  ch->delayed_IPI_flags);
				spin_unlock(&part->chctl_lock);
				spin_unlock(&part->IPI_lock);
				wakeup_channel_mgr = 1;
				wakeup_channel_mgr = 1;
			}
			}
			ch->delayed_IPI_flags = 0;
			ch->delayed_chctl_flags = 0;
		}
		}


		ch->flags &= ~XPC_C_WDISCONNECT;
		ch->flags &= ~XPC_C_WDISCONNECT;
+152 −149

File changed.

Preview size limit exceeded, changes collapsed.

+5 −5
Original line number Original line Diff line number Diff line
@@ -26,7 +26,7 @@ static DECLARE_BITMAP(xpc_heartbeating_to_mask_uv, XP_MAX_NPARTITIONS_UV);
static void *xpc_activate_mq;
static void *xpc_activate_mq;


static void
static void
xpc_IPI_send_local_activate_uv(struct xpc_partition *part)
xpc_send_local_activate_IRQ_uv(struct xpc_partition *part)
{
{
	/*
	/*
	 * >>> make our side think that the remote parition sent an activate
	 * >>> make our side think that the remote parition sent an activate
@@ -75,13 +75,13 @@ xpc_request_partition_activation_uv(struct xpc_rsvd_page *remote_rp,
 * >>>	part->sn.uv.activate_mq_gpa = remote_rp->sn.activate_mq_gpa;
 * >>>	part->sn.uv.activate_mq_gpa = remote_rp->sn.activate_mq_gpa;
 */
 */


	xpc_IPI_send_local_activate_uv(part);
	xpc_send_local_activate_IRQ_uv(part);
}
}


static void
static void
xpc_request_partition_reactivation_uv(struct xpc_partition *part)
xpc_request_partition_reactivation_uv(struct xpc_partition *part)
{
{
	xpc_IPI_send_local_activate_uv(part);
	xpc_send_local_activate_IRQ_uv(part);
}
}


/*
/*
@@ -114,7 +114,7 @@ xpc_make_first_contact_uv(struct xpc_partition *part)
}
}


static u64
static u64
xpc_get_IPI_flags_uv(struct xpc_partition *part)
xpc_get_chctl_all_flags_uv(struct xpc_partition *part)
{
{
	/* >>> this function needs fleshing out */
	/* >>> this function needs fleshing out */
	return 0UL;
	return 0UL;
@@ -140,7 +140,7 @@ xpc_init_uv(void)
	xpc_setup_infrastructure = xpc_setup_infrastructure_uv;
	xpc_setup_infrastructure = xpc_setup_infrastructure_uv;
	xpc_teardown_infrastructure = xpc_teardown_infrastructure_uv;
	xpc_teardown_infrastructure = xpc_teardown_infrastructure_uv;
	xpc_make_first_contact = xpc_make_first_contact_uv;
	xpc_make_first_contact = xpc_make_first_contact_uv;
	xpc_get_IPI_flags = xpc_get_IPI_flags_uv;
	xpc_get_chctl_all_flags = xpc_get_chctl_all_flags_uv;
	xpc_get_deliverable_msg = xpc_get_deliverable_msg_uv;
	xpc_get_deliverable_msg = xpc_get_deliverable_msg_uv;
}
}