diff options
Diffstat (limited to 'drivers/scsi/mpt3sas/mpt3sas_base.c')
-rw-r--r-- | drivers/scsi/mpt3sas/mpt3sas_base.c | 287 |
1 files changed, 227 insertions, 60 deletions
diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.c b/drivers/scsi/mpt3sas/mpt3sas_base.c index 93ce2b2baa41..1560115079c7 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_base.c +++ b/drivers/scsi/mpt3sas/mpt3sas_base.c | |||
@@ -3,7 +3,7 @@ | |||
3 | * for access to MPT (Message Passing Technology) firmware. | 3 | * for access to MPT (Message Passing Technology) firmware. |
4 | * | 4 | * |
5 | * This code is based on drivers/scsi/mpt3sas/mpt3sas_base.c | 5 | * This code is based on drivers/scsi/mpt3sas/mpt3sas_base.c |
6 | * Copyright (C) 2012-2013 LSI Corporation | 6 | * Copyright (C) 2012-2014 LSI Corporation |
7 | * (mailto:DL-MPTFusionLinux@lsi.com) | 7 | * (mailto:DL-MPTFusionLinux@lsi.com) |
8 | * | 8 | * |
9 | * This program is free software; you can redistribute it and/or | 9 | * This program is free software; you can redistribute it and/or |
@@ -91,6 +91,8 @@ static int mpt3sas_fwfault_debug; | |||
91 | MODULE_PARM_DESC(mpt3sas_fwfault_debug, | 91 | MODULE_PARM_DESC(mpt3sas_fwfault_debug, |
92 | " enable detection of firmware fault and halt firmware - (default=0)"); | 92 | " enable detection of firmware fault and halt firmware - (default=0)"); |
93 | 93 | ||
94 | static int | ||
95 | _base_get_ioc_facts(struct MPT3SAS_ADAPTER *ioc, int sleep_flag); | ||
94 | 96 | ||
95 | /** | 97 | /** |
96 | * _scsih_set_fwfault_debug - global setting of ioc->fwfault_debug. | 98 | * _scsih_set_fwfault_debug - global setting of ioc->fwfault_debug. |
@@ -1482,17 +1484,22 @@ static int | |||
1482 | _base_config_dma_addressing(struct MPT3SAS_ADAPTER *ioc, struct pci_dev *pdev) | 1484 | _base_config_dma_addressing(struct MPT3SAS_ADAPTER *ioc, struct pci_dev *pdev) |
1483 | { | 1485 | { |
1484 | struct sysinfo s; | 1486 | struct sysinfo s; |
1485 | char *desc = NULL; | 1487 | u64 consistent_dma_mask; |
1488 | |||
1489 | if (ioc->dma_mask) | ||
1490 | consistent_dma_mask = DMA_BIT_MASK(64); | ||
1491 | else | ||
1492 | consistent_dma_mask = DMA_BIT_MASK(32); | ||
1486 | 1493 | ||
1487 | if (sizeof(dma_addr_t) > 4) { | 1494 | if (sizeof(dma_addr_t) > 4) { |
1488 | const uint64_t required_mask = | 1495 | const uint64_t required_mask = |
1489 | dma_get_required_mask(&pdev->dev); | 1496 | dma_get_required_mask(&pdev->dev); |
1490 | if ((required_mask > DMA_BIT_MASK(32)) && | 1497 | if ((required_mask > DMA_BIT_MASK(32)) && |
1491 | !pci_set_dma_mask(pdev, DMA_BIT_MASK(64)) && | 1498 | !pci_set_dma_mask(pdev, DMA_BIT_MASK(64)) && |
1492 | !pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64))) { | 1499 | !pci_set_consistent_dma_mask(pdev, consistent_dma_mask)) { |
1493 | ioc->base_add_sg_single = &_base_add_sg_single_64; | 1500 | ioc->base_add_sg_single = &_base_add_sg_single_64; |
1494 | ioc->sge_size = sizeof(Mpi2SGESimple64_t); | 1501 | ioc->sge_size = sizeof(Mpi2SGESimple64_t); |
1495 | desc = "64"; | 1502 | ioc->dma_mask = 64; |
1496 | goto out; | 1503 | goto out; |
1497 | } | 1504 | } |
1498 | } | 1505 | } |
@@ -1501,19 +1508,30 @@ _base_config_dma_addressing(struct MPT3SAS_ADAPTER *ioc, struct pci_dev *pdev) | |||
1501 | && !pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32))) { | 1508 | && !pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32))) { |
1502 | ioc->base_add_sg_single = &_base_add_sg_single_32; | 1509 | ioc->base_add_sg_single = &_base_add_sg_single_32; |
1503 | ioc->sge_size = sizeof(Mpi2SGESimple32_t); | 1510 | ioc->sge_size = sizeof(Mpi2SGESimple32_t); |
1504 | desc = "32"; | 1511 | ioc->dma_mask = 32; |
1505 | } else | 1512 | } else |
1506 | return -ENODEV; | 1513 | return -ENODEV; |
1507 | 1514 | ||
1508 | out: | 1515 | out: |
1509 | si_meminfo(&s); | 1516 | si_meminfo(&s); |
1510 | pr_info(MPT3SAS_FMT | 1517 | pr_info(MPT3SAS_FMT |
1511 | "%s BIT PCI BUS DMA ADDRESSING SUPPORTED, total mem (%ld kB)\n", | 1518 | "%d BIT PCI BUS DMA ADDRESSING SUPPORTED, total mem (%ld kB)\n", |
1512 | ioc->name, desc, convert_to_kb(s.totalram)); | 1519 | ioc->name, ioc->dma_mask, convert_to_kb(s.totalram)); |
1513 | 1520 | ||
1514 | return 0; | 1521 | return 0; |
1515 | } | 1522 | } |
1516 | 1523 | ||
1524 | static int | ||
1525 | _base_change_consistent_dma_mask(struct MPT3SAS_ADAPTER *ioc, | ||
1526 | struct pci_dev *pdev) | ||
1527 | { | ||
1528 | if (pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64))) { | ||
1529 | if (pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32))) | ||
1530 | return -ENODEV; | ||
1531 | } | ||
1532 | return 0; | ||
1533 | } | ||
1534 | |||
1517 | /** | 1535 | /** |
1518 | * _base_check_enable_msix - checks MSIX capabable. | 1536 | * _base_check_enable_msix - checks MSIX capabable. |
1519 | * @ioc: per adapter object | 1537 | * @ioc: per adapter object |
@@ -1698,11 +1716,15 @@ _base_enable_msix(struct MPT3SAS_ADAPTER *ioc) | |||
1698 | ": %d, max_msix_vectors: %d\n", ioc->name, ioc->msix_vector_count, | 1716 | ": %d, max_msix_vectors: %d\n", ioc->name, ioc->msix_vector_count, |
1699 | ioc->cpu_count, max_msix_vectors); | 1717 | ioc->cpu_count, max_msix_vectors); |
1700 | 1718 | ||
1719 | if (!ioc->rdpq_array_enable && max_msix_vectors == -1) | ||
1720 | max_msix_vectors = 8; | ||
1721 | |||
1701 | if (max_msix_vectors > 0) { | 1722 | if (max_msix_vectors > 0) { |
1702 | ioc->reply_queue_count = min_t(int, max_msix_vectors, | 1723 | ioc->reply_queue_count = min_t(int, max_msix_vectors, |
1703 | ioc->reply_queue_count); | 1724 | ioc->reply_queue_count); |
1704 | ioc->msix_vector_count = ioc->reply_queue_count; | 1725 | ioc->msix_vector_count = ioc->reply_queue_count; |
1705 | } | 1726 | } else if (max_msix_vectors == 0) |
1727 | goto try_ioapic; | ||
1706 | 1728 | ||
1707 | entries = kcalloc(ioc->reply_queue_count, sizeof(struct msix_entry), | 1729 | entries = kcalloc(ioc->reply_queue_count, sizeof(struct msix_entry), |
1708 | GFP_KERNEL); | 1730 | GFP_KERNEL); |
@@ -1716,10 +1738,10 @@ _base_enable_msix(struct MPT3SAS_ADAPTER *ioc) | |||
1716 | for (i = 0, a = entries; i < ioc->reply_queue_count; i++, a++) | 1738 | for (i = 0, a = entries; i < ioc->reply_queue_count; i++, a++) |
1717 | a->entry = i; | 1739 | a->entry = i; |
1718 | 1740 | ||
1719 | r = pci_enable_msix(ioc->pdev, entries, ioc->reply_queue_count); | 1741 | r = pci_enable_msix_exact(ioc->pdev, entries, ioc->reply_queue_count); |
1720 | if (r) { | 1742 | if (r) { |
1721 | dfailprintk(ioc, pr_info(MPT3SAS_FMT | 1743 | dfailprintk(ioc, pr_info(MPT3SAS_FMT |
1722 | "pci_enable_msix failed (r=%d) !!!\n", | 1744 | "pci_enable_msix_exact failed (r=%d) !!!\n", |
1723 | ioc->name, r)); | 1745 | ioc->name, r)); |
1724 | kfree(entries); | 1746 | kfree(entries); |
1725 | goto try_ioapic; | 1747 | goto try_ioapic; |
@@ -1742,6 +1764,7 @@ _base_enable_msix(struct MPT3SAS_ADAPTER *ioc) | |||
1742 | /* failback to io_apic interrupt routing */ | 1764 | /* failback to io_apic interrupt routing */ |
1743 | try_ioapic: | 1765 | try_ioapic: |
1744 | 1766 | ||
1767 | ioc->reply_queue_count = 1; | ||
1745 | r = _base_request_irq(ioc, 0, ioc->pdev->irq); | 1768 | r = _base_request_irq(ioc, 0, ioc->pdev->irq); |
1746 | 1769 | ||
1747 | return r; | 1770 | return r; |
@@ -1821,6 +1844,16 @@ mpt3sas_base_map_resources(struct MPT3SAS_ADAPTER *ioc) | |||
1821 | } | 1844 | } |
1822 | 1845 | ||
1823 | _base_mask_interrupts(ioc); | 1846 | _base_mask_interrupts(ioc); |
1847 | |||
1848 | r = _base_get_ioc_facts(ioc, CAN_SLEEP); | ||
1849 | if (r) | ||
1850 | goto out_fail; | ||
1851 | |||
1852 | if (!ioc->rdpq_array_enable_assigned) { | ||
1853 | ioc->rdpq_array_enable = ioc->rdpq_array_capable; | ||
1854 | ioc->rdpq_array_enable_assigned = 1; | ||
1855 | } | ||
1856 | |||
1824 | r = _base_enable_msix(ioc); | 1857 | r = _base_enable_msix(ioc); |
1825 | if (r) | 1858 | if (r) |
1826 | goto out_fail; | 1859 | goto out_fail; |
@@ -2185,6 +2218,53 @@ mpt3sas_base_put_smid_default(struct MPT3SAS_ADAPTER *ioc, u16 smid) | |||
2185 | &ioc->scsi_lookup_lock); | 2218 | &ioc->scsi_lookup_lock); |
2186 | } | 2219 | } |
2187 | 2220 | ||
2221 | /** | ||
2222 | * _base_display_intel_branding - Display branding string | ||
2223 | * @ioc: per adapter object | ||
2224 | * | ||
2225 | * Return nothing. | ||
2226 | */ | ||
2227 | static void | ||
2228 | _base_display_intel_branding(struct MPT3SAS_ADAPTER *ioc) | ||
2229 | { | ||
2230 | if (ioc->pdev->subsystem_vendor != PCI_VENDOR_ID_INTEL) | ||
2231 | return; | ||
2232 | |||
2233 | switch (ioc->pdev->device) { | ||
2234 | case MPI25_MFGPAGE_DEVID_SAS3008: | ||
2235 | switch (ioc->pdev->subsystem_device) { | ||
2236 | case MPT3SAS_INTEL_RMS3JC080_SSDID: | ||
2237 | pr_info(MPT3SAS_FMT "%s\n", ioc->name, | ||
2238 | MPT3SAS_INTEL_RMS3JC080_BRANDING); | ||
2239 | break; | ||
2240 | |||
2241 | case MPT3SAS_INTEL_RS3GC008_SSDID: | ||
2242 | pr_info(MPT3SAS_FMT "%s\n", ioc->name, | ||
2243 | MPT3SAS_INTEL_RS3GC008_BRANDING); | ||
2244 | break; | ||
2245 | case MPT3SAS_INTEL_RS3FC044_SSDID: | ||
2246 | pr_info(MPT3SAS_FMT "%s\n", ioc->name, | ||
2247 | MPT3SAS_INTEL_RS3FC044_BRANDING); | ||
2248 | break; | ||
2249 | case MPT3SAS_INTEL_RS3UC080_SSDID: | ||
2250 | pr_info(MPT3SAS_FMT "%s\n", ioc->name, | ||
2251 | MPT3SAS_INTEL_RS3UC080_BRANDING); | ||
2252 | break; | ||
2253 | default: | ||
2254 | pr_info(MPT3SAS_FMT | ||
2255 | "Intel(R) Controller: Subsystem ID: 0x%X\n", | ||
2256 | ioc->name, ioc->pdev->subsystem_device); | ||
2257 | break; | ||
2258 | } | ||
2259 | break; | ||
2260 | default: | ||
2261 | pr_info(MPT3SAS_FMT | ||
2262 | "Intel(R) Controller: Subsystem ID: 0x%X\n", | ||
2263 | ioc->name, ioc->pdev->subsystem_device); | ||
2264 | break; | ||
2265 | } | ||
2266 | } | ||
2267 | |||
2188 | 2268 | ||
2189 | 2269 | ||
2190 | /** | 2270 | /** |
@@ -2216,6 +2296,8 @@ _base_display_ioc_capabilities(struct MPT3SAS_ADAPTER *ioc) | |||
2216 | (bios_version & 0x0000FF00) >> 8, | 2296 | (bios_version & 0x0000FF00) >> 8, |
2217 | bios_version & 0x000000FF); | 2297 | bios_version & 0x000000FF); |
2218 | 2298 | ||
2299 | _base_display_intel_branding(ioc); | ||
2300 | |||
2219 | pr_info(MPT3SAS_FMT "Protocol=(", ioc->name); | 2301 | pr_info(MPT3SAS_FMT "Protocol=(", ioc->name); |
2220 | 2302 | ||
2221 | if (ioc->facts.ProtocolFlags & MPI2_IOCFACTS_PROTOCOL_SCSI_INITIATOR) { | 2303 | if (ioc->facts.ProtocolFlags & MPI2_IOCFACTS_PROTOCOL_SCSI_INITIATOR) { |
@@ -2447,7 +2529,8 @@ _base_static_config_pages(struct MPT3SAS_ADAPTER *ioc) | |||
2447 | static void | 2529 | static void |
2448 | _base_release_memory_pools(struct MPT3SAS_ADAPTER *ioc) | 2530 | _base_release_memory_pools(struct MPT3SAS_ADAPTER *ioc) |
2449 | { | 2531 | { |
2450 | int i; | 2532 | int i = 0; |
2533 | struct reply_post_struct *rps; | ||
2451 | 2534 | ||
2452 | dexitprintk(ioc, pr_info(MPT3SAS_FMT "%s\n", ioc->name, | 2535 | dexitprintk(ioc, pr_info(MPT3SAS_FMT "%s\n", ioc->name, |
2453 | __func__)); | 2536 | __func__)); |
@@ -2492,15 +2575,25 @@ _base_release_memory_pools(struct MPT3SAS_ADAPTER *ioc) | |||
2492 | ioc->reply_free = NULL; | 2575 | ioc->reply_free = NULL; |
2493 | } | 2576 | } |
2494 | 2577 | ||
2495 | if (ioc->reply_post_free) { | 2578 | if (ioc->reply_post) { |
2496 | pci_pool_free(ioc->reply_post_free_dma_pool, | 2579 | do { |
2497 | ioc->reply_post_free, ioc->reply_post_free_dma); | 2580 | rps = &ioc->reply_post[i]; |
2581 | if (rps->reply_post_free) { | ||
2582 | pci_pool_free( | ||
2583 | ioc->reply_post_free_dma_pool, | ||
2584 | rps->reply_post_free, | ||
2585 | rps->reply_post_free_dma); | ||
2586 | dexitprintk(ioc, pr_info(MPT3SAS_FMT | ||
2587 | "reply_post_free_pool(0x%p): free\n", | ||
2588 | ioc->name, rps->reply_post_free)); | ||
2589 | rps->reply_post_free = NULL; | ||
2590 | } | ||
2591 | } while (ioc->rdpq_array_enable && | ||
2592 | (++i < ioc->reply_queue_count)); | ||
2593 | |||
2498 | if (ioc->reply_post_free_dma_pool) | 2594 | if (ioc->reply_post_free_dma_pool) |
2499 | pci_pool_destroy(ioc->reply_post_free_dma_pool); | 2595 | pci_pool_destroy(ioc->reply_post_free_dma_pool); |
2500 | dexitprintk(ioc, pr_info(MPT3SAS_FMT | 2596 | kfree(ioc->reply_post); |
2501 | "reply_post_free_pool(0x%p): free\n", ioc->name, | ||
2502 | ioc->reply_post_free)); | ||
2503 | ioc->reply_post_free = NULL; | ||
2504 | } | 2597 | } |
2505 | 2598 | ||
2506 | if (ioc->config_page) { | 2599 | if (ioc->config_page) { |
@@ -2647,6 +2740,65 @@ _base_allocate_memory_pools(struct MPT3SAS_ADAPTER *ioc, int sleep_flag) | |||
2647 | ioc->max_sges_in_chain_message, ioc->shost->sg_tablesize, | 2740 | ioc->max_sges_in_chain_message, ioc->shost->sg_tablesize, |
2648 | ioc->chains_needed_per_io)); | 2741 | ioc->chains_needed_per_io)); |
2649 | 2742 | ||
2743 | /* reply post queue, 16 byte align */ | ||
2744 | reply_post_free_sz = ioc->reply_post_queue_depth * | ||
2745 | sizeof(Mpi2DefaultReplyDescriptor_t); | ||
2746 | |||
2747 | sz = reply_post_free_sz; | ||
2748 | if (_base_is_controller_msix_enabled(ioc) && !ioc->rdpq_array_enable) | ||
2749 | sz *= ioc->reply_queue_count; | ||
2750 | |||
2751 | ioc->reply_post = kcalloc((ioc->rdpq_array_enable) ? | ||
2752 | (ioc->reply_queue_count):1, | ||
2753 | sizeof(struct reply_post_struct), GFP_KERNEL); | ||
2754 | |||
2755 | if (!ioc->reply_post) { | ||
2756 | pr_err(MPT3SAS_FMT "reply_post_free pool: kcalloc failed\n", | ||
2757 | ioc->name); | ||
2758 | goto out; | ||
2759 | } | ||
2760 | ioc->reply_post_free_dma_pool = pci_pool_create("reply_post_free pool", | ||
2761 | ioc->pdev, sz, 16, 0); | ||
2762 | if (!ioc->reply_post_free_dma_pool) { | ||
2763 | pr_err(MPT3SAS_FMT | ||
2764 | "reply_post_free pool: pci_pool_create failed\n", | ||
2765 | ioc->name); | ||
2766 | goto out; | ||
2767 | } | ||
2768 | i = 0; | ||
2769 | do { | ||
2770 | ioc->reply_post[i].reply_post_free = | ||
2771 | pci_pool_alloc(ioc->reply_post_free_dma_pool, | ||
2772 | GFP_KERNEL, | ||
2773 | &ioc->reply_post[i].reply_post_free_dma); | ||
2774 | if (!ioc->reply_post[i].reply_post_free) { | ||
2775 | pr_err(MPT3SAS_FMT | ||
2776 | "reply_post_free pool: pci_pool_alloc failed\n", | ||
2777 | ioc->name); | ||
2778 | goto out; | ||
2779 | } | ||
2780 | memset(ioc->reply_post[i].reply_post_free, 0, sz); | ||
2781 | dinitprintk(ioc, pr_info(MPT3SAS_FMT | ||
2782 | "reply post free pool (0x%p): depth(%d)," | ||
2783 | "element_size(%d), pool_size(%d kB)\n", ioc->name, | ||
2784 | ioc->reply_post[i].reply_post_free, | ||
2785 | ioc->reply_post_queue_depth, 8, sz/1024)); | ||
2786 | dinitprintk(ioc, pr_info(MPT3SAS_FMT | ||
2787 | "reply_post_free_dma = (0x%llx)\n", ioc->name, | ||
2788 | (unsigned long long) | ||
2789 | ioc->reply_post[i].reply_post_free_dma)); | ||
2790 | total_sz += sz; | ||
2791 | } while (ioc->rdpq_array_enable && (++i < ioc->reply_queue_count)); | ||
2792 | |||
2793 | if (ioc->dma_mask == 64) { | ||
2794 | if (_base_change_consistent_dma_mask(ioc, ioc->pdev) != 0) { | ||
2795 | pr_warn(MPT3SAS_FMT | ||
2796 | "no suitable consistent DMA mask for %s\n", | ||
2797 | ioc->name, pci_name(ioc->pdev)); | ||
2798 | goto out; | ||
2799 | } | ||
2800 | } | ||
2801 | |||
2650 | ioc->scsiio_depth = ioc->hba_queue_depth - | 2802 | ioc->scsiio_depth = ioc->hba_queue_depth - |
2651 | ioc->hi_priority_depth - ioc->internal_depth; | 2803 | ioc->hi_priority_depth - ioc->internal_depth; |
2652 | 2804 | ||
@@ -2861,40 +3013,6 @@ _base_allocate_memory_pools(struct MPT3SAS_ADAPTER *ioc, int sleep_flag) | |||
2861 | ioc->name, (unsigned long long)ioc->reply_free_dma)); | 3013 | ioc->name, (unsigned long long)ioc->reply_free_dma)); |
2862 | total_sz += sz; | 3014 | total_sz += sz; |
2863 | 3015 | ||
2864 | /* reply post queue, 16 byte align */ | ||
2865 | reply_post_free_sz = ioc->reply_post_queue_depth * | ||
2866 | sizeof(Mpi2DefaultReplyDescriptor_t); | ||
2867 | if (_base_is_controller_msix_enabled(ioc)) | ||
2868 | sz = reply_post_free_sz * ioc->reply_queue_count; | ||
2869 | else | ||
2870 | sz = reply_post_free_sz; | ||
2871 | ioc->reply_post_free_dma_pool = pci_pool_create("reply_post_free pool", | ||
2872 | ioc->pdev, sz, 16, 0); | ||
2873 | if (!ioc->reply_post_free_dma_pool) { | ||
2874 | pr_err(MPT3SAS_FMT | ||
2875 | "reply_post_free pool: pci_pool_create failed\n", | ||
2876 | ioc->name); | ||
2877 | goto out; | ||
2878 | } | ||
2879 | ioc->reply_post_free = pci_pool_alloc(ioc->reply_post_free_dma_pool , | ||
2880 | GFP_KERNEL, &ioc->reply_post_free_dma); | ||
2881 | if (!ioc->reply_post_free) { | ||
2882 | pr_err(MPT3SAS_FMT | ||
2883 | "reply_post_free pool: pci_pool_alloc failed\n", | ||
2884 | ioc->name); | ||
2885 | goto out; | ||
2886 | } | ||
2887 | memset(ioc->reply_post_free, 0, sz); | ||
2888 | dinitprintk(ioc, pr_info(MPT3SAS_FMT "reply post free pool" \ | ||
2889 | "(0x%p): depth(%d), element_size(%d), pool_size(%d kB)\n", | ||
2890 | ioc->name, ioc->reply_post_free, ioc->reply_post_queue_depth, 8, | ||
2891 | sz/1024)); | ||
2892 | dinitprintk(ioc, pr_info(MPT3SAS_FMT | ||
2893 | "reply_post_free_dma = (0x%llx)\n", | ||
2894 | ioc->name, (unsigned long long) | ||
2895 | ioc->reply_post_free_dma)); | ||
2896 | total_sz += sz; | ||
2897 | |||
2898 | ioc->config_page_sz = 512; | 3016 | ioc->config_page_sz = 512; |
2899 | ioc->config_page = pci_alloc_consistent(ioc->pdev, | 3017 | ioc->config_page = pci_alloc_consistent(ioc->pdev, |
2900 | ioc->config_page_sz, &ioc->config_page_dma); | 3018 | ioc->config_page_sz, &ioc->config_page_dma); |
@@ -3577,6 +3695,9 @@ _base_get_ioc_facts(struct MPT3SAS_ADAPTER *ioc, int sleep_flag) | |||
3577 | facts->IOCCapabilities = le32_to_cpu(mpi_reply.IOCCapabilities); | 3695 | facts->IOCCapabilities = le32_to_cpu(mpi_reply.IOCCapabilities); |
3578 | if ((facts->IOCCapabilities & MPI2_IOCFACTS_CAPABILITY_INTEGRATED_RAID)) | 3696 | if ((facts->IOCCapabilities & MPI2_IOCFACTS_CAPABILITY_INTEGRATED_RAID)) |
3579 | ioc->ir_firmware = 1; | 3697 | ioc->ir_firmware = 1; |
3698 | if ((facts->IOCCapabilities & | ||
3699 | MPI2_IOCFACTS_CAPABILITY_RDPQ_ARRAY_CAPABLE)) | ||
3700 | ioc->rdpq_array_capable = 1; | ||
3580 | facts->FWVersion.Word = le32_to_cpu(mpi_reply.FWVersion.Word); | 3701 | facts->FWVersion.Word = le32_to_cpu(mpi_reply.FWVersion.Word); |
3581 | facts->IOCRequestFrameSize = | 3702 | facts->IOCRequestFrameSize = |
3582 | le16_to_cpu(mpi_reply.IOCRequestFrameSize); | 3703 | le16_to_cpu(mpi_reply.IOCRequestFrameSize); |
@@ -3613,9 +3734,12 @@ _base_send_ioc_init(struct MPT3SAS_ADAPTER *ioc, int sleep_flag) | |||
3613 | { | 3734 | { |
3614 | Mpi2IOCInitRequest_t mpi_request; | 3735 | Mpi2IOCInitRequest_t mpi_request; |
3615 | Mpi2IOCInitReply_t mpi_reply; | 3736 | Mpi2IOCInitReply_t mpi_reply; |
3616 | int r; | 3737 | int i, r = 0; |
3617 | struct timeval current_time; | 3738 | struct timeval current_time; |
3618 | u16 ioc_status; | 3739 | u16 ioc_status; |
3740 | u32 reply_post_free_array_sz = 0; | ||
3741 | Mpi2IOCInitRDPQArrayEntry *reply_post_free_array = NULL; | ||
3742 | dma_addr_t reply_post_free_array_dma; | ||
3619 | 3743 | ||
3620 | dinitprintk(ioc, pr_info(MPT3SAS_FMT "%s\n", ioc->name, | 3744 | dinitprintk(ioc, pr_info(MPT3SAS_FMT "%s\n", ioc->name, |
3621 | __func__)); | 3745 | __func__)); |
@@ -3644,9 +3768,31 @@ _base_send_ioc_init(struct MPT3SAS_ADAPTER *ioc, int sleep_flag) | |||
3644 | cpu_to_le64((u64)ioc->request_dma); | 3768 | cpu_to_le64((u64)ioc->request_dma); |
3645 | mpi_request.ReplyFreeQueueAddress = | 3769 | mpi_request.ReplyFreeQueueAddress = |
3646 | cpu_to_le64((u64)ioc->reply_free_dma); | 3770 | cpu_to_le64((u64)ioc->reply_free_dma); |
3647 | mpi_request.ReplyDescriptorPostQueueAddress = | ||
3648 | cpu_to_le64((u64)ioc->reply_post_free_dma); | ||
3649 | 3771 | ||
3772 | if (ioc->rdpq_array_enable) { | ||
3773 | reply_post_free_array_sz = ioc->reply_queue_count * | ||
3774 | sizeof(Mpi2IOCInitRDPQArrayEntry); | ||
3775 | reply_post_free_array = pci_alloc_consistent(ioc->pdev, | ||
3776 | reply_post_free_array_sz, &reply_post_free_array_dma); | ||
3777 | if (!reply_post_free_array) { | ||
3778 | pr_err(MPT3SAS_FMT | ||
3779 | "reply_post_free_array: pci_alloc_consistent failed\n", | ||
3780 | ioc->name); | ||
3781 | r = -ENOMEM; | ||
3782 | goto out; | ||
3783 | } | ||
3784 | memset(reply_post_free_array, 0, reply_post_free_array_sz); | ||
3785 | for (i = 0; i < ioc->reply_queue_count; i++) | ||
3786 | reply_post_free_array[i].RDPQBaseAddress = | ||
3787 | cpu_to_le64( | ||
3788 | (u64)ioc->reply_post[i].reply_post_free_dma); | ||
3789 | mpi_request.MsgFlags = MPI2_IOCINIT_MSGFLAG_RDPQ_ARRAY_MODE; | ||
3790 | mpi_request.ReplyDescriptorPostQueueAddress = | ||
3791 | cpu_to_le64((u64)reply_post_free_array_dma); | ||
3792 | } else { | ||
3793 | mpi_request.ReplyDescriptorPostQueueAddress = | ||
3794 | cpu_to_le64((u64)ioc->reply_post[0].reply_post_free_dma); | ||
3795 | } | ||
3650 | 3796 | ||
3651 | /* This time stamp specifies number of milliseconds | 3797 | /* This time stamp specifies number of milliseconds |
3652 | * since epoch ~ midnight January 1, 1970. | 3798 | * since epoch ~ midnight January 1, 1970. |
@@ -3674,7 +3820,7 @@ _base_send_ioc_init(struct MPT3SAS_ADAPTER *ioc, int sleep_flag) | |||
3674 | if (r != 0) { | 3820 | if (r != 0) { |
3675 | pr_err(MPT3SAS_FMT "%s: handshake failed (r=%d)\n", | 3821 | pr_err(MPT3SAS_FMT "%s: handshake failed (r=%d)\n", |
3676 | ioc->name, __func__, r); | 3822 | ioc->name, __func__, r); |
3677 | return r; | 3823 | goto out; |
3678 | } | 3824 | } |
3679 | 3825 | ||
3680 | ioc_status = le16_to_cpu(mpi_reply.IOCStatus) & MPI2_IOCSTATUS_MASK; | 3826 | ioc_status = le16_to_cpu(mpi_reply.IOCStatus) & MPI2_IOCSTATUS_MASK; |
@@ -3684,7 +3830,12 @@ _base_send_ioc_init(struct MPT3SAS_ADAPTER *ioc, int sleep_flag) | |||
3684 | r = -EIO; | 3830 | r = -EIO; |
3685 | } | 3831 | } |
3686 | 3832 | ||
3687 | return 0; | 3833 | out: |
3834 | if (reply_post_free_array) | ||
3835 | pci_free_consistent(ioc->pdev, reply_post_free_array_sz, | ||
3836 | reply_post_free_array, | ||
3837 | reply_post_free_array_dma); | ||
3838 | return r; | ||
3688 | } | 3839 | } |
3689 | 3840 | ||
3690 | /** | 3841 | /** |
@@ -4234,7 +4385,7 @@ _base_make_ioc_operational(struct MPT3SAS_ADAPTER *ioc, int sleep_flag) | |||
4234 | struct _tr_list *delayed_tr, *delayed_tr_next; | 4385 | struct _tr_list *delayed_tr, *delayed_tr_next; |
4235 | struct adapter_reply_queue *reply_q; | 4386 | struct adapter_reply_queue *reply_q; |
4236 | long reply_post_free; | 4387 | long reply_post_free; |
4237 | u32 reply_post_free_sz; | 4388 | u32 reply_post_free_sz, index = 0; |
4238 | 4389 | ||
4239 | dinitprintk(ioc, pr_info(MPT3SAS_FMT "%s\n", ioc->name, | 4390 | dinitprintk(ioc, pr_info(MPT3SAS_FMT "%s\n", ioc->name, |
4240 | __func__)); | 4391 | __func__)); |
@@ -4305,9 +4456,9 @@ _base_make_ioc_operational(struct MPT3SAS_ADAPTER *ioc, int sleep_flag) | |||
4305 | _base_assign_reply_queues(ioc); | 4456 | _base_assign_reply_queues(ioc); |
4306 | 4457 | ||
4307 | /* initialize Reply Post Free Queue */ | 4458 | /* initialize Reply Post Free Queue */ |
4308 | reply_post_free = (long)ioc->reply_post_free; | ||
4309 | reply_post_free_sz = ioc->reply_post_queue_depth * | 4459 | reply_post_free_sz = ioc->reply_post_queue_depth * |
4310 | sizeof(Mpi2DefaultReplyDescriptor_t); | 4460 | sizeof(Mpi2DefaultReplyDescriptor_t); |
4461 | reply_post_free = (long)ioc->reply_post[index].reply_post_free; | ||
4311 | list_for_each_entry(reply_q, &ioc->reply_queue_list, list) { | 4462 | list_for_each_entry(reply_q, &ioc->reply_queue_list, list) { |
4312 | reply_q->reply_post_host_index = 0; | 4463 | reply_q->reply_post_host_index = 0; |
4313 | reply_q->reply_post_free = (Mpi2ReplyDescriptorsUnion_t *) | 4464 | reply_q->reply_post_free = (Mpi2ReplyDescriptorsUnion_t *) |
@@ -4317,7 +4468,15 @@ _base_make_ioc_operational(struct MPT3SAS_ADAPTER *ioc, int sleep_flag) | |||
4317 | cpu_to_le64(ULLONG_MAX); | 4468 | cpu_to_le64(ULLONG_MAX); |
4318 | if (!_base_is_controller_msix_enabled(ioc)) | 4469 | if (!_base_is_controller_msix_enabled(ioc)) |
4319 | goto skip_init_reply_post_free_queue; | 4470 | goto skip_init_reply_post_free_queue; |
4320 | reply_post_free += reply_post_free_sz; | 4471 | /* |
4472 | * If RDPQ is enabled, switch to the next allocation. | ||
4473 | * Otherwise advance within the contiguous region. | ||
4474 | */ | ||
4475 | if (ioc->rdpq_array_enable) | ||
4476 | reply_post_free = (long) | ||
4477 | ioc->reply_post[++index].reply_post_free; | ||
4478 | else | ||
4479 | reply_post_free += reply_post_free_sz; | ||
4321 | } | 4480 | } |
4322 | skip_init_reply_post_free_queue: | 4481 | skip_init_reply_post_free_queue: |
4323 | 4482 | ||
@@ -4428,6 +4587,8 @@ mpt3sas_base_attach(struct MPT3SAS_ADAPTER *ioc) | |||
4428 | goto out_free_resources; | 4587 | goto out_free_resources; |
4429 | } | 4588 | } |
4430 | 4589 | ||
4590 | ioc->rdpq_array_enable_assigned = 0; | ||
4591 | ioc->dma_mask = 0; | ||
4431 | r = mpt3sas_base_map_resources(ioc); | 4592 | r = mpt3sas_base_map_resources(ioc); |
4432 | if (r) | 4593 | if (r) |
4433 | goto out_free_resources; | 4594 | goto out_free_resources; |
@@ -4804,6 +4965,12 @@ mpt3sas_base_hard_reset_handler(struct MPT3SAS_ADAPTER *ioc, int sleep_flag, | |||
4804 | r = _base_get_ioc_facts(ioc, CAN_SLEEP); | 4965 | r = _base_get_ioc_facts(ioc, CAN_SLEEP); |
4805 | if (r) | 4966 | if (r) |
4806 | goto out; | 4967 | goto out; |
4968 | |||
4969 | if (ioc->rdpq_array_enable && !ioc->rdpq_array_capable) | ||
4970 | panic("%s: Issue occurred with flashing controller firmware." | ||
4971 | "Please reboot the system and ensure that the correct" | ||
4972 | " firmware version is running\n", ioc->name); | ||
4973 | |||
4807 | r = _base_make_ioc_operational(ioc, sleep_flag); | 4974 | r = _base_make_ioc_operational(ioc, sleep_flag); |
4808 | if (!r) | 4975 | if (!r) |
4809 | _base_reset_handler(ioc, MPT3_IOC_DONE_RESET); | 4976 | _base_reset_handler(ioc, MPT3_IOC_DONE_RESET); |