|
@@ -18,6 +18,8 @@
|
|
|
#include <linux/interrupt.h>
|
|
|
#include <linux/delay.h>
|
|
|
#include <linux/device.h>
|
|
|
+#include <linux/cpu.h>
|
|
|
+#include <linux/module.h>
|
|
|
#include <linux/err.h>
|
|
|
#include <linux/slab.h>
|
|
|
#include <asm/uv/uv_hub.h>
|
|
@@ -59,6 +61,8 @@ static struct xpc_heartbeat_uv *xpc_heartbeat_uv;
|
|
|
XPC_NOTIFY_MSG_SIZE_UV)
|
|
|
#define XPC_NOTIFY_IRQ_NAME "xpc_notify"
|
|
|
|
|
|
+static int xpc_mq_node = -1;
|
|
|
+
|
|
|
static struct xpc_gru_mq_uv *xpc_activate_mq_uv;
|
|
|
static struct xpc_gru_mq_uv *xpc_notify_mq_uv;
|
|
|
|
|
@@ -109,11 +113,8 @@ xpc_get_gru_mq_irq_uv(struct xpc_gru_mq_uv *mq, int cpu, char *irq_name)
|
|
|
#if defined CONFIG_X86_64
|
|
|
mq->irq = uv_setup_irq(irq_name, cpu, mq->mmr_blade, mq->mmr_offset,
|
|
|
UV_AFFINITY_CPU);
|
|
|
- if (mq->irq < 0) {
|
|
|
- dev_err(xpc_part, "uv_setup_irq() returned error=%d\n",
|
|
|
- -mq->irq);
|
|
|
+ if (mq->irq < 0)
|
|
|
return mq->irq;
|
|
|
- }
|
|
|
|
|
|
mq->mmr_value = uv_read_global_mmr64(mmr_pnode, mq->mmr_offset);
|
|
|
|
|
@@ -238,8 +239,9 @@ xpc_create_gru_mq_uv(unsigned int mq_size, int cpu, char *irq_name,
|
|
|
mq->mmr_blade = uv_cpu_to_blade_id(cpu);
|
|
|
|
|
|
nid = cpu_to_node(cpu);
|
|
|
- page = alloc_pages_exact_node(nid, GFP_KERNEL | __GFP_ZERO | GFP_THISNODE,
|
|
|
- pg_order);
|
|
|
+ page = alloc_pages_exact_node(nid,
|
|
|
+ GFP_KERNEL | __GFP_ZERO | GFP_THISNODE,
|
|
|
+ pg_order);
|
|
|
if (page == NULL) {
|
|
|
dev_err(xpc_part, "xpc_create_gru_mq_uv() failed to alloc %d "
|
|
|
"bytes of memory on nid=%d for GRU mq\n", mq_size, nid);
|
|
@@ -1731,9 +1733,50 @@ static struct xpc_arch_operations xpc_arch_ops_uv = {
|
|
|
.notify_senders_of_disconnect = xpc_notify_senders_of_disconnect_uv,
|
|
|
};
|
|
|
|
|
|
+static int
|
|
|
+xpc_init_mq_node(int nid)
|
|
|
+{
|
|
|
+ int cpu;
|
|
|
+
|
|
|
+ get_online_cpus();
|
|
|
+
|
|
|
+ for_each_cpu(cpu, cpumask_of_node(nid)) {
|
|
|
+ xpc_activate_mq_uv =
|
|
|
+ xpc_create_gru_mq_uv(XPC_ACTIVATE_MQ_SIZE_UV, nid,
|
|
|
+ XPC_ACTIVATE_IRQ_NAME,
|
|
|
+ xpc_handle_activate_IRQ_uv);
|
|
|
+ if (!IS_ERR(xpc_activate_mq_uv))
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ if (IS_ERR(xpc_activate_mq_uv)) {
|
|
|
+ put_online_cpus();
|
|
|
+ return PTR_ERR(xpc_activate_mq_uv);
|
|
|
+ }
|
|
|
+
|
|
|
+ for_each_cpu(cpu, cpumask_of_node(nid)) {
|
|
|
+ xpc_notify_mq_uv =
|
|
|
+ xpc_create_gru_mq_uv(XPC_NOTIFY_MQ_SIZE_UV, nid,
|
|
|
+ XPC_NOTIFY_IRQ_NAME,
|
|
|
+ xpc_handle_notify_IRQ_uv);
|
|
|
+ if (!IS_ERR(xpc_notify_mq_uv))
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ if (IS_ERR(xpc_notify_mq_uv)) {
|
|
|
+ xpc_destroy_gru_mq_uv(xpc_activate_mq_uv);
|
|
|
+ put_online_cpus();
|
|
|
+ return PTR_ERR(xpc_notify_mq_uv);
|
|
|
+ }
|
|
|
+
|
|
|
+ put_online_cpus();
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
int
|
|
|
xpc_init_uv(void)
|
|
|
{
|
|
|
+ int nid;
|
|
|
+ int ret = 0;
|
|
|
+
|
|
|
xpc_arch_ops = xpc_arch_ops_uv;
|
|
|
|
|
|
if (sizeof(struct xpc_notify_mq_msghdr_uv) > XPC_MSG_HDR_MAX_SIZE) {
|
|
@@ -1742,21 +1785,21 @@ xpc_init_uv(void)
|
|
|
return -E2BIG;
|
|
|
}
|
|
|
|
|
|
- xpc_activate_mq_uv = xpc_create_gru_mq_uv(XPC_ACTIVATE_MQ_SIZE_UV, 0,
|
|
|
- XPC_ACTIVATE_IRQ_NAME,
|
|
|
- xpc_handle_activate_IRQ_uv);
|
|
|
- if (IS_ERR(xpc_activate_mq_uv))
|
|
|
- return PTR_ERR(xpc_activate_mq_uv);
|
|
|
+ if (xpc_mq_node < 0)
|
|
|
+ for_each_online_node(nid) {
|
|
|
+ ret = xpc_init_mq_node(nid);
|
|
|
|
|
|
- xpc_notify_mq_uv = xpc_create_gru_mq_uv(XPC_NOTIFY_MQ_SIZE_UV, 0,
|
|
|
- XPC_NOTIFY_IRQ_NAME,
|
|
|
- xpc_handle_notify_IRQ_uv);
|
|
|
- if (IS_ERR(xpc_notify_mq_uv)) {
|
|
|
- xpc_destroy_gru_mq_uv(xpc_activate_mq_uv);
|
|
|
- return PTR_ERR(xpc_notify_mq_uv);
|
|
|
- }
|
|
|
+ if (!ret)
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ ret = xpc_init_mq_node(xpc_mq_node);
|
|
|
|
|
|
- return 0;
|
|
|
+ if (ret < 0)
|
|
|
+ dev_err(xpc_part, "xpc_init_mq_node() returned error=%d\n",
|
|
|
+ -ret);
|
|
|
+
|
|
|
+ return ret;
|
|
|
}
|
|
|
|
|
|
void
|
|
@@ -1765,3 +1808,6 @@ xpc_exit_uv(void)
|
|
|
xpc_destroy_gru_mq_uv(xpc_notify_mq_uv);
|
|
|
xpc_destroy_gru_mq_uv(xpc_activate_mq_uv);
|
|
|
}
|
|
|
+
|
|
|
+module_param(xpc_mq_node, int, 0);
|
|
|
+MODULE_PARM_DESC(xpc_mq_node, "Node number on which to allocate message queues.");
|