aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMartin K. Petersen <martin.petersen@oracle.com>2014-01-03 19:16:56 -0500
committerChristoph Hellwig <hch@lst.de>2014-07-25 17:16:58 -0400
commit91b265bf0b5733a6c4865e809c93a2a812de46e8 (patch)
tree79499e2dd01542f89f6db0a6f87213a2e4f95989
parentcbbb7b31ad842e17b690254a546ddcedc79a4f05 (diff)
mpt3sas: Rework the MSI-X grouping code
On systems with a non power-of-two CPU count the existing MSI-X grouping code failed to distribute interrupts correctly. Rework the code to handle arbitrary processor counts. Also remove the hardcoded upper limit on the number of processors so we can boot on large systems. Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com> Acked-by: Sreekanth Reddy <Sreekanth.reddy@avagotech.com> Signed-off-by: Christoph Hellwig <hch@lst.de>
-rw-r--r--drivers/scsi/mpt3sas/mpt3sas_base.c73
1 files changed, 21 insertions, 52 deletions
diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.c b/drivers/scsi/mpt3sas/mpt3sas_base.c
index 0cf4f7000f94..c608a616941a 100644
--- a/drivers/scsi/mpt3sas/mpt3sas_base.c
+++ b/drivers/scsi/mpt3sas/mpt3sas_base.c
@@ -1624,66 +1624,35 @@ _base_request_irq(struct MPT3SAS_ADAPTER *ioc, u8 index, u32 vector)
1624static void 1624static void
1625_base_assign_reply_queues(struct MPT3SAS_ADAPTER *ioc) 1625_base_assign_reply_queues(struct MPT3SAS_ADAPTER *ioc)
1626{ 1626{
1627 struct adapter_reply_queue *reply_q; 1627 unsigned int cpu, nr_cpus, nr_msix, index = 0;
1628 int cpu_id;
1629 int cpu_grouping, loop, grouping, grouping_mod;
1630 int reply_queue;
1631 1628
1632 if (!_base_is_controller_msix_enabled(ioc)) 1629 if (!_base_is_controller_msix_enabled(ioc))
1633 return; 1630 return;
1634 1631
1635 memset(ioc->cpu_msix_table, 0, ioc->cpu_msix_table_sz); 1632 memset(ioc->cpu_msix_table, 0, ioc->cpu_msix_table_sz);
1636 1633
1637 /* NUMA Hardware bug workaround - drop to less reply queues */ 1634 nr_cpus = num_online_cpus();
1638 if (ioc->reply_queue_count > ioc->facts.MaxMSIxVectors) { 1635 nr_msix = ioc->reply_queue_count = min(ioc->reply_queue_count,
1639 ioc->reply_queue_count = ioc->facts.MaxMSIxVectors; 1636 ioc->facts.MaxMSIxVectors);
1640 reply_queue = 0; 1637 if (!nr_msix)
1641 list_for_each_entry(reply_q, &ioc->reply_queue_list, list) { 1638 return;
1642 reply_q->msix_index = reply_queue;
1643 if (++reply_queue == ioc->reply_queue_count)
1644 reply_queue = 0;
1645 }
1646 }
1647 1639
1648 /* when there are more cpus than available msix vectors, 1640 cpu = cpumask_first(cpu_online_mask);
1649 * then group cpus togeather on same irq 1641
1650 */ 1642 do {
1651 if (ioc->cpu_count > ioc->msix_vector_count) { 1643 unsigned int i, group = nr_cpus / nr_msix;
1652 grouping = ioc->cpu_count / ioc->msix_vector_count; 1644
1653 grouping_mod = ioc->cpu_count % ioc->msix_vector_count; 1645 if (index < nr_cpus % nr_msix)
1654 if (grouping < 2 || (grouping == 2 && !grouping_mod)) 1646 group++;
1655 cpu_grouping = 2; 1647
1656 else if (grouping < 4 || (grouping == 4 && !grouping_mod)) 1648 for (i = 0 ; i < group ; i++) {
1657 cpu_grouping = 4; 1649 ioc->cpu_msix_table[cpu] = index;
1658 else if (grouping < 8 || (grouping == 8 && !grouping_mod)) 1650 cpu = cpumask_next(cpu, cpu_online_mask);
1659 cpu_grouping = 8;
1660 else
1661 cpu_grouping = 16;
1662 } else
1663 cpu_grouping = 0;
1664
1665 loop = 0;
1666 reply_q = list_entry(ioc->reply_queue_list.next,
1667 struct adapter_reply_queue, list);
1668 for_each_online_cpu(cpu_id) {
1669 if (!cpu_grouping) {
1670 ioc->cpu_msix_table[cpu_id] = reply_q->msix_index;
1671 reply_q = list_entry(reply_q->list.next,
1672 struct adapter_reply_queue, list);
1673 } else {
1674 if (loop < cpu_grouping) {
1675 ioc->cpu_msix_table[cpu_id] =
1676 reply_q->msix_index;
1677 loop++;
1678 } else {
1679 reply_q = list_entry(reply_q->list.next,
1680 struct adapter_reply_queue, list);
1681 ioc->cpu_msix_table[cpu_id] =
1682 reply_q->msix_index;
1683 loop = 1;
1684 }
1685 } 1651 }
1686 } 1652
1653 index++;
1654
1655 } while (cpu < nr_cpus);
1687} 1656}
1688 1657
1689/** 1658/**