Commit 49c68a85 authored by Jesse Larrew's avatar Jesse Larrew Committed by Benjamin Herrenschmidt

powerpc/pseries: Add PRRN RTAS event handler

A PRRN event is signaled via the RTAS event-scan mechanism, which
returns a Hot Plug Event message "fixed part" indicating "Platform
Resource Reassignment". In response to the Hot Plug Event message,
we must call ibm,update-nodes to determine which resources were
reassigned and then ibm,update-properties to obtain the new affinity
information about those resources.

The PRRN event-scan RTAS message contains only the "fixed part" with
the "Type" field set to the value 160 and no Extended Event Log. The
four-byte Extended Event Log Length field is re-purposed (since no
Extended Event Log message is included) to pass the "scope" parameter
that causes the ibm,update-nodes to return the nodes affected by the
specific resource reassignment.

This patch adds a handler for RTAS events. The function
pseries_devicetree_update() (from mobility.c) is used to make the
ibm,update-nodes/ibm,update-properties RTAS calls. Updating the NUMA maps
(handled by a subsequent patch) will require significant processing,
so pseries_devicetree_update() is called from an asynchronous workqueue
to allow event processing to continue.

PRRN RTAS events on pseries systems are rare events that have to be
initiated from the HMC console for the system by an IBM tech. This allows
us to assume that these events are widely spaced. Additionally, all work
on the queue is flushed before handling any new work to ensure we only have
one event in flight being handled at a time.
Signed-off-by: default avatarNathan Fontenot <nfont@linux.vnet.ibm.com>
Signed-off-by: default avatarBenjamin Herrenschmidt <benh@kernel.crashing.org>
parent 2e9b7b02
...@@ -143,6 +143,8 @@ struct rtas_suspend_me_data { ...@@ -143,6 +143,8 @@ struct rtas_suspend_me_data {
#define RTAS_TYPE_PMGM_TIME_ALARM 0x6f #define RTAS_TYPE_PMGM_TIME_ALARM 0x6f
#define RTAS_TYPE_PMGM_CONFIG_CHANGE 0x70 #define RTAS_TYPE_PMGM_CONFIG_CHANGE 0x70
#define RTAS_TYPE_PMGM_SERVICE_PROC 0x71 #define RTAS_TYPE_PMGM_SERVICE_PROC 0x71
/* Platform Resource Reassignment Notification */
#define RTAS_TYPE_PRRN 0xA0
/* RTAS check-exception vector offset */ /* RTAS check-exception vector offset */
#define RTAS_VECTOR_EXTERNAL_INTERRUPT 0x500 #define RTAS_VECTOR_EXTERNAL_INTERRUPT 0x500
......
...@@ -87,6 +87,8 @@ static char *rtas_event_type(int type) ...@@ -87,6 +87,8 @@ static char *rtas_event_type(int type)
return "Resource Deallocation Event"; return "Resource Deallocation Event";
case RTAS_TYPE_DUMP: case RTAS_TYPE_DUMP:
return "Dump Notification Event"; return "Dump Notification Event";
case RTAS_TYPE_PRRN:
return "Platform Resource Reassignment Event";
} }
return rtas_type[0]; return rtas_type[0];
...@@ -265,9 +267,49 @@ void pSeries_log_error(char *buf, unsigned int err_type, int fatal) ...@@ -265,9 +267,49 @@ void pSeries_log_error(char *buf, unsigned int err_type, int fatal)
spin_unlock_irqrestore(&rtasd_log_lock, s); spin_unlock_irqrestore(&rtasd_log_lock, s);
return; return;
} }
}
#ifdef CONFIG_PPC_PSERIES
static s32 prrn_update_scope;
static void prrn_work_fn(struct work_struct *work)
{
/*
* For PRRN, we must pass the negative of the scope value in
* the RTAS event.
*/
pseries_devicetree_update(-prrn_update_scope);
}
static DECLARE_WORK(prrn_work, prrn_work_fn);
void prrn_schedule_update(u32 scope)
{
flush_work(&prrn_work);
prrn_update_scope = scope;
schedule_work(&prrn_work);
}
static void handle_rtas_event(const struct rtas_error_log *log)
{
if (log->type == RTAS_TYPE_PRRN)
/* For PRRN Events the extended log length is used to denote
* the scope for calling rtas update-nodes.
*/
prrn_schedule_update(log->extended_log_length);
return;
}
#else
static void handle_rtas_event(const struct rtas_error_log *log)
{
return;
} }
#endif
static int rtas_log_open(struct inode * inode, struct file * file) static int rtas_log_open(struct inode * inode, struct file * file)
{ {
return 0; return 0;
...@@ -388,8 +430,10 @@ static void do_event_scan(void) ...@@ -388,8 +430,10 @@ static void do_event_scan(void)
break; break;
} }
if (error == 0) if (error == 0) {
pSeries_log_error(logdata, ERR_TYPE_RTAS_LOG, 0); pSeries_log_error(logdata, ERR_TYPE_RTAS_LOG, 0);
handle_rtas_event((struct rtas_error_log *)logdata);
}
} while(error == 0); } while(error == 0);
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment