diff options
| -rw-r--r-- | drivers/misc/sgi-xp/xpc_uv.c | 84 |
1 files changed, 65 insertions, 19 deletions
diff --git a/drivers/misc/sgi-xp/xpc_uv.c b/drivers/misc/sgi-xp/xpc_uv.c index 87b251ab6ec5..b9e2000969f0 100644 --- a/drivers/misc/sgi-xp/xpc_uv.c +++ b/drivers/misc/sgi-xp/xpc_uv.c | |||
| @@ -18,6 +18,8 @@ | |||
| 18 | #include <linux/interrupt.h> | 18 | #include <linux/interrupt.h> |
| 19 | #include <linux/delay.h> | 19 | #include <linux/delay.h> |
| 20 | #include <linux/device.h> | 20 | #include <linux/device.h> |
| 21 | #include <linux/cpu.h> | ||
| 22 | #include <linux/module.h> | ||
| 21 | #include <linux/err.h> | 23 | #include <linux/err.h> |
| 22 | #include <linux/slab.h> | 24 | #include <linux/slab.h> |
| 23 | #include <asm/uv/uv_hub.h> | 25 | #include <asm/uv/uv_hub.h> |
| @@ -59,6 +61,8 @@ static struct xpc_heartbeat_uv *xpc_heartbeat_uv; | |||
| 59 | XPC_NOTIFY_MSG_SIZE_UV) | 61 | XPC_NOTIFY_MSG_SIZE_UV) |
| 60 | #define XPC_NOTIFY_IRQ_NAME "xpc_notify" | 62 | #define XPC_NOTIFY_IRQ_NAME "xpc_notify" |
| 61 | 63 | ||
| 64 | static int xpc_mq_node = -1; | ||
| 65 | |||
| 62 | static struct xpc_gru_mq_uv *xpc_activate_mq_uv; | 66 | static struct xpc_gru_mq_uv *xpc_activate_mq_uv; |
| 63 | static struct xpc_gru_mq_uv *xpc_notify_mq_uv; | 67 | static struct xpc_gru_mq_uv *xpc_notify_mq_uv; |
| 64 | 68 | ||
| @@ -109,11 +113,8 @@ xpc_get_gru_mq_irq_uv(struct xpc_gru_mq_uv *mq, int cpu, char *irq_name) | |||
| 109 | #if defined CONFIG_X86_64 | 113 | #if defined CONFIG_X86_64 |
| 110 | mq->irq = uv_setup_irq(irq_name, cpu, mq->mmr_blade, mq->mmr_offset, | 114 | mq->irq = uv_setup_irq(irq_name, cpu, mq->mmr_blade, mq->mmr_offset, |
| 111 | UV_AFFINITY_CPU); | 115 | UV_AFFINITY_CPU); |
| 112 | if (mq->irq < 0) { | 116 | if (mq->irq < 0) |
| 113 | dev_err(xpc_part, "uv_setup_irq() returned error=%d\n", | ||
| 114 | -mq->irq); | ||
| 115 | return mq->irq; | 117 | return mq->irq; |
| 116 | } | ||
| 117 | 118 | ||
| 118 | mq->mmr_value = uv_read_global_mmr64(mmr_pnode, mq->mmr_offset); | 119 | mq->mmr_value = uv_read_global_mmr64(mmr_pnode, mq->mmr_offset); |
| 119 | 120 | ||
| @@ -238,8 +239,9 @@ xpc_create_gru_mq_uv(unsigned int mq_size, int cpu, char *irq_name, | |||
| 238 | mq->mmr_blade = uv_cpu_to_blade_id(cpu); | 239 | mq->mmr_blade = uv_cpu_to_blade_id(cpu); |
| 239 | 240 | ||
| 240 | nid = cpu_to_node(cpu); | 241 | nid = cpu_to_node(cpu); |
| 241 | page = alloc_pages_exact_node(nid, GFP_KERNEL | __GFP_ZERO | GFP_THISNODE, | 242 | page = alloc_pages_exact_node(nid, |
| 242 | pg_order); | 243 | GFP_KERNEL | __GFP_ZERO | GFP_THISNODE, |
| 244 | pg_order); | ||
| 243 | if (page == NULL) { | 245 | if (page == NULL) { |
| 244 | dev_err(xpc_part, "xpc_create_gru_mq_uv() failed to alloc %d " | 246 | dev_err(xpc_part, "xpc_create_gru_mq_uv() failed to alloc %d " |
| 245 | "bytes of memory on nid=%d for GRU mq\n", mq_size, nid); | 247 | "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 = { | |||
| 1731 | .notify_senders_of_disconnect = xpc_notify_senders_of_disconnect_uv, | 1733 | .notify_senders_of_disconnect = xpc_notify_senders_of_disconnect_uv, |
| 1732 | }; | 1734 | }; |
| 1733 | 1735 | ||
| 1736 | static int | ||
| 1737 | xpc_init_mq_node(int nid) | ||
| 1738 | { | ||
| 1739 | int cpu; | ||
| 1740 | |||
| 1741 | get_online_cpus(); | ||
| 1742 | |||
| 1743 | for_each_cpu(cpu, cpumask_of_node(nid)) { | ||
| 1744 | xpc_activate_mq_uv = | ||
| 1745 | xpc_create_gru_mq_uv(XPC_ACTIVATE_MQ_SIZE_UV, nid, | ||
| 1746 | XPC_ACTIVATE_IRQ_NAME, | ||
| 1747 | xpc_handle_activate_IRQ_uv); | ||
| 1748 | if (!IS_ERR(xpc_activate_mq_uv)) | ||
| 1749 | break; | ||
| 1750 | } | ||
| 1751 | if (IS_ERR(xpc_activate_mq_uv)) { | ||
| 1752 | put_online_cpus(); | ||
| 1753 | return PTR_ERR(xpc_activate_mq_uv); | ||
| 1754 | } | ||
| 1755 | |||
| 1756 | for_each_cpu(cpu, cpumask_of_node(nid)) { | ||
| 1757 | xpc_notify_mq_uv = | ||
| 1758 | xpc_create_gru_mq_uv(XPC_NOTIFY_MQ_SIZE_UV, nid, | ||
| 1759 | XPC_NOTIFY_IRQ_NAME, | ||
| 1760 | xpc_handle_notify_IRQ_uv); | ||
| 1761 | if (!IS_ERR(xpc_notify_mq_uv)) | ||
| 1762 | break; | ||
| 1763 | } | ||
| 1764 | if (IS_ERR(xpc_notify_mq_uv)) { | ||
| 1765 | xpc_destroy_gru_mq_uv(xpc_activate_mq_uv); | ||
| 1766 | put_online_cpus(); | ||
| 1767 | return PTR_ERR(xpc_notify_mq_uv); | ||
| 1768 | } | ||
| 1769 | |||
| 1770 | put_online_cpus(); | ||
| 1771 | return 0; | ||
| 1772 | } | ||
| 1773 | |||
| 1734 | int | 1774 | int |
| 1735 | xpc_init_uv(void) | 1775 | xpc_init_uv(void) |
| 1736 | { | 1776 | { |
| 1777 | int nid; | ||
| 1778 | int ret = 0; | ||
| 1779 | |||
| 1737 | xpc_arch_ops = xpc_arch_ops_uv; | 1780 | xpc_arch_ops = xpc_arch_ops_uv; |
| 1738 | 1781 | ||
| 1739 | if (sizeof(struct xpc_notify_mq_msghdr_uv) > XPC_MSG_HDR_MAX_SIZE) { | 1782 | if (sizeof(struct xpc_notify_mq_msghdr_uv) > XPC_MSG_HDR_MAX_SIZE) { |
| @@ -1742,21 +1785,21 @@ xpc_init_uv(void) | |||
| 1742 | return -E2BIG; | 1785 | return -E2BIG; |
| 1743 | } | 1786 | } |
| 1744 | 1787 | ||
| 1745 | xpc_activate_mq_uv = xpc_create_gru_mq_uv(XPC_ACTIVATE_MQ_SIZE_UV, 0, | 1788 | if (xpc_mq_node < 0) |
| 1746 | XPC_ACTIVATE_IRQ_NAME, | 1789 | for_each_online_node(nid) { |
| 1747 | xpc_handle_activate_IRQ_uv); | 1790 | ret = xpc_init_mq_node(nid); |
| 1748 | if (IS_ERR(xpc_activate_mq_uv)) | ||
| 1749 | return PTR_ERR(xpc_activate_mq_uv); | ||
| 1750 | 1791 | ||
| 1751 | xpc_notify_mq_uv = xpc_create_gru_mq_uv(XPC_NOTIFY_MQ_SIZE_UV, 0, | 1792 | if (!ret) |
| 1752 | XPC_NOTIFY_IRQ_NAME, | 1793 | break; |
| 1753 | xpc_handle_notify_IRQ_uv); | 1794 | } |
| 1754 | if (IS_ERR(xpc_notify_mq_uv)) { | 1795 | else |
| 1755 | xpc_destroy_gru_mq_uv(xpc_activate_mq_uv); | 1796 | ret = xpc_init_mq_node(xpc_mq_node); |
| 1756 | return PTR_ERR(xpc_notify_mq_uv); | ||
| 1757 | } | ||
| 1758 | 1797 | ||
| 1759 | return 0; | 1798 | if (ret < 0) |
| 1799 | dev_err(xpc_part, "xpc_init_mq_node() returned error=%d\n", | ||
| 1800 | -ret); | ||
| 1801 | |||
| 1802 | return ret; | ||
| 1760 | } | 1803 | } |
| 1761 | 1804 | ||
| 1762 | void | 1805 | void |
| @@ -1765,3 +1808,6 @@ xpc_exit_uv(void) | |||
| 1765 | xpc_destroy_gru_mq_uv(xpc_notify_mq_uv); | 1808 | xpc_destroy_gru_mq_uv(xpc_notify_mq_uv); |
| 1766 | xpc_destroy_gru_mq_uv(xpc_activate_mq_uv); | 1809 | xpc_destroy_gru_mq_uv(xpc_activate_mq_uv); |
| 1767 | } | 1810 | } |
| 1811 | |||
| 1812 | module_param(xpc_mq_node, int, 0); | ||
| 1813 | MODULE_PARM_DESC(xpc_mq_node, "Node number on which to allocate message queues."); | ||
