.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-or-later |
---|
1 | 2 | /* |
---|
2 | 3 | * Linux MegaRAID driver for SAS based RAID controllers |
---|
3 | 4 | * |
---|
4 | 5 | * Copyright (c) 2009-2013 LSI Corporation |
---|
5 | | - * Copyright (c) 2013-2014 Avago Technologies |
---|
6 | | - * |
---|
7 | | - * This program is free software; you can redistribute it and/or |
---|
8 | | - * modify it under the terms of the GNU General Public License |
---|
9 | | - * as published by the Free Software Foundation; either version 2 |
---|
10 | | - * of the License, or (at your option) any later version. |
---|
11 | | - * |
---|
12 | | - * This program is distributed in the hope that it will be useful, |
---|
13 | | - * but WITHOUT ANY WARRANTY; without even the implied warranty of |
---|
14 | | - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
---|
15 | | - * GNU General Public License for more details. |
---|
16 | | - * |
---|
17 | | - * You should have received a copy of the GNU General Public License |
---|
18 | | - * along with this program. If not, see <http://www.gnu.org/licenses/>. |
---|
| 6 | + * Copyright (c) 2013-2016 Avago Technologies |
---|
| 7 | + * Copyright (c) 2016-2018 Broadcom Inc. |
---|
19 | 8 | * |
---|
20 | 9 | * FILE: megaraid_sas_fp.c |
---|
21 | 10 | * |
---|
22 | | - * Authors: Avago Technologies |
---|
| 11 | + * Authors: Broadcom Inc. |
---|
23 | 12 | * Sumant Patro |
---|
24 | 13 | * Varad Talamacki |
---|
25 | 14 | * Manoj Jose |
---|
26 | | - * Kashyap Desai <kashyap.desai@avagotech.com> |
---|
27 | | - * Sumit Saxena <sumit.saxena@avagotech.com> |
---|
| 15 | + * Kashyap Desai <kashyap.desai@broadcom.com> |
---|
| 16 | + * Sumit Saxena <sumit.saxena@broadcom.com> |
---|
28 | 17 | * |
---|
29 | | - * Send feedback to: megaraidlinux.pdl@avagotech.com |
---|
30 | | - * |
---|
31 | | - * Mail to: Avago Technologies, 350 West Trimble Road, Building 90, |
---|
32 | | - * San Jose, California 95131 |
---|
| 18 | + * Send feedback to: megaraidlinux.pdl@broadcom.com |
---|
33 | 19 | */ |
---|
34 | 20 | |
---|
35 | 21 | #include <linux/kernel.h> |
---|
.. | .. |
---|
47 | 33 | #include <linux/compat.h> |
---|
48 | 34 | #include <linux/blkdev.h> |
---|
49 | 35 | #include <linux/poll.h> |
---|
| 36 | +#include <linux/irq_poll.h> |
---|
50 | 37 | |
---|
51 | 38 | #include <scsi/scsi.h> |
---|
52 | 39 | #include <scsi/scsi_cmnd.h> |
---|
.. | .. |
---|
59 | 46 | |
---|
60 | 47 | #define LB_PENDING_CMDS_DEFAULT 4 |
---|
61 | 48 | static unsigned int lb_pending_cmds = LB_PENDING_CMDS_DEFAULT; |
---|
62 | | -module_param(lb_pending_cmds, int, S_IRUGO); |
---|
| 49 | +module_param(lb_pending_cmds, int, 0444); |
---|
63 | 50 | MODULE_PARM_DESC(lb_pending_cmds, "Change raid-1 load balancing outstanding " |
---|
64 | 51 | "threshold. Valid Values are 1-128. Default: 4"); |
---|
65 | 52 | |
---|
.. | .. |
---|
93 | 80 | } |
---|
94 | 81 | |
---|
95 | 82 | /** |
---|
96 | | - * @param dividend : Dividend |
---|
97 | | - * @param divisor : Divisor |
---|
| 83 | + * mega_div64_32 - Do a 64-bit division |
---|
| 84 | + * @dividend: Dividend |
---|
| 85 | + * @divisor: Divisor |
---|
98 | 86 | * |
---|
99 | 87 | * @return quotient |
---|
100 | 88 | **/ |
---|
101 | | -u64 mega_div64_32(uint64_t dividend, uint32_t divisor) |
---|
| 89 | +static u64 mega_div64_32(uint64_t dividend, uint32_t divisor) |
---|
102 | 90 | { |
---|
103 | | - u32 remainder; |
---|
104 | | - u64 d; |
---|
| 91 | + u64 d = dividend; |
---|
105 | 92 | |
---|
106 | 93 | if (!divisor) |
---|
107 | 94 | printk(KERN_ERR "megasas : DIVISOR is zero in mod fn\n"); |
---|
108 | 95 | |
---|
109 | | - d = dividend; |
---|
110 | | - remainder = do_div(d, divisor); |
---|
| 96 | + do_div(d, divisor); |
---|
111 | 97 | |
---|
112 | 98 | return d; |
---|
113 | 99 | } |
---|
.. | .. |
---|
363 | 349 | |
---|
364 | 350 | num_lds = le16_to_cpu(drv_map->raidMap.ldCount); |
---|
365 | 351 | |
---|
| 352 | + memcpy(instance->ld_ids_prev, |
---|
| 353 | + instance->ld_ids_from_raidmap, |
---|
| 354 | + sizeof(instance->ld_ids_from_raidmap)); |
---|
| 355 | + memset(instance->ld_ids_from_raidmap, 0xff, MEGASAS_MAX_LD_IDS); |
---|
366 | 356 | /*Convert Raid capability values to CPU arch */ |
---|
367 | 357 | for (i = 0; (num_lds > 0) && (i < MAX_LOGICAL_DRIVES_EXT); i++) { |
---|
368 | 358 | ld = MR_TargetIdToLdGet(i, drv_map); |
---|
369 | 359 | |
---|
370 | 360 | /* For non existing VDs, iterate to next VD*/ |
---|
371 | | - if (ld >= (MAX_LOGICAL_DRIVES_EXT - 1)) |
---|
| 361 | + if (ld >= MEGASAS_MAX_SUPPORTED_LD_IDS) |
---|
372 | 362 | continue; |
---|
373 | 363 | |
---|
374 | 364 | raid = MR_LdRaidGet(ld, drv_map); |
---|
375 | 365 | le32_to_cpus((u32 *)&raid->capability); |
---|
376 | | - |
---|
| 366 | + instance->ld_ids_from_raidmap[i] = i; |
---|
377 | 367 | num_lds--; |
---|
378 | 368 | } |
---|
379 | 369 | |
---|
380 | 370 | return 1; |
---|
381 | 371 | } |
---|
382 | 372 | |
---|
383 | | -u32 MR_GetSpanBlock(u32 ld, u64 row, u64 *span_blk, |
---|
| 373 | +static u32 MR_GetSpanBlock(u32 ld, u64 row, u64 *span_blk, |
---|
384 | 374 | struct MR_DRV_RAID_MAP_ALL *map) |
---|
385 | 375 | { |
---|
386 | 376 | struct MR_SPAN_BLOCK_INFO *pSpanBlock = MR_LdSpanInfoGet(ld, map); |
---|
.. | .. |
---|
399 | 389 | le64_to_cpu(quad->logEnd) && (mega_mod64(row - le64_to_cpu(quad->logStart), |
---|
400 | 390 | le32_to_cpu(quad->diff))) == 0) { |
---|
401 | 391 | if (span_blk != NULL) { |
---|
402 | | - u64 blk, debugBlk; |
---|
| 392 | + u64 blk; |
---|
403 | 393 | blk = mega_div64_32((row-le64_to_cpu(quad->logStart)), le32_to_cpu(quad->diff)); |
---|
404 | | - debugBlk = blk; |
---|
405 | 394 | |
---|
406 | 395 | blk = (blk + le64_to_cpu(quad->offsetInSpan)) << raid->stripeShift; |
---|
407 | 396 | *span_blk = blk; |
---|
.. | .. |
---|
431 | 420 | * div_error - Devide error code. |
---|
432 | 421 | */ |
---|
433 | 422 | |
---|
434 | | -u32 mr_spanset_get_span_block(struct megasas_instance *instance, |
---|
| 423 | +static u32 mr_spanset_get_span_block(struct megasas_instance *instance, |
---|
435 | 424 | u32 ld, u64 row, u64 *span_blk, struct MR_DRV_RAID_MAP_ALL *map) |
---|
436 | 425 | { |
---|
437 | 426 | struct fusion_context *fusion = instance->ctrl_context; |
---|
.. | .. |
---|
656 | 645 | } |
---|
657 | 646 | |
---|
658 | 647 | /* This Function will return Phys arm */ |
---|
659 | | -u8 get_arm(struct megasas_instance *instance, u32 ld, u8 span, u64 stripe, |
---|
| 648 | +static u8 get_arm(struct megasas_instance *instance, u32 ld, u8 span, u64 stripe, |
---|
660 | 649 | struct MR_DRV_RAID_MAP_ALL *map) |
---|
661 | 650 | { |
---|
662 | 651 | struct MR_LD_RAID *raid = MR_LdRaidGet(ld, map); |
---|
.. | .. |
---|
712 | 701 | __le16 *pDevHandle = &io_info->devHandle; |
---|
713 | 702 | u8 *pPdInterface = &io_info->pd_interface; |
---|
714 | 703 | u32 logArm, rowMod, armQ, arm; |
---|
715 | | - struct fusion_context *fusion; |
---|
716 | 704 | |
---|
717 | | - fusion = instance->ctrl_context; |
---|
718 | 705 | *pDevHandle = cpu_to_le16(MR_DEVHANDLE_INVALID); |
---|
719 | 706 | |
---|
720 | 707 | /*Get row and span from io_info for Uneven Span IO.*/ |
---|
.. | .. |
---|
745 | 732 | *pDevHandle = MR_PdDevHandleGet(pd, map); |
---|
746 | 733 | *pPdInterface = MR_PdInterfaceTypeGet(pd, map); |
---|
747 | 734 | /* get second pd also for raid 1/10 fast path writes*/ |
---|
748 | | - if ((instance->adapter_type == VENTURA_SERIES) && |
---|
| 735 | + if ((instance->adapter_type >= VENTURA_SERIES) && |
---|
749 | 736 | (raid->level == 1) && |
---|
750 | 737 | !io_info->isRead) { |
---|
751 | 738 | r1_alt_pd = MR_ArPdGet(arRef, physArm + 1, map); |
---|
.. | .. |
---|
770 | 757 | } |
---|
771 | 758 | |
---|
772 | 759 | *pdBlock += stripRef + le64_to_cpu(MR_LdSpanPtrGet(ld, span, map)->startBlk); |
---|
773 | | - if (instance->adapter_type == VENTURA_SERIES) { |
---|
| 760 | + if (instance->adapter_type >= VENTURA_SERIES) { |
---|
774 | 761 | ((struct RAID_CONTEXT_G35 *)pRAID_Context)->span_arm = |
---|
775 | 762 | (span << RAID_CTX_SPANARM_SPAN_SHIFT) | physArm; |
---|
776 | 763 | io_info->span_arm = |
---|
.. | .. |
---|
801 | 788 | * span - Span number |
---|
802 | 789 | * block - Absolute Block number in the physical disk |
---|
803 | 790 | */ |
---|
804 | | -u8 MR_GetPhyParams(struct megasas_instance *instance, u32 ld, u64 stripRow, |
---|
| 791 | +static u8 MR_GetPhyParams(struct megasas_instance *instance, u32 ld, u64 stripRow, |
---|
805 | 792 | u16 stripRef, struct IO_REQUEST_INFO *io_info, |
---|
806 | 793 | struct RAID_CONTEXT *pRAID_Context, |
---|
807 | 794 | struct MR_DRV_RAID_MAP_ALL *map) |
---|
.. | .. |
---|
814 | 801 | u64 *pdBlock = &io_info->pdBlock; |
---|
815 | 802 | __le16 *pDevHandle = &io_info->devHandle; |
---|
816 | 803 | u8 *pPdInterface = &io_info->pd_interface; |
---|
817 | | - struct fusion_context *fusion; |
---|
818 | 804 | |
---|
819 | | - fusion = instance->ctrl_context; |
---|
820 | 805 | *pDevHandle = cpu_to_le16(MR_DEVHANDLE_INVALID); |
---|
821 | 806 | |
---|
822 | 807 | row = mega_div64_32(stripRow, raid->rowDataSize); |
---|
.. | .. |
---|
861 | 846 | *pDevHandle = MR_PdDevHandleGet(pd, map); |
---|
862 | 847 | *pPdInterface = MR_PdInterfaceTypeGet(pd, map); |
---|
863 | 848 | /* get second pd also for raid 1/10 fast path writes*/ |
---|
864 | | - if ((instance->adapter_type == VENTURA_SERIES) && |
---|
| 849 | + if ((instance->adapter_type >= VENTURA_SERIES) && |
---|
865 | 850 | (raid->level == 1) && |
---|
866 | 851 | !io_info->isRead) { |
---|
867 | 852 | r1_alt_pd = MR_ArPdGet(arRef, physArm + 1, map); |
---|
.. | .. |
---|
888 | 873 | } |
---|
889 | 874 | |
---|
890 | 875 | *pdBlock += stripRef + le64_to_cpu(MR_LdSpanPtrGet(ld, span, map)->startBlk); |
---|
891 | | - if (instance->adapter_type == VENTURA_SERIES) { |
---|
| 876 | + if (instance->adapter_type >= VENTURA_SERIES) { |
---|
892 | 877 | ((struct RAID_CONTEXT_G35 *)pRAID_Context)->span_arm = |
---|
893 | 878 | (span << RAID_CTX_SPANARM_SPAN_SHIFT) | physArm; |
---|
894 | 879 | io_info->span_arm = |
---|
.. | .. |
---|
900 | 885 | } |
---|
901 | 886 | io_info->pd_after_lb = pd; |
---|
902 | 887 | return retval; |
---|
| 888 | +} |
---|
| 889 | + |
---|
| 890 | +/* |
---|
| 891 | + * mr_get_phy_params_r56_rmw - Calculate parameters for R56 CTIO write operation |
---|
| 892 | + * @instance: Adapter soft state |
---|
| 893 | + * @ld: LD index |
---|
| 894 | + * @stripNo: Strip Number |
---|
| 895 | + * @io_info: IO info structure pointer |
---|
| 896 | + * pRAID_Context: RAID context pointer |
---|
| 897 | + * map: RAID map pointer |
---|
| 898 | + * |
---|
| 899 | + * This routine calculates the logical arm, data Arm, row number and parity arm |
---|
| 900 | + * for R56 CTIO write operation. |
---|
| 901 | + */ |
---|
| 902 | +static void mr_get_phy_params_r56_rmw(struct megasas_instance *instance, |
---|
| 903 | + u32 ld, u64 stripNo, |
---|
| 904 | + struct IO_REQUEST_INFO *io_info, |
---|
| 905 | + struct RAID_CONTEXT_G35 *pRAID_Context, |
---|
| 906 | + struct MR_DRV_RAID_MAP_ALL *map) |
---|
| 907 | +{ |
---|
| 908 | + struct MR_LD_RAID *raid = MR_LdRaidGet(ld, map); |
---|
| 909 | + u8 span, dataArms, arms, dataArm, logArm; |
---|
| 910 | + s8 rightmostParityArm, PParityArm; |
---|
| 911 | + u64 rowNum; |
---|
| 912 | + u64 *pdBlock = &io_info->pdBlock; |
---|
| 913 | + |
---|
| 914 | + dataArms = raid->rowDataSize; |
---|
| 915 | + arms = raid->rowSize; |
---|
| 916 | + |
---|
| 917 | + rowNum = mega_div64_32(stripNo, dataArms); |
---|
| 918 | + /* parity disk arm, first arm is 0 */ |
---|
| 919 | + rightmostParityArm = (arms - 1) - mega_mod64(rowNum, arms); |
---|
| 920 | + |
---|
| 921 | + /* logical arm within row */ |
---|
| 922 | + logArm = mega_mod64(stripNo, dataArms); |
---|
| 923 | + /* physical arm for data */ |
---|
| 924 | + dataArm = mega_mod64((rightmostParityArm + 1 + logArm), arms); |
---|
| 925 | + |
---|
| 926 | + if (raid->spanDepth == 1) { |
---|
| 927 | + span = 0; |
---|
| 928 | + } else { |
---|
| 929 | + span = (u8)MR_GetSpanBlock(ld, rowNum, pdBlock, map); |
---|
| 930 | + if (span == SPAN_INVALID) |
---|
| 931 | + return; |
---|
| 932 | + } |
---|
| 933 | + |
---|
| 934 | + if (raid->level == 6) { |
---|
| 935 | + /* P Parity arm, note this can go negative adjust if negative */ |
---|
| 936 | + PParityArm = (arms - 2) - mega_mod64(rowNum, arms); |
---|
| 937 | + |
---|
| 938 | + if (PParityArm < 0) |
---|
| 939 | + PParityArm += arms; |
---|
| 940 | + |
---|
| 941 | + /* rightmostParityArm is P-Parity for RAID 5 and Q-Parity for RAID */ |
---|
| 942 | + pRAID_Context->flow_specific.r56_arm_map = rightmostParityArm; |
---|
| 943 | + pRAID_Context->flow_specific.r56_arm_map |= |
---|
| 944 | + (u16)(PParityArm << RAID_CTX_R56_P_ARM_SHIFT); |
---|
| 945 | + } else { |
---|
| 946 | + pRAID_Context->flow_specific.r56_arm_map |= |
---|
| 947 | + (u16)(rightmostParityArm << RAID_CTX_R56_P_ARM_SHIFT); |
---|
| 948 | + } |
---|
| 949 | + |
---|
| 950 | + pRAID_Context->reg_lock_row_lba = cpu_to_le64(rowNum); |
---|
| 951 | + pRAID_Context->flow_specific.r56_arm_map |= |
---|
| 952 | + (u16)(logArm << RAID_CTX_R56_LOG_ARM_SHIFT); |
---|
| 953 | + cpu_to_le16s(&pRAID_Context->flow_specific.r56_arm_map); |
---|
| 954 | + pRAID_Context->span_arm = (span << RAID_CTX_SPANARM_SPAN_SHIFT) | dataArm; |
---|
| 955 | + pRAID_Context->raid_flags = (MR_RAID_FLAGS_IO_SUB_TYPE_R56_DIV_OFFLOAD << |
---|
| 956 | + MR_RAID_CTX_RAID_FLAGS_IO_SUB_TYPE_SHIFT); |
---|
| 957 | + |
---|
| 958 | + return; |
---|
903 | 959 | } |
---|
904 | 960 | |
---|
905 | 961 | /* |
---|
.. | .. |
---|
968 | 1024 | stripSize = 1 << raid->stripeShift; |
---|
969 | 1025 | stripe_mask = stripSize-1; |
---|
970 | 1026 | |
---|
| 1027 | + io_info->data_arms = raid->rowDataSize; |
---|
971 | 1028 | |
---|
972 | 1029 | /* |
---|
973 | 1030 | * calculate starting row and stripe, and number of strips and rows |
---|
.. | .. |
---|
1109 | 1166 | /* save pointer to raid->LUN array */ |
---|
1110 | 1167 | *raidLUN = raid->LUN; |
---|
1111 | 1168 | |
---|
| 1169 | + /* Aero R5/6 Division Offload for WRITE */ |
---|
| 1170 | + if (fusion->r56_div_offload && (raid->level >= 5) && !isRead) { |
---|
| 1171 | + mr_get_phy_params_r56_rmw(instance, ld, start_strip, io_info, |
---|
| 1172 | + (struct RAID_CONTEXT_G35 *)pRAID_Context, |
---|
| 1173 | + map); |
---|
| 1174 | + return true; |
---|
| 1175 | + } |
---|
1112 | 1176 | |
---|
1113 | 1177 | /*Get Phy Params only if FP capable, or else leave it to MR firmware |
---|
1114 | 1178 | to do the calculation.*/ |
---|
.. | .. |
---|
1281 | 1345 | } |
---|
1282 | 1346 | } |
---|
1283 | 1347 | |
---|
1284 | | -u8 megasas_get_best_arm_pd(struct megasas_instance *instance, |
---|
| 1348 | +static u8 megasas_get_best_arm_pd(struct megasas_instance *instance, |
---|
1285 | 1349 | struct LD_LOAD_BALANCE_INFO *lbInfo, |
---|
1286 | 1350 | struct IO_REQUEST_INFO *io_info, |
---|
1287 | 1351 | struct MR_DRV_RAID_MAP_ALL *drv_map) |
---|