]>
Commit | Line | Data |
---|---|---|
9c915a8c AR |
1 | /* |
2 | * Linux MegaRAID driver for SAS based RAID controllers | |
3 | * | |
e399065b SS |
4 | * Copyright (c) 2009-2013 LSI Corporation |
5 | * Copyright (c) 2013-2014 Avago Technologies | |
9c915a8c AR |
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 | |
e399065b | 18 | * along with this program. If not, see <http://www.gnu.org/licenses/>. |
9c915a8c AR |
19 | * |
20 | * FILE: megaraid_sas_fp.c | |
21 | * | |
e399065b | 22 | * Authors: Avago Technologies |
9c915a8c AR |
23 | * Sumant Patro |
24 | * Varad Talamacki | |
25 | * Manoj Jose | |
e399065b SS |
26 | * Kashyap Desai <kashyap.desai@avagotech.com> |
27 | * Sumit Saxena <sumit.saxena@avagotech.com> | |
9c915a8c | 28 | * |
e399065b | 29 | * Send feedback to: megaraidlinux.pdl@avagotech.com |
9c915a8c | 30 | * |
e399065b SS |
31 | * Mail to: Avago Technologies, 350 West Trimble Road, Building 90, |
32 | * San Jose, California 95131 | |
9c915a8c AR |
33 | */ |
34 | ||
35 | #include <linux/kernel.h> | |
36 | #include <linux/types.h> | |
37 | #include <linux/pci.h> | |
38 | #include <linux/list.h> | |
39 | #include <linux/moduleparam.h> | |
40 | #include <linux/module.h> | |
41 | #include <linux/spinlock.h> | |
42 | #include <linux/interrupt.h> | |
43 | #include <linux/delay.h> | |
9c915a8c AR |
44 | #include <linux/uio.h> |
45 | #include <linux/uaccess.h> | |
46 | #include <linux/fs.h> | |
47 | #include <linux/compat.h> | |
48 | #include <linux/blkdev.h> | |
49 | #include <linux/poll.h> | |
50 | ||
51 | #include <scsi/scsi.h> | |
52 | #include <scsi/scsi_cmnd.h> | |
53 | #include <scsi/scsi_device.h> | |
54 | #include <scsi/scsi_host.h> | |
55 | ||
56 | #include "megaraid_sas_fusion.h" | |
36807e67 | 57 | #include "megaraid_sas.h" |
9c915a8c AR |
58 | #include <asm/div64.h> |
59 | ||
d2552ebe SS |
60 | #define LB_PENDING_CMDS_DEFAULT 4 |
61 | static unsigned int lb_pending_cmds = LB_PENDING_CMDS_DEFAULT; | |
62 | module_param(lb_pending_cmds, int, S_IRUGO); | |
63 | MODULE_PARM_DESC(lb_pending_cmds, "Change raid-1 load balancing outstanding " | |
64 | "threshold. Valid Values are 1-128. Default: 4"); | |
65 | ||
66 | ||
9c915a8c AR |
67 | #define ABS_DIFF(a, b) (((a) > (b)) ? ((a) - (b)) : ((b) - (a))) |
68 | #define MR_LD_STATE_OPTIMAL 3 | |
ad466c6c SS |
69 | |
70 | #ifdef FALSE | |
71 | #undef FALSE | |
72 | #endif | |
9c915a8c | 73 | #define FALSE 0 |
ad466c6c SS |
74 | |
75 | #ifdef TRUE | |
76 | #undef TRUE | |
77 | #endif | |
9c915a8c AR |
78 | #define TRUE 1 |
79 | ||
bc93d425 SS |
80 | #define SPAN_ROW_SIZE(map, ld, index_) (MR_LdSpanPtrGet(ld, index_, map)->spanRowSize) |
81 | #define SPAN_ROW_DATA_SIZE(map_, ld, index_) (MR_LdSpanPtrGet(ld, index_, map)->spanRowDataSize) | |
82 | #define SPAN_INVALID 0xff | |
83 | ||
9c915a8c | 84 | /* Prototypes */ |
51087a86 | 85 | static void mr_update_span_set(struct MR_DRV_RAID_MAP_ALL *map, |
bc93d425 SS |
86 | PLD_SPAN_INFO ldSpanInfo); |
87 | static u8 mr_spanset_get_phy_params(struct megasas_instance *instance, u32 ld, | |
88 | u64 stripRow, u16 stripRef, struct IO_REQUEST_INFO *io_info, | |
51087a86 | 89 | struct RAID_CONTEXT *pRAID_Context, struct MR_DRV_RAID_MAP_ALL *map); |
bc93d425 | 90 | static u64 get_row_from_strip(struct megasas_instance *instance, u32 ld, |
51087a86 | 91 | u64 strip, struct MR_DRV_RAID_MAP_ALL *map); |
9c915a8c AR |
92 | |
93 | u32 mega_mod64(u64 dividend, u32 divisor) | |
94 | { | |
95 | u64 d; | |
96 | u32 remainder; | |
97 | ||
98 | if (!divisor) | |
99 | printk(KERN_ERR "megasas : DIVISOR is zero, in div fn\n"); | |
100 | d = dividend; | |
101 | remainder = do_div(d, divisor); | |
102 | return remainder; | |
103 | } | |
104 | ||
105 | /** | |
106 | * @param dividend : Dividend | |
107 | * @param divisor : Divisor | |
108 | * | |
109 | * @return quotient | |
110 | **/ | |
111 | u64 mega_div64_32(uint64_t dividend, uint32_t divisor) | |
112 | { | |
113 | u32 remainder; | |
114 | u64 d; | |
115 | ||
116 | if (!divisor) | |
117 | printk(KERN_ERR "megasas : DIVISOR is zero in mod fn\n"); | |
118 | ||
119 | d = dividend; | |
120 | remainder = do_div(d, divisor); | |
121 | ||
122 | return d; | |
123 | } | |
124 | ||
51087a86 | 125 | struct MR_LD_RAID *MR_LdRaidGet(u32 ld, struct MR_DRV_RAID_MAP_ALL *map) |
9c915a8c AR |
126 | { |
127 | return &map->raidMap.ldSpanMap[ld].ldRaid; | |
128 | } | |
129 | ||
130 | static struct MR_SPAN_BLOCK_INFO *MR_LdSpanInfoGet(u32 ld, | |
51087a86 | 131 | struct MR_DRV_RAID_MAP_ALL |
9c915a8c AR |
132 | *map) |
133 | { | |
134 | return &map->raidMap.ldSpanMap[ld].spanBlock[0]; | |
135 | } | |
136 | ||
51087a86 | 137 | static u8 MR_LdDataArmGet(u32 ld, u32 armIdx, struct MR_DRV_RAID_MAP_ALL *map) |
9c915a8c AR |
138 | { |
139 | return map->raidMap.ldSpanMap[ld].dataArmMap[armIdx]; | |
140 | } | |
141 | ||
51087a86 | 142 | u16 MR_ArPdGet(u32 ar, u32 arm, struct MR_DRV_RAID_MAP_ALL *map) |
9c915a8c | 143 | { |
94cd65dd | 144 | return le16_to_cpu(map->raidMap.arMapInfo[ar].pd[arm]); |
9c915a8c AR |
145 | } |
146 | ||
51087a86 | 147 | u16 MR_LdSpanArrayGet(u32 ld, u32 span, struct MR_DRV_RAID_MAP_ALL *map) |
9c915a8c | 148 | { |
94cd65dd | 149 | return le16_to_cpu(map->raidMap.ldSpanMap[ld].spanBlock[span].span.arrayRef); |
9c915a8c AR |
150 | } |
151 | ||
9ab9ed38 | 152 | __le16 MR_PdDevHandleGet(u32 pd, struct MR_DRV_RAID_MAP_ALL *map) |
9c915a8c AR |
153 | { |
154 | return map->raidMap.devHndlInfo[pd].curDevHdl; | |
155 | } | |
156 | ||
33203bc4 S |
157 | static u8 MR_PdInterfaceTypeGet(u32 pd, struct MR_DRV_RAID_MAP_ALL *map) |
158 | { | |
159 | return map->raidMap.devHndlInfo[pd].interfaceType; | |
160 | } | |
161 | ||
51087a86 | 162 | u16 MR_GetLDTgtId(u32 ld, struct MR_DRV_RAID_MAP_ALL *map) |
9c915a8c | 163 | { |
be26374b | 164 | return le16_to_cpu(map->raidMap.ldSpanMap[ld].ldRaid.targetId); |
9c915a8c AR |
165 | } |
166 | ||
d2d0358b | 167 | u16 MR_TargetIdToLdGet(u32 ldTgtId, struct MR_DRV_RAID_MAP_ALL *map) |
9c915a8c | 168 | { |
be26374b | 169 | return map->raidMap.ldTgtIdToLd[ldTgtId]; |
9c915a8c AR |
170 | } |
171 | ||
172 | static struct MR_LD_SPAN *MR_LdSpanPtrGet(u32 ld, u32 span, | |
51087a86 | 173 | struct MR_DRV_RAID_MAP_ALL *map) |
9c915a8c AR |
174 | { |
175 | return &map->raidMap.ldSpanMap[ld].spanBlock[span].span; | |
176 | } | |
177 | ||
51087a86 SS |
178 | /* |
179 | * This function will Populate Driver Map using firmware raid map | |
180 | */ | |
181 | void MR_PopulateDrvRaidMap(struct megasas_instance *instance) | |
182 | { | |
183 | struct fusion_context *fusion = instance->ctrl_context; | |
184 | struct MR_FW_RAID_MAP_ALL *fw_map_old = NULL; | |
185 | struct MR_FW_RAID_MAP *pFwRaidMap = NULL; | |
d889344e | 186 | int i, j; |
200aed58 | 187 | u16 ld_count; |
d889344e SC |
188 | struct MR_FW_RAID_MAP_DYNAMIC *fw_map_dyn; |
189 | struct MR_FW_RAID_MAP_EXT *fw_map_ext; | |
190 | struct MR_RAID_MAP_DESC_TABLE *desc_table; | |
51087a86 SS |
191 | |
192 | ||
193 | struct MR_DRV_RAID_MAP_ALL *drv_map = | |
194 | fusion->ld_drv_map[(instance->map_id & 1)]; | |
195 | struct MR_DRV_RAID_MAP *pDrvRaidMap = &drv_map->raidMap; | |
d889344e SC |
196 | void *raid_map_data = NULL; |
197 | ||
198 | memset(drv_map, 0, fusion->drv_map_sz); | |
199 | memset(pDrvRaidMap->ldTgtIdToLd, | |
41064f1b | 200 | 0xff, (sizeof(u16) * MAX_LOGICAL_DRIVES_DYN)); |
d889344e SC |
201 | |
202 | if (instance->max_raid_mapsize) { | |
203 | fw_map_dyn = fusion->ld_map[(instance->map_id & 1)]; | |
d889344e SC |
204 | desc_table = |
205 | (struct MR_RAID_MAP_DESC_TABLE *)((void *)fw_map_dyn + le32_to_cpu(fw_map_dyn->desc_table_offset)); | |
206 | if (desc_table != fw_map_dyn->raid_map_desc_table) | |
207 | dev_dbg(&instance->pdev->dev, "offsets of desc table are not matching desc %p original %p\n", | |
208 | desc_table, fw_map_dyn->raid_map_desc_table); | |
209 | ||
210 | ld_count = (u16)le16_to_cpu(fw_map_dyn->ld_count); | |
211 | pDrvRaidMap->ldCount = (__le16)cpu_to_le16(ld_count); | |
212 | pDrvRaidMap->fpPdIoTimeoutSec = | |
213 | fw_map_dyn->fp_pd_io_timeout_sec; | |
a174118b S |
214 | pDrvRaidMap->totalSize = |
215 | cpu_to_le32(sizeof(struct MR_DRV_RAID_MAP_ALL)); | |
d889344e SC |
216 | /* point to actual data starting point*/ |
217 | raid_map_data = (void *)fw_map_dyn + | |
218 | le32_to_cpu(fw_map_dyn->desc_table_offset) + | |
219 | le32_to_cpu(fw_map_dyn->desc_table_size); | |
220 | ||
221 | for (i = 0; i < le32_to_cpu(fw_map_dyn->desc_table_num_elements); ++i) { | |
d889344e SC |
222 | switch (le32_to_cpu(desc_table->raid_map_desc_type)) { |
223 | case RAID_MAP_DESC_TYPE_DEVHDL_INFO: | |
224 | fw_map_dyn->dev_hndl_info = | |
225 | (struct MR_DEV_HANDLE_INFO *)(raid_map_data + le32_to_cpu(desc_table->raid_map_desc_offset)); | |
d889344e | 226 | memcpy(pDrvRaidMap->devHndlInfo, |
41064f1b S |
227 | fw_map_dyn->dev_hndl_info, |
228 | sizeof(struct MR_DEV_HANDLE_INFO) * | |
229 | le32_to_cpu(desc_table->raid_map_desc_elements)); | |
d889344e SC |
230 | break; |
231 | case RAID_MAP_DESC_TYPE_TGTID_INFO: | |
232 | fw_map_dyn->ld_tgt_id_to_ld = | |
41064f1b S |
233 | (u16 *)(raid_map_data + |
234 | le32_to_cpu(desc_table->raid_map_desc_offset)); | |
235 | for (j = 0; j < le32_to_cpu(desc_table->raid_map_desc_elements); j++) { | |
236 | pDrvRaidMap->ldTgtIdToLd[j] = | |
237 | le16_to_cpu(fw_map_dyn->ld_tgt_id_to_ld[j]); | |
238 | } | |
d889344e SC |
239 | break; |
240 | case RAID_MAP_DESC_TYPE_ARRAY_INFO: | |
241 | fw_map_dyn->ar_map_info = | |
41064f1b S |
242 | (struct MR_ARRAY_INFO *) |
243 | (raid_map_data + le32_to_cpu(desc_table->raid_map_desc_offset)); | |
d889344e | 244 | memcpy(pDrvRaidMap->arMapInfo, |
41064f1b S |
245 | fw_map_dyn->ar_map_info, |
246 | sizeof(struct MR_ARRAY_INFO) * | |
247 | le32_to_cpu(desc_table->raid_map_desc_elements)); | |
d889344e SC |
248 | break; |
249 | case RAID_MAP_DESC_TYPE_SPAN_INFO: | |
250 | fw_map_dyn->ld_span_map = | |
41064f1b S |
251 | (struct MR_LD_SPAN_MAP *) |
252 | (raid_map_data + | |
253 | le32_to_cpu(desc_table->raid_map_desc_offset)); | |
d889344e | 254 | memcpy(pDrvRaidMap->ldSpanMap, |
41064f1b S |
255 | fw_map_dyn->ld_span_map, |
256 | sizeof(struct MR_LD_SPAN_MAP) * | |
257 | le32_to_cpu(desc_table->raid_map_desc_elements)); | |
d889344e SC |
258 | break; |
259 | default: | |
260 | dev_dbg(&instance->pdev->dev, "wrong number of desctableElements %d\n", | |
261 | fw_map_dyn->desc_table_num_elements); | |
262 | } | |
263 | ++desc_table; | |
264 | } | |
265 | ||
266 | } else if (instance->supportmax256vd) { | |
267 | fw_map_ext = | |
41064f1b | 268 | (struct MR_FW_RAID_MAP_EXT *)fusion->ld_map[(instance->map_id & 1)]; |
d889344e SC |
269 | ld_count = (u16)le16_to_cpu(fw_map_ext->ldCount); |
270 | if (ld_count > MAX_LOGICAL_DRIVES_EXT) { | |
271 | dev_dbg(&instance->pdev->dev, "megaraid_sas: LD count exposed in RAID map in not valid\n"); | |
272 | return; | |
273 | } | |
d889344e SC |
274 | |
275 | pDrvRaidMap->ldCount = (__le16)cpu_to_le16(ld_count); | |
276 | pDrvRaidMap->fpPdIoTimeoutSec = fw_map_ext->fpPdIoTimeoutSec; | |
277 | for (i = 0; i < (MAX_LOGICAL_DRIVES_EXT); i++) | |
278 | pDrvRaidMap->ldTgtIdToLd[i] = | |
279 | (u16)fw_map_ext->ldTgtIdToLd[i]; | |
280 | memcpy(pDrvRaidMap->ldSpanMap, fw_map_ext->ldSpanMap, | |
41064f1b | 281 | sizeof(struct MR_LD_SPAN_MAP) * ld_count); |
d889344e | 282 | memcpy(pDrvRaidMap->arMapInfo, fw_map_ext->arMapInfo, |
41064f1b | 283 | sizeof(struct MR_ARRAY_INFO) * MAX_API_ARRAYS_EXT); |
d889344e | 284 | memcpy(pDrvRaidMap->devHndlInfo, fw_map_ext->devHndlInfo, |
41064f1b S |
285 | sizeof(struct MR_DEV_HANDLE_INFO) * |
286 | MAX_RAIDMAP_PHYSICAL_DEVICES); | |
51087a86 | 287 | |
51087a86 SS |
288 | /* New Raid map will not set totalSize, so keep expected value |
289 | * for legacy code in ValidateMapInfo | |
290 | */ | |
6e755ddc SS |
291 | pDrvRaidMap->totalSize = |
292 | cpu_to_le32(sizeof(struct MR_FW_RAID_MAP_EXT)); | |
51087a86 SS |
293 | } else { |
294 | fw_map_old = (struct MR_FW_RAID_MAP_ALL *) | |
295 | fusion->ld_map[(instance->map_id & 1)]; | |
296 | pFwRaidMap = &fw_map_old->raidMap; | |
200aed58 | 297 | ld_count = (u16)le32_to_cpu(pFwRaidMap->ldCount); |
51087a86 | 298 | pDrvRaidMap->totalSize = pFwRaidMap->totalSize; |
200aed58 | 299 | pDrvRaidMap->ldCount = (__le16)cpu_to_le16(ld_count); |
51087a86 SS |
300 | pDrvRaidMap->fpPdIoTimeoutSec = pFwRaidMap->fpPdIoTimeoutSec; |
301 | for (i = 0; i < MAX_RAIDMAP_LOGICAL_DRIVES + MAX_RAIDMAP_VIEWS; i++) | |
302 | pDrvRaidMap->ldTgtIdToLd[i] = | |
303 | (u8)pFwRaidMap->ldTgtIdToLd[i]; | |
200aed58 | 304 | for (i = 0; i < ld_count; i++) { |
51087a86 | 305 | pDrvRaidMap->ldSpanMap[i] = pFwRaidMap->ldSpanMap[i]; |
51087a86 SS |
306 | } |
307 | memcpy(pDrvRaidMap->arMapInfo, pFwRaidMap->arMapInfo, | |
308 | sizeof(struct MR_ARRAY_INFO) * MAX_RAIDMAP_ARRAYS); | |
309 | memcpy(pDrvRaidMap->devHndlInfo, pFwRaidMap->devHndlInfo, | |
310 | sizeof(struct MR_DEV_HANDLE_INFO) * | |
311 | MAX_RAIDMAP_PHYSICAL_DEVICES); | |
312 | } | |
313 | } | |
314 | ||
9c915a8c AR |
315 | /* |
316 | * This function will validate Map info data provided by FW | |
317 | */ | |
bc93d425 | 318 | u8 MR_ValidateMapInfo(struct megasas_instance *instance) |
9c915a8c | 319 | { |
51087a86 SS |
320 | struct fusion_context *fusion; |
321 | struct MR_DRV_RAID_MAP_ALL *drv_map; | |
322 | struct MR_DRV_RAID_MAP *pDrvRaidMap; | |
323 | struct LD_LOAD_BALANCE_INFO *lbInfo; | |
324 | PLD_SPAN_INFO ldSpanInfo; | |
94cd65dd | 325 | struct MR_LD_RAID *raid; |
a09454ce | 326 | u16 num_lds, i; |
94cd65dd | 327 | u16 ld; |
51087a86 | 328 | u32 expected_size; |
94cd65dd | 329 | |
9c915a8c | 330 | |
51087a86 SS |
331 | MR_PopulateDrvRaidMap(instance); |
332 | ||
333 | fusion = instance->ctrl_context; | |
334 | drv_map = fusion->ld_drv_map[(instance->map_id & 1)]; | |
335 | pDrvRaidMap = &drv_map->raidMap; | |
336 | ||
337 | lbInfo = fusion->load_balance_info; | |
338 | ldSpanInfo = fusion->log_to_span; | |
339 | ||
d889344e SC |
340 | if (instance->max_raid_mapsize) |
341 | expected_size = sizeof(struct MR_DRV_RAID_MAP_ALL); | |
342 | else if (instance->supportmax256vd) | |
51087a86 SS |
343 | expected_size = sizeof(struct MR_FW_RAID_MAP_EXT); |
344 | else | |
345 | expected_size = | |
346 | (sizeof(struct MR_FW_RAID_MAP) - sizeof(struct MR_LD_SPAN_MAP) + | |
6e755ddc | 347 | (sizeof(struct MR_LD_SPAN_MAP) * le16_to_cpu(pDrvRaidMap->ldCount))); |
51087a86 SS |
348 | |
349 | if (le32_to_cpu(pDrvRaidMap->totalSize) != expected_size) { | |
d889344e SC |
350 | dev_dbg(&instance->pdev->dev, "megasas: map info structure size 0x%x", |
351 | le32_to_cpu(pDrvRaidMap->totalSize)); | |
352 | dev_dbg(&instance->pdev->dev, "is not matching expected size 0x%x\n", | |
41064f1b | 353 | (unsigned int)expected_size); |
51087a86 SS |
354 | dev_err(&instance->pdev->dev, "megasas: span map %x, pDrvRaidMap->totalSize : %x\n", |
355 | (unsigned int)sizeof(struct MR_LD_SPAN_MAP), | |
356 | le32_to_cpu(pDrvRaidMap->totalSize)); | |
9c915a8c AR |
357 | return 0; |
358 | } | |
359 | ||
bc93d425 | 360 | if (instance->UnevenSpanSupport) |
51087a86 | 361 | mr_update_span_set(drv_map, ldSpanInfo); |
bc93d425 | 362 | |
5fc499b6 S |
363 | if (lbInfo) |
364 | mr_update_load_balance_params(drv_map, lbInfo); | |
9c915a8c | 365 | |
6e755ddc | 366 | num_lds = le16_to_cpu(drv_map->raidMap.ldCount); |
94cd65dd SS |
367 | |
368 | /*Convert Raid capability values to CPU arch */ | |
a09454ce S |
369 | for (i = 0; (num_lds > 0) && (i < MAX_LOGICAL_DRIVES_EXT); i++) { |
370 | ld = MR_TargetIdToLdGet(i, drv_map); | |
371 | ||
372 | /* For non existing VDs, iterate to next VD*/ | |
373 | if (ld >= (MAX_LOGICAL_DRIVES_EXT - 1)) | |
374 | continue; | |
375 | ||
51087a86 | 376 | raid = MR_LdRaidGet(ld, drv_map); |
94cd65dd | 377 | le32_to_cpus((u32 *)&raid->capability); |
a09454ce S |
378 | |
379 | num_lds--; | |
94cd65dd SS |
380 | } |
381 | ||
9c915a8c AR |
382 | return 1; |
383 | } | |
384 | ||
385 | u32 MR_GetSpanBlock(u32 ld, u64 row, u64 *span_blk, | |
51087a86 | 386 | struct MR_DRV_RAID_MAP_ALL *map) |
9c915a8c AR |
387 | { |
388 | struct MR_SPAN_BLOCK_INFO *pSpanBlock = MR_LdSpanInfoGet(ld, map); | |
389 | struct MR_QUAD_ELEMENT *quad; | |
390 | struct MR_LD_RAID *raid = MR_LdRaidGet(ld, map); | |
391 | u32 span, j; | |
392 | ||
393 | for (span = 0; span < raid->spanDepth; span++, pSpanBlock++) { | |
394 | ||
94cd65dd | 395 | for (j = 0; j < le32_to_cpu(pSpanBlock->block_span_info.noElements); j++) { |
9c915a8c AR |
396 | quad = &pSpanBlock->block_span_info.quad[j]; |
397 | ||
94cd65dd | 398 | if (le32_to_cpu(quad->diff) == 0) |
bc93d425 | 399 | return SPAN_INVALID; |
94cd65dd SS |
400 | if (le64_to_cpu(quad->logStart) <= row && row <= |
401 | le64_to_cpu(quad->logEnd) && (mega_mod64(row - le64_to_cpu(quad->logStart), | |
402 | le32_to_cpu(quad->diff))) == 0) { | |
9c915a8c AR |
403 | if (span_blk != NULL) { |
404 | u64 blk, debugBlk; | |
94cd65dd | 405 | blk = mega_div64_32((row-le64_to_cpu(quad->logStart)), le32_to_cpu(quad->diff)); |
9c915a8c AR |
406 | debugBlk = blk; |
407 | ||
94cd65dd | 408 | blk = (blk + le64_to_cpu(quad->offsetInSpan)) << raid->stripeShift; |
9c915a8c AR |
409 | *span_blk = blk; |
410 | } | |
411 | return span; | |
412 | } | |
413 | } | |
414 | } | |
bc93d425 SS |
415 | return SPAN_INVALID; |
416 | } | |
417 | ||
bc93d425 SS |
418 | /* |
419 | ****************************************************************************** | |
420 | * | |
421 | * This routine calculates the Span block for given row using spanset. | |
422 | * | |
423 | * Inputs : | |
424 | * instance - HBA instance | |
425 | * ld - Logical drive number | |
426 | * row - Row number | |
427 | * map - LD map | |
428 | * | |
429 | * Outputs : | |
430 | * | |
431 | * span - Span number | |
432 | * block - Absolute Block number in the physical disk | |
433 | * div_error - Devide error code. | |
434 | */ | |
435 | ||
436 | u32 mr_spanset_get_span_block(struct megasas_instance *instance, | |
51087a86 | 437 | u32 ld, u64 row, u64 *span_blk, struct MR_DRV_RAID_MAP_ALL *map) |
bc93d425 SS |
438 | { |
439 | struct fusion_context *fusion = instance->ctrl_context; | |
440 | struct MR_LD_RAID *raid = MR_LdRaidGet(ld, map); | |
441 | LD_SPAN_SET *span_set; | |
442 | struct MR_QUAD_ELEMENT *quad; | |
443 | u32 span, info; | |
444 | PLD_SPAN_INFO ldSpanInfo = fusion->log_to_span; | |
445 | ||
446 | for (info = 0; info < MAX_QUAD_DEPTH; info++) { | |
447 | span_set = &(ldSpanInfo[ld].span_set[info]); | |
448 | ||
449 | if (span_set->span_row_data_width == 0) | |
450 | break; | |
451 | ||
452 | if (row > span_set->data_row_end) | |
453 | continue; | |
454 | ||
455 | for (span = 0; span < raid->spanDepth; span++) | |
94cd65dd SS |
456 | if (le32_to_cpu(map->raidMap.ldSpanMap[ld].spanBlock[span]. |
457 | block_span_info.noElements) >= info+1) { | |
bc93d425 SS |
458 | quad = &map->raidMap.ldSpanMap[ld]. |
459 | spanBlock[span]. | |
460 | block_span_info.quad[info]; | |
6e755ddc | 461 | if (le32_to_cpu(quad->diff) == 0) |
bc93d425 | 462 | return SPAN_INVALID; |
94cd65dd SS |
463 | if (le64_to_cpu(quad->logStart) <= row && |
464 | row <= le64_to_cpu(quad->logEnd) && | |
465 | (mega_mod64(row - le64_to_cpu(quad->logStart), | |
466 | le32_to_cpu(quad->diff))) == 0) { | |
bc93d425 SS |
467 | if (span_blk != NULL) { |
468 | u64 blk; | |
469 | blk = mega_div64_32 | |
94cd65dd SS |
470 | ((row - le64_to_cpu(quad->logStart)), |
471 | le32_to_cpu(quad->diff)); | |
472 | blk = (blk + le64_to_cpu(quad->offsetInSpan)) | |
bc93d425 SS |
473 | << raid->stripeShift; |
474 | *span_blk = blk; | |
475 | } | |
476 | return span; | |
477 | } | |
478 | } | |
479 | } | |
480 | return SPAN_INVALID; | |
481 | } | |
482 | ||
483 | /* | |
484 | ****************************************************************************** | |
485 | * | |
486 | * This routine calculates the row for given strip using spanset. | |
487 | * | |
488 | * Inputs : | |
489 | * instance - HBA instance | |
490 | * ld - Logical drive number | |
491 | * Strip - Strip | |
492 | * map - LD map | |
493 | * | |
494 | * Outputs : | |
495 | * | |
496 | * row - row associated with strip | |
497 | */ | |
498 | ||
499 | static u64 get_row_from_strip(struct megasas_instance *instance, | |
51087a86 | 500 | u32 ld, u64 strip, struct MR_DRV_RAID_MAP_ALL *map) |
bc93d425 SS |
501 | { |
502 | struct fusion_context *fusion = instance->ctrl_context; | |
503 | struct MR_LD_RAID *raid = MR_LdRaidGet(ld, map); | |
504 | LD_SPAN_SET *span_set; | |
505 | PLD_SPAN_INFO ldSpanInfo = fusion->log_to_span; | |
506 | u32 info, strip_offset, span, span_offset; | |
507 | u64 span_set_Strip, span_set_Row, retval; | |
508 | ||
509 | for (info = 0; info < MAX_QUAD_DEPTH; info++) { | |
510 | span_set = &(ldSpanInfo[ld].span_set[info]); | |
511 | ||
512 | if (span_set->span_row_data_width == 0) | |
513 | break; | |
514 | if (strip > span_set->data_strip_end) | |
515 | continue; | |
516 | ||
517 | span_set_Strip = strip - span_set->data_strip_start; | |
518 | strip_offset = mega_mod64(span_set_Strip, | |
519 | span_set->span_row_data_width); | |
520 | span_set_Row = mega_div64_32(span_set_Strip, | |
521 | span_set->span_row_data_width) * span_set->diff; | |
522 | for (span = 0, span_offset = 0; span < raid->spanDepth; span++) | |
94cd65dd | 523 | if (le32_to_cpu(map->raidMap.ldSpanMap[ld].spanBlock[span]. |
6e755ddc | 524 | block_span_info.noElements) >= info+1) { |
bc93d425 SS |
525 | if (strip_offset >= |
526 | span_set->strip_offset[span]) | |
527 | span_offset++; | |
528 | else | |
529 | break; | |
530 | } | |
e00731bc | 531 | |
bc93d425 SS |
532 | retval = (span_set->data_row_start + span_set_Row + |
533 | (span_offset - 1)); | |
534 | return retval; | |
535 | } | |
536 | return -1LLU; | |
537 | } | |
538 | ||
539 | ||
540 | /* | |
541 | ****************************************************************************** | |
542 | * | |
543 | * This routine calculates the Start Strip for given row using spanset. | |
544 | * | |
545 | * Inputs : | |
546 | * instance - HBA instance | |
547 | * ld - Logical drive number | |
548 | * row - Row number | |
549 | * map - LD map | |
550 | * | |
551 | * Outputs : | |
552 | * | |
553 | * Strip - Start strip associated with row | |
554 | */ | |
555 | ||
556 | static u64 get_strip_from_row(struct megasas_instance *instance, | |
51087a86 | 557 | u32 ld, u64 row, struct MR_DRV_RAID_MAP_ALL *map) |
bc93d425 SS |
558 | { |
559 | struct fusion_context *fusion = instance->ctrl_context; | |
560 | struct MR_LD_RAID *raid = MR_LdRaidGet(ld, map); | |
561 | LD_SPAN_SET *span_set; | |
562 | struct MR_QUAD_ELEMENT *quad; | |
563 | PLD_SPAN_INFO ldSpanInfo = fusion->log_to_span; | |
564 | u32 span, info; | |
565 | u64 strip; | |
566 | ||
567 | for (info = 0; info < MAX_QUAD_DEPTH; info++) { | |
568 | span_set = &(ldSpanInfo[ld].span_set[info]); | |
569 | ||
570 | if (span_set->span_row_data_width == 0) | |
571 | break; | |
572 | if (row > span_set->data_row_end) | |
573 | continue; | |
574 | ||
575 | for (span = 0; span < raid->spanDepth; span++) | |
94cd65dd SS |
576 | if (le32_to_cpu(map->raidMap.ldSpanMap[ld].spanBlock[span]. |
577 | block_span_info.noElements) >= info+1) { | |
bc93d425 SS |
578 | quad = &map->raidMap.ldSpanMap[ld]. |
579 | spanBlock[span].block_span_info.quad[info]; | |
94cd65dd SS |
580 | if (le64_to_cpu(quad->logStart) <= row && |
581 | row <= le64_to_cpu(quad->logEnd) && | |
582 | mega_mod64((row - le64_to_cpu(quad->logStart)), | |
583 | le32_to_cpu(quad->diff)) == 0) { | |
bc93d425 SS |
584 | strip = mega_div64_32 |
585 | (((row - span_set->data_row_start) | |
94cd65dd SS |
586 | - le64_to_cpu(quad->logStart)), |
587 | le32_to_cpu(quad->diff)); | |
bc93d425 SS |
588 | strip *= span_set->span_row_data_width; |
589 | strip += span_set->data_strip_start; | |
590 | strip += span_set->strip_offset[span]; | |
591 | return strip; | |
592 | } | |
593 | } | |
594 | } | |
595 | dev_err(&instance->pdev->dev, "get_strip_from_row" | |
596 | "returns invalid strip for ld=%x, row=%lx\n", | |
597 | ld, (long unsigned int)row); | |
598 | return -1; | |
599 | } | |
600 | ||
601 | /* | |
602 | ****************************************************************************** | |
603 | * | |
604 | * This routine calculates the Physical Arm for given strip using spanset. | |
605 | * | |
606 | * Inputs : | |
607 | * instance - HBA instance | |
608 | * ld - Logical drive number | |
609 | * strip - Strip | |
610 | * map - LD map | |
611 | * | |
612 | * Outputs : | |
613 | * | |
614 | * Phys Arm - Phys Arm associated with strip | |
615 | */ | |
616 | ||
617 | static u32 get_arm_from_strip(struct megasas_instance *instance, | |
51087a86 | 618 | u32 ld, u64 strip, struct MR_DRV_RAID_MAP_ALL *map) |
bc93d425 SS |
619 | { |
620 | struct fusion_context *fusion = instance->ctrl_context; | |
621 | struct MR_LD_RAID *raid = MR_LdRaidGet(ld, map); | |
622 | LD_SPAN_SET *span_set; | |
623 | PLD_SPAN_INFO ldSpanInfo = fusion->log_to_span; | |
624 | u32 info, strip_offset, span, span_offset, retval; | |
625 | ||
626 | for (info = 0 ; info < MAX_QUAD_DEPTH; info++) { | |
627 | span_set = &(ldSpanInfo[ld].span_set[info]); | |
628 | ||
629 | if (span_set->span_row_data_width == 0) | |
630 | break; | |
631 | if (strip > span_set->data_strip_end) | |
632 | continue; | |
633 | ||
634 | strip_offset = (uint)mega_mod64 | |
635 | ((strip - span_set->data_strip_start), | |
636 | span_set->span_row_data_width); | |
637 | ||
638 | for (span = 0, span_offset = 0; span < raid->spanDepth; span++) | |
94cd65dd SS |
639 | if (le32_to_cpu(map->raidMap.ldSpanMap[ld].spanBlock[span]. |
640 | block_span_info.noElements) >= info+1) { | |
bc93d425 SS |
641 | if (strip_offset >= |
642 | span_set->strip_offset[span]) | |
643 | span_offset = | |
644 | span_set->strip_offset[span]; | |
645 | else | |
646 | break; | |
647 | } | |
e00731bc | 648 | |
bc93d425 SS |
649 | retval = (strip_offset - span_offset); |
650 | return retval; | |
651 | } | |
652 | ||
653 | dev_err(&instance->pdev->dev, "get_arm_from_strip" | |
654 | "returns invalid arm for ld=%x strip=%lx\n", | |
655 | ld, (long unsigned int)strip); | |
656 | ||
657 | return -1; | |
658 | } | |
659 | ||
660 | /* This Function will return Phys arm */ | |
661 | u8 get_arm(struct megasas_instance *instance, u32 ld, u8 span, u64 stripe, | |
51087a86 | 662 | struct MR_DRV_RAID_MAP_ALL *map) |
bc93d425 SS |
663 | { |
664 | struct MR_LD_RAID *raid = MR_LdRaidGet(ld, map); | |
665 | /* Need to check correct default value */ | |
666 | u32 arm = 0; | |
667 | ||
668 | switch (raid->level) { | |
669 | case 0: | |
670 | case 5: | |
671 | case 6: | |
672 | arm = mega_mod64(stripe, SPAN_ROW_SIZE(map, ld, span)); | |
673 | break; | |
674 | case 1: | |
675 | /* start with logical arm */ | |
676 | arm = get_arm_from_strip(instance, ld, stripe, map); | |
fec3c1b4 | 677 | if (arm != -1U) |
bc93d425 SS |
678 | arm *= 2; |
679 | break; | |
680 | } | |
681 | ||
682 | return arm; | |
683 | } | |
684 | ||
685 | ||
686 | /* | |
687 | ****************************************************************************** | |
688 | * | |
689 | * This routine calculates the arm, span and block for the specified stripe and | |
690 | * reference in stripe using spanset | |
691 | * | |
692 | * Inputs : | |
693 | * | |
694 | * ld - Logical drive number | |
695 | * stripRow - Stripe number | |
696 | * stripRef - Reference in stripe | |
697 | * | |
698 | * Outputs : | |
699 | * | |
700 | * span - Span number | |
701 | * block - Absolute Block number in the physical disk | |
702 | */ | |
703 | static u8 mr_spanset_get_phy_params(struct megasas_instance *instance, u32 ld, | |
704 | u64 stripRow, u16 stripRef, struct IO_REQUEST_INFO *io_info, | |
705 | struct RAID_CONTEXT *pRAID_Context, | |
51087a86 | 706 | struct MR_DRV_RAID_MAP_ALL *map) |
bc93d425 SS |
707 | { |
708 | struct MR_LD_RAID *raid = MR_LdRaidGet(ld, map); | |
69c337c0 | 709 | u32 pd, arRef, r1_alt_pd; |
bc93d425 SS |
710 | u8 physArm, span; |
711 | u64 row; | |
712 | u8 retval = TRUE; | |
bc93d425 | 713 | u64 *pdBlock = &io_info->pdBlock; |
9ab9ed38 | 714 | __le16 *pDevHandle = &io_info->devHandle; |
33203bc4 | 715 | u8 *pPdInterface = &io_info->pd_interface; |
bc93d425 | 716 | u32 logArm, rowMod, armQ, arm; |
5a8cb85b | 717 | struct fusion_context *fusion; |
bc93d425 | 718 | |
5a8cb85b | 719 | fusion = instance->ctrl_context; |
b41c0a4a | 720 | *pDevHandle = cpu_to_le16(MR_DEVHANDLE_INVALID); |
bc93d425 SS |
721 | |
722 | /*Get row and span from io_info for Uneven Span IO.*/ | |
723 | row = io_info->start_row; | |
724 | span = io_info->start_span; | |
725 | ||
726 | ||
727 | if (raid->level == 6) { | |
728 | logArm = get_arm_from_strip(instance, ld, stripRow, map); | |
fec3c1b4 | 729 | if (logArm == -1U) |
bc93d425 SS |
730 | return FALSE; |
731 | rowMod = mega_mod64(row, SPAN_ROW_SIZE(map, ld, span)); | |
732 | armQ = SPAN_ROW_SIZE(map, ld, span) - 1 - rowMod; | |
733 | arm = armQ + 1 + logArm; | |
734 | if (arm >= SPAN_ROW_SIZE(map, ld, span)) | |
735 | arm -= SPAN_ROW_SIZE(map, ld, span); | |
736 | physArm = (u8)arm; | |
737 | } else | |
738 | /* Calculate the arm */ | |
739 | physArm = get_arm(instance, ld, span, stripRow, map); | |
740 | if (physArm == 0xFF) | |
741 | return FALSE; | |
742 | ||
743 | arRef = MR_LdSpanArrayGet(ld, span, map); | |
744 | pd = MR_ArPdGet(arRef, physArm, map); | |
745 | ||
69c337c0 | 746 | if (pd != MR_PD_INVALID) { |
bc93d425 | 747 | *pDevHandle = MR_PdDevHandleGet(pd, map); |
33203bc4 | 748 | *pPdInterface = MR_PdInterfaceTypeGet(pd, map); |
69c337c0 | 749 | /* get second pd also for raid 1/10 fast path writes*/ |
33203bc4 S |
750 | if (instance->is_ventura && |
751 | (raid->level == 1) && | |
752 | !io_info->isRead) { | |
69c337c0 SC |
753 | r1_alt_pd = MR_ArPdGet(arRef, physArm + 1, map); |
754 | if (r1_alt_pd != MR_PD_INVALID) | |
755 | io_info->r1_alt_dev_handle = | |
756 | MR_PdDevHandleGet(r1_alt_pd, map); | |
757 | } | |
758 | } else { | |
bc93d425 | 759 | if ((raid->level >= 5) && |
5a8cb85b | 760 | ((fusion->adapter_type == THUNDERBOLT_SERIES) || |
761 | ((fusion->adapter_type == INVADER_SERIES) && | |
bc93d425 | 762 | (raid->regTypeReqOnRead != REGION_TYPE_UNUSED)))) |
d889344e | 763 | pRAID_Context->reg_lock_flags = REGION_TYPE_EXCLUSIVE; |
bc93d425 | 764 | else if (raid->level == 1) { |
b3e3827b KD |
765 | physArm = physArm + 1; |
766 | pd = MR_ArPdGet(arRef, physArm, map); | |
33203bc4 | 767 | if (pd != MR_PD_INVALID) { |
bc93d425 | 768 | *pDevHandle = MR_PdDevHandleGet(pd, map); |
33203bc4 S |
769 | *pPdInterface = MR_PdInterfaceTypeGet(pd, map); |
770 | } | |
bc93d425 SS |
771 | } |
772 | } | |
773 | ||
94cd65dd | 774 | *pdBlock += stripRef + le64_to_cpu(MR_LdSpanPtrGet(ld, span, map)->startBlk); |
d889344e | 775 | if (instance->is_ventura) { |
41064f1b | 776 | ((struct RAID_CONTEXT_G35 *)pRAID_Context)->span_arm = |
d889344e SC |
777 | (span << RAID_CTX_SPANARM_SPAN_SHIFT) | physArm; |
778 | io_info->span_arm = | |
779 | (span << RAID_CTX_SPANARM_SPAN_SHIFT) | physArm; | |
780 | } else { | |
781 | pRAID_Context->span_arm = | |
782 | (span << RAID_CTX_SPANARM_SPAN_SHIFT) | physArm; | |
783 | io_info->span_arm = pRAID_Context->span_arm; | |
784 | } | |
b41c0a4a | 785 | io_info->pd_after_lb = pd; |
bc93d425 | 786 | return retval; |
9c915a8c AR |
787 | } |
788 | ||
789 | /* | |
790 | ****************************************************************************** | |
791 | * | |
792 | * This routine calculates the arm, span and block for the specified stripe and | |
793 | * reference in stripe. | |
794 | * | |
795 | * Inputs : | |
796 | * | |
797 | * ld - Logical drive number | |
798 | * stripRow - Stripe number | |
799 | * stripRef - Reference in stripe | |
800 | * | |
801 | * Outputs : | |
802 | * | |
803 | * span - Span number | |
804 | * block - Absolute Block number in the physical disk | |
805 | */ | |
36807e67 | 806 | u8 MR_GetPhyParams(struct megasas_instance *instance, u32 ld, u64 stripRow, |
bc93d425 SS |
807 | u16 stripRef, struct IO_REQUEST_INFO *io_info, |
808 | struct RAID_CONTEXT *pRAID_Context, | |
51087a86 | 809 | struct MR_DRV_RAID_MAP_ALL *map) |
9c915a8c AR |
810 | { |
811 | struct MR_LD_RAID *raid = MR_LdRaidGet(ld, map); | |
69c337c0 | 812 | u32 pd, arRef, r1_alt_pd; |
9c915a8c AR |
813 | u8 physArm, span; |
814 | u64 row; | |
815 | u8 retval = TRUE; | |
bc93d425 | 816 | u64 *pdBlock = &io_info->pdBlock; |
9ab9ed38 | 817 | __le16 *pDevHandle = &io_info->devHandle; |
33203bc4 | 818 | u8 *pPdInterface = &io_info->pd_interface; |
5a8cb85b | 819 | struct fusion_context *fusion; |
820 | ||
821 | fusion = instance->ctrl_context; | |
b41c0a4a | 822 | *pDevHandle = cpu_to_le16(MR_DEVHANDLE_INVALID); |
9c915a8c AR |
823 | |
824 | row = mega_div64_32(stripRow, raid->rowDataSize); | |
825 | ||
826 | if (raid->level == 6) { | |
827 | /* logical arm within row */ | |
828 | u32 logArm = mega_mod64(stripRow, raid->rowDataSize); | |
829 | u32 rowMod, armQ, arm; | |
830 | ||
831 | if (raid->rowSize == 0) | |
832 | return FALSE; | |
833 | /* get logical row mod */ | |
834 | rowMod = mega_mod64(row, raid->rowSize); | |
835 | armQ = raid->rowSize-1-rowMod; /* index of Q drive */ | |
836 | arm = armQ+1+logArm; /* data always logically follows Q */ | |
837 | if (arm >= raid->rowSize) /* handle wrap condition */ | |
838 | arm -= raid->rowSize; | |
839 | physArm = (u8)arm; | |
840 | } else { | |
841 | if (raid->modFactor == 0) | |
842 | return FALSE; | |
843 | physArm = MR_LdDataArmGet(ld, mega_mod64(stripRow, | |
844 | raid->modFactor), | |
845 | map); | |
846 | } | |
847 | ||
848 | if (raid->spanDepth == 1) { | |
849 | span = 0; | |
850 | *pdBlock = row << raid->stripeShift; | |
851 | } else { | |
bc93d425 SS |
852 | span = (u8)MR_GetSpanBlock(ld, row, pdBlock, map); |
853 | if (span == SPAN_INVALID) | |
9c915a8c AR |
854 | return FALSE; |
855 | } | |
856 | ||
857 | /* Get the array on which this span is present */ | |
858 | arRef = MR_LdSpanArrayGet(ld, span, map); | |
859 | pd = MR_ArPdGet(arRef, physArm, map); /* Get the pd */ | |
860 | ||
69c337c0 | 861 | if (pd != MR_PD_INVALID) { |
9c915a8c AR |
862 | /* Get dev handle from Pd. */ |
863 | *pDevHandle = MR_PdDevHandleGet(pd, map); | |
33203bc4 | 864 | *pPdInterface = MR_PdInterfaceTypeGet(pd, map); |
69c337c0 | 865 | /* get second pd also for raid 1/10 fast path writes*/ |
33203bc4 S |
866 | if (instance->is_ventura && |
867 | (raid->level == 1) && | |
868 | !io_info->isRead) { | |
69c337c0 SC |
869 | r1_alt_pd = MR_ArPdGet(arRef, physArm + 1, map); |
870 | if (r1_alt_pd != MR_PD_INVALID) | |
871 | io_info->r1_alt_dev_handle = | |
33203bc4 | 872 | MR_PdDevHandleGet(r1_alt_pd, map); |
69c337c0 SC |
873 | } |
874 | } else { | |
36807e67 | 875 | if ((raid->level >= 5) && |
5a8cb85b | 876 | ((fusion->adapter_type == THUNDERBOLT_SERIES) || |
877 | ((fusion->adapter_type == INVADER_SERIES) && | |
21d3c710 | 878 | (raid->regTypeReqOnRead != REGION_TYPE_UNUSED)))) |
d889344e | 879 | pRAID_Context->reg_lock_flags = REGION_TYPE_EXCLUSIVE; |
9c915a8c AR |
880 | else if (raid->level == 1) { |
881 | /* Get alternate Pd. */ | |
b3e3827b KD |
882 | physArm = physArm + 1; |
883 | pd = MR_ArPdGet(arRef, physArm, map); | |
33203bc4 | 884 | if (pd != MR_PD_INVALID) { |
9c915a8c AR |
885 | /* Get dev handle from Pd */ |
886 | *pDevHandle = MR_PdDevHandleGet(pd, map); | |
33203bc4 S |
887 | *pPdInterface = MR_PdInterfaceTypeGet(pd, map); |
888 | } | |
9c915a8c | 889 | } |
9c915a8c AR |
890 | } |
891 | ||
94cd65dd | 892 | *pdBlock += stripRef + le64_to_cpu(MR_LdSpanPtrGet(ld, span, map)->startBlk); |
d889344e | 893 | if (instance->is_ventura) { |
41064f1b | 894 | ((struct RAID_CONTEXT_G35 *)pRAID_Context)->span_arm = |
d889344e SC |
895 | (span << RAID_CTX_SPANARM_SPAN_SHIFT) | physArm; |
896 | io_info->span_arm = | |
897 | (span << RAID_CTX_SPANARM_SPAN_SHIFT) | physArm; | |
898 | } else { | |
899 | pRAID_Context->span_arm = | |
900 | (span << RAID_CTX_SPANARM_SPAN_SHIFT) | physArm; | |
901 | io_info->span_arm = pRAID_Context->span_arm; | |
902 | } | |
b41c0a4a | 903 | io_info->pd_after_lb = pd; |
9c915a8c AR |
904 | return retval; |
905 | } | |
906 | ||
907 | /* | |
908 | ****************************************************************************** | |
909 | * | |
910 | * MR_BuildRaidContext function | |
911 | * | |
912 | * This function will initiate command processing. The start/end row and strip | |
913 | * information is calculated then the lock is acquired. | |
914 | * This function will return 0 if region lock was acquired OR return num strips | |
915 | */ | |
916 | u8 | |
36807e67 AR |
917 | MR_BuildRaidContext(struct megasas_instance *instance, |
918 | struct IO_REQUEST_INFO *io_info, | |
9c915a8c | 919 | struct RAID_CONTEXT *pRAID_Context, |
51087a86 | 920 | struct MR_DRV_RAID_MAP_ALL *map, u8 **raidLUN) |
9c915a8c | 921 | { |
5a8cb85b | 922 | struct fusion_context *fusion; |
9c915a8c | 923 | struct MR_LD_RAID *raid; |
d2d0358b | 924 | u32 stripSize, stripe_mask; |
9c915a8c AR |
925 | u64 endLba, endStrip, endRow, start_row, start_strip; |
926 | u64 regStart; | |
927 | u32 regSize; | |
928 | u8 num_strips, numRows; | |
929 | u16 ref_in_start_stripe, ref_in_end_stripe; | |
930 | u64 ldStartBlock; | |
931 | u32 numBlocks, ldTgtId; | |
932 | u8 isRead; | |
933 | u8 retval = 0; | |
bc93d425 SS |
934 | u8 startlba_span = SPAN_INVALID; |
935 | u64 *pdBlock = &io_info->pdBlock; | |
d2d0358b | 936 | u16 ld; |
9c915a8c AR |
937 | |
938 | ldStartBlock = io_info->ldStartBlock; | |
939 | numBlocks = io_info->numBlocks; | |
940 | ldTgtId = io_info->ldTgtId; | |
941 | isRead = io_info->isRead; | |
bc93d425 SS |
942 | io_info->IoforUnevenSpan = 0; |
943 | io_info->start_span = SPAN_INVALID; | |
5a8cb85b | 944 | fusion = instance->ctrl_context; |
9c915a8c AR |
945 | |
946 | ld = MR_TargetIdToLdGet(ldTgtId, map); | |
947 | raid = MR_LdRaidGet(ld, map); | |
fdd84e25 SC |
948 | /*check read ahead bit*/ |
949 | io_info->ra_capable = raid->capability.ra_capable; | |
9c915a8c | 950 | |
bc93d425 SS |
951 | /* |
952 | * if rowDataSize @RAID map and spanRowDataSize @SPAN INFO are zero | |
953 | * return FALSE | |
954 | */ | |
955 | if (raid->rowDataSize == 0) { | |
956 | if (MR_LdSpanPtrGet(ld, 0, map)->spanRowDataSize == 0) | |
957 | return FALSE; | |
958 | else if (instance->UnevenSpanSupport) { | |
959 | io_info->IoforUnevenSpan = 1; | |
960 | } else { | |
961 | dev_info(&instance->pdev->dev, | |
962 | "raid->rowDataSize is 0, but has SPAN[0]" | |
963 | "rowDataSize = 0x%0x," | |
964 | "but there is _NO_ UnevenSpanSupport\n", | |
965 | MR_LdSpanPtrGet(ld, 0, map)->spanRowDataSize); | |
966 | return FALSE; | |
967 | } | |
968 | } | |
969 | ||
9c915a8c AR |
970 | stripSize = 1 << raid->stripeShift; |
971 | stripe_mask = stripSize-1; | |
bc93d425 SS |
972 | |
973 | ||
9c915a8c AR |
974 | /* |
975 | * calculate starting row and stripe, and number of strips and rows | |
976 | */ | |
977 | start_strip = ldStartBlock >> raid->stripeShift; | |
978 | ref_in_start_stripe = (u16)(ldStartBlock & stripe_mask); | |
979 | endLba = ldStartBlock + numBlocks - 1; | |
980 | ref_in_end_stripe = (u16)(endLba & stripe_mask); | |
981 | endStrip = endLba >> raid->stripeShift; | |
982 | num_strips = (u8)(endStrip - start_strip + 1); /* End strip */ | |
bc93d425 SS |
983 | |
984 | if (io_info->IoforUnevenSpan) { | |
985 | start_row = get_row_from_strip(instance, ld, start_strip, map); | |
986 | endRow = get_row_from_strip(instance, ld, endStrip, map); | |
987 | if (start_row == -1ULL || endRow == -1ULL) { | |
988 | dev_info(&instance->pdev->dev, "return from %s %d." | |
989 | "Send IO w/o region lock.\n", | |
990 | __func__, __LINE__); | |
991 | return FALSE; | |
992 | } | |
993 | ||
994 | if (raid->spanDepth == 1) { | |
995 | startlba_span = 0; | |
996 | *pdBlock = start_row << raid->stripeShift; | |
997 | } else | |
998 | startlba_span = (u8)mr_spanset_get_span_block(instance, | |
999 | ld, start_row, pdBlock, map); | |
1000 | if (startlba_span == SPAN_INVALID) { | |
1001 | dev_info(&instance->pdev->dev, "return from %s %d" | |
1002 | "for row 0x%llx,start strip %llx" | |
1003 | "endSrip %llx\n", __func__, __LINE__, | |
1004 | (unsigned long long)start_row, | |
1005 | (unsigned long long)start_strip, | |
1006 | (unsigned long long)endStrip); | |
1007 | return FALSE; | |
1008 | } | |
1009 | io_info->start_span = startlba_span; | |
1010 | io_info->start_row = start_row; | |
bc93d425 SS |
1011 | } else { |
1012 | start_row = mega_div64_32(start_strip, raid->rowDataSize); | |
1013 | endRow = mega_div64_32(endStrip, raid->rowDataSize); | |
1014 | } | |
1015 | numRows = (u8)(endRow - start_row + 1); | |
9c915a8c AR |
1016 | |
1017 | /* | |
1018 | * calculate region info. | |
1019 | */ | |
1020 | ||
1021 | /* assume region is at the start of the first row */ | |
1022 | regStart = start_row << raid->stripeShift; | |
1023 | /* assume this IO needs the full row - we'll adjust if not true */ | |
1024 | regSize = stripSize; | |
1025 | ||
8f05024c SS |
1026 | io_info->do_fp_rlbypass = raid->capability.fpBypassRegionLock; |
1027 | ||
c1529fa2 AR |
1028 | /* Check if we can send this I/O via FastPath */ |
1029 | if (raid->capability.fpCapable) { | |
1030 | if (isRead) | |
1031 | io_info->fpOkForIo = (raid->capability.fpReadCapable && | |
1032 | ((num_strips == 1) || | |
1033 | raid->capability. | |
1034 | fpReadAcrossStripe)); | |
1035 | else | |
1036 | io_info->fpOkForIo = (raid->capability.fpWriteCapable && | |
1037 | ((num_strips == 1) || | |
1038 | raid->capability. | |
1039 | fpWriteAcrossStripe)); | |
1040 | } else | |
9c915a8c | 1041 | io_info->fpOkForIo = FALSE; |
9c915a8c AR |
1042 | |
1043 | if (numRows == 1) { | |
1044 | /* single-strip IOs can always lock only the data needed */ | |
1045 | if (num_strips == 1) { | |
1046 | regStart += ref_in_start_stripe; | |
1047 | regSize = numBlocks; | |
1048 | } | |
1049 | /* multi-strip IOs always need to full stripe locked */ | |
bc93d425 SS |
1050 | } else if (io_info->IoforUnevenSpan == 0) { |
1051 | /* | |
1052 | * For Even span region lock optimization. | |
1053 | * If the start strip is the last in the start row | |
1054 | */ | |
9c915a8c | 1055 | if (start_strip == (start_row + 1) * raid->rowDataSize - 1) { |
9c915a8c | 1056 | regStart += ref_in_start_stripe; |
9c915a8c AR |
1057 | /* initialize count to sectors from startref to end |
1058 | of strip */ | |
bc93d425 | 1059 | regSize = stripSize - ref_in_start_stripe; |
9c915a8c AR |
1060 | } |
1061 | ||
bc93d425 | 1062 | /* add complete rows in the middle of the transfer */ |
9c915a8c | 1063 | if (numRows > 2) |
9c915a8c AR |
1064 | regSize += (numRows-2) << raid->stripeShift; |
1065 | ||
bc93d425 | 1066 | /* if IO ends within first strip of last row*/ |
9c915a8c AR |
1067 | if (endStrip == endRow*raid->rowDataSize) |
1068 | regSize += ref_in_end_stripe+1; | |
1069 | else | |
1070 | regSize += stripSize; | |
bc93d425 SS |
1071 | } else { |
1072 | /* | |
1073 | * For Uneven span region lock optimization. | |
1074 | * If the start strip is the last in the start row | |
1075 | */ | |
1076 | if (start_strip == (get_strip_from_row(instance, ld, start_row, map) + | |
1077 | SPAN_ROW_DATA_SIZE(map, ld, startlba_span) - 1)) { | |
1078 | regStart += ref_in_start_stripe; | |
1079 | /* initialize count to sectors from | |
1080 | * startRef to end of strip | |
1081 | */ | |
1082 | regSize = stripSize - ref_in_start_stripe; | |
1083 | } | |
1084 | /* Add complete rows in the middle of the transfer*/ | |
1085 | ||
1086 | if (numRows > 2) | |
1087 | /* Add complete rows in the middle of the transfer*/ | |
1088 | regSize += (numRows-2) << raid->stripeShift; | |
1089 | ||
1090 | /* if IO ends within first strip of last row */ | |
1091 | if (endStrip == get_strip_from_row(instance, ld, endRow, map)) | |
1092 | regSize += ref_in_end_stripe + 1; | |
1093 | else | |
1094 | regSize += stripSize; | |
9c915a8c AR |
1095 | } |
1096 | ||
d889344e | 1097 | pRAID_Context->timeout_value = |
26a077e7 AR |
1098 | cpu_to_le16(raid->fpIoTimeoutForLd ? |
1099 | raid->fpIoTimeoutForLd : | |
1100 | map->raidMap.fpPdIoTimeoutSec); | |
5a8cb85b | 1101 | if (fusion->adapter_type == INVADER_SERIES) |
d889344e | 1102 | pRAID_Context->reg_lock_flags = (isRead) ? |
36807e67 | 1103 | raid->regTypeReqOnRead : raid->regTypeReqOnWrite; |
d889344e SC |
1104 | else if (!instance->is_ventura) |
1105 | pRAID_Context->reg_lock_flags = (isRead) ? | |
36807e67 | 1106 | REGION_TYPE_SHARED_READ : raid->regTypeReqOnWrite; |
d889344e SC |
1107 | pRAID_Context->virtual_disk_tgt_id = raid->targetId; |
1108 | pRAID_Context->reg_lock_row_lba = cpu_to_le64(regStart); | |
1109 | pRAID_Context->reg_lock_length = cpu_to_le32(regSize); | |
1110 | pRAID_Context->config_seq_num = raid->seqNum; | |
21c9e160 AR |
1111 | /* save pointer to raid->LUN array */ |
1112 | *raidLUN = raid->LUN; | |
1113 | ||
9c915a8c AR |
1114 | |
1115 | /*Get Phy Params only if FP capable, or else leave it to MR firmware | |
1116 | to do the calculation.*/ | |
1117 | if (io_info->fpOkForIo) { | |
bc93d425 SS |
1118 | retval = io_info->IoforUnevenSpan ? |
1119 | mr_spanset_get_phy_params(instance, ld, | |
1120 | start_strip, ref_in_start_stripe, | |
1121 | io_info, pRAID_Context, map) : | |
1122 | MR_GetPhyParams(instance, ld, start_strip, | |
1123 | ref_in_start_stripe, io_info, | |
1124 | pRAID_Context, map); | |
1125 | /* If IO on an invalid Pd, then FP is not possible.*/ | |
8bf7c65d | 1126 | if (io_info->devHandle == MR_DEVHANDLE_INVALID) |
9c915a8c AR |
1127 | io_info->fpOkForIo = FALSE; |
1128 | return retval; | |
1129 | } else if (isRead) { | |
1130 | uint stripIdx; | |
1131 | for (stripIdx = 0; stripIdx < num_strips; stripIdx++) { | |
bc93d425 SS |
1132 | retval = io_info->IoforUnevenSpan ? |
1133 | mr_spanset_get_phy_params(instance, ld, | |
1134 | start_strip + stripIdx, | |
1135 | ref_in_start_stripe, io_info, | |
1136 | pRAID_Context, map) : | |
1137 | MR_GetPhyParams(instance, ld, | |
1138 | start_strip + stripIdx, ref_in_start_stripe, | |
1139 | io_info, pRAID_Context, map); | |
1140 | if (!retval) | |
9c915a8c AR |
1141 | return TRUE; |
1142 | } | |
1143 | } | |
1144 | return TRUE; | |
1145 | } | |
1146 | ||
bc93d425 SS |
1147 | /* |
1148 | ****************************************************************************** | |
1149 | * | |
1150 | * This routine pepare spanset info from Valid Raid map and store it into | |
1151 | * local copy of ldSpanInfo per instance data structure. | |
1152 | * | |
1153 | * Inputs : | |
1154 | * map - LD map | |
1155 | * ldSpanInfo - ldSpanInfo per HBA instance | |
1156 | * | |
1157 | */ | |
51087a86 | 1158 | void mr_update_span_set(struct MR_DRV_RAID_MAP_ALL *map, |
d2552ebe | 1159 | PLD_SPAN_INFO ldSpanInfo) |
bc93d425 SS |
1160 | { |
1161 | u8 span, count; | |
1162 | u32 element, span_row_width; | |
1163 | u64 span_row; | |
1164 | struct MR_LD_RAID *raid; | |
1165 | LD_SPAN_SET *span_set, *span_set_prev; | |
1166 | struct MR_QUAD_ELEMENT *quad; | |
1167 | int ldCount; | |
1168 | u16 ld; | |
1169 | ||
1170 | ||
51087a86 | 1171 | for (ldCount = 0; ldCount < MAX_LOGICAL_DRIVES_EXT; ldCount++) { |
bc93d425 | 1172 | ld = MR_TargetIdToLdGet(ldCount, map); |
200aed58 | 1173 | if (ld >= (MAX_LOGICAL_DRIVES_EXT - 1)) |
bc93d425 SS |
1174 | continue; |
1175 | raid = MR_LdRaidGet(ld, map); | |
1176 | for (element = 0; element < MAX_QUAD_DEPTH; element++) { | |
1177 | for (span = 0; span < raid->spanDepth; span++) { | |
94cd65dd SS |
1178 | if (le32_to_cpu(map->raidMap.ldSpanMap[ld].spanBlock[span]. |
1179 | block_span_info.noElements) < | |
bc93d425 SS |
1180 | element + 1) |
1181 | continue; | |
1182 | span_set = &(ldSpanInfo[ld].span_set[element]); | |
1183 | quad = &map->raidMap.ldSpanMap[ld]. | |
1184 | spanBlock[span].block_span_info. | |
1185 | quad[element]; | |
1186 | ||
94cd65dd | 1187 | span_set->diff = le32_to_cpu(quad->diff); |
bc93d425 SS |
1188 | |
1189 | for (count = 0, span_row_width = 0; | |
1190 | count < raid->spanDepth; count++) { | |
94cd65dd | 1191 | if (le32_to_cpu(map->raidMap.ldSpanMap[ld]. |
bc93d425 SS |
1192 | spanBlock[count]. |
1193 | block_span_info. | |
94cd65dd | 1194 | noElements) >= element + 1) { |
bc93d425 SS |
1195 | span_set->strip_offset[count] = |
1196 | span_row_width; | |
1197 | span_row_width += | |
1198 | MR_LdSpanPtrGet | |
1199 | (ld, count, map)->spanRowDataSize; | |
bc93d425 SS |
1200 | } |
1201 | } | |
1202 | ||
1203 | span_set->span_row_data_width = span_row_width; | |
94cd65dd SS |
1204 | span_row = mega_div64_32(((le64_to_cpu(quad->logEnd) - |
1205 | le64_to_cpu(quad->logStart)) + le32_to_cpu(quad->diff)), | |
1206 | le32_to_cpu(quad->diff)); | |
bc93d425 SS |
1207 | |
1208 | if (element == 0) { | |
1209 | span_set->log_start_lba = 0; | |
1210 | span_set->log_end_lba = | |
1211 | ((span_row << raid->stripeShift) | |
1212 | * span_row_width) - 1; | |
1213 | ||
1214 | span_set->span_row_start = 0; | |
1215 | span_set->span_row_end = span_row - 1; | |
1216 | ||
1217 | span_set->data_strip_start = 0; | |
1218 | span_set->data_strip_end = | |
1219 | (span_row * span_row_width) - 1; | |
1220 | ||
1221 | span_set->data_row_start = 0; | |
1222 | span_set->data_row_end = | |
94cd65dd | 1223 | (span_row * le32_to_cpu(quad->diff)) - 1; |
bc93d425 SS |
1224 | } else { |
1225 | span_set_prev = &(ldSpanInfo[ld]. | |
1226 | span_set[element - 1]); | |
1227 | span_set->log_start_lba = | |
1228 | span_set_prev->log_end_lba + 1; | |
1229 | span_set->log_end_lba = | |
1230 | span_set->log_start_lba + | |
1231 | ((span_row << raid->stripeShift) | |
1232 | * span_row_width) - 1; | |
1233 | ||
1234 | span_set->span_row_start = | |
1235 | span_set_prev->span_row_end + 1; | |
1236 | span_set->span_row_end = | |
1237 | span_set->span_row_start + span_row - 1; | |
1238 | ||
1239 | span_set->data_strip_start = | |
1240 | span_set_prev->data_strip_end + 1; | |
1241 | span_set->data_strip_end = | |
1242 | span_set->data_strip_start + | |
1243 | (span_row * span_row_width) - 1; | |
1244 | ||
1245 | span_set->data_row_start = | |
1246 | span_set_prev->data_row_end + 1; | |
1247 | span_set->data_row_end = | |
1248 | span_set->data_row_start + | |
94cd65dd | 1249 | (span_row * le32_to_cpu(quad->diff)) - 1; |
bc93d425 SS |
1250 | } |
1251 | break; | |
1252 | } | |
1253 | if (span == raid->spanDepth) | |
1254 | break; | |
1255 | } | |
1256 | } | |
bc93d425 SS |
1257 | } |
1258 | ||
d2552ebe SS |
1259 | void mr_update_load_balance_params(struct MR_DRV_RAID_MAP_ALL *drv_map, |
1260 | struct LD_LOAD_BALANCE_INFO *lbInfo) | |
9c915a8c AR |
1261 | { |
1262 | int ldCount; | |
1263 | u16 ld; | |
1264 | struct MR_LD_RAID *raid; | |
1265 | ||
d2552ebe SS |
1266 | if (lb_pending_cmds > 128 || lb_pending_cmds < 1) |
1267 | lb_pending_cmds = LB_PENDING_CMDS_DEFAULT; | |
1268 | ||
51087a86 | 1269 | for (ldCount = 0; ldCount < MAX_LOGICAL_DRIVES_EXT; ldCount++) { |
d2552ebe | 1270 | ld = MR_TargetIdToLdGet(ldCount, drv_map); |
51087a86 | 1271 | if (ld >= MAX_LOGICAL_DRIVES_EXT) { |
9c915a8c AR |
1272 | lbInfo[ldCount].loadBalanceFlag = 0; |
1273 | continue; | |
1274 | } | |
1275 | ||
d2552ebe SS |
1276 | raid = MR_LdRaidGet(ld, drv_map); |
1277 | if ((raid->level != 1) || | |
1278 | (raid->ldState != MR_LD_STATE_OPTIMAL)) { | |
9c915a8c | 1279 | lbInfo[ldCount].loadBalanceFlag = 0; |
d2552ebe SS |
1280 | continue; |
1281 | } | |
1282 | lbInfo[ldCount].loadBalanceFlag = 1; | |
9c915a8c AR |
1283 | } |
1284 | } | |
1285 | ||
d2552ebe | 1286 | u8 megasas_get_best_arm_pd(struct megasas_instance *instance, |
33203bc4 S |
1287 | struct LD_LOAD_BALANCE_INFO *lbInfo, |
1288 | struct IO_REQUEST_INFO *io_info, | |
1289 | struct MR_DRV_RAID_MAP_ALL *drv_map) | |
9c915a8c | 1290 | { |
d2552ebe | 1291 | struct MR_LD_RAID *raid; |
d889344e | 1292 | u16 pd1_dev_handle; |
d2552ebe | 1293 | u16 pend0, pend1, ld; |
9c915a8c | 1294 | u64 diff0, diff1; |
d2552ebe SS |
1295 | u8 bestArm, pd0, pd1, span, arm; |
1296 | u32 arRef, span_row_size; | |
1297 | ||
1298 | u64 block = io_info->ldStartBlock; | |
1299 | u32 count = io_info->numBlocks; | |
1300 | ||
1301 | span = ((io_info->span_arm & RAID_CTX_SPANARM_SPAN_MASK) | |
1302 | >> RAID_CTX_SPANARM_SPAN_SHIFT); | |
1303 | arm = (io_info->span_arm & RAID_CTX_SPANARM_ARM_MASK); | |
1304 | ||
d2552ebe SS |
1305 | ld = MR_TargetIdToLdGet(io_info->ldTgtId, drv_map); |
1306 | raid = MR_LdRaidGet(ld, drv_map); | |
1307 | span_row_size = instance->UnevenSpanSupport ? | |
1308 | SPAN_ROW_SIZE(drv_map, ld, span) : raid->rowSize; | |
1309 | ||
1310 | arRef = MR_LdSpanArrayGet(ld, span, drv_map); | |
1311 | pd0 = MR_ArPdGet(arRef, arm, drv_map); | |
1312 | pd1 = MR_ArPdGet(arRef, (arm + 1) >= span_row_size ? | |
1313 | (arm + 1 - span_row_size) : arm + 1, drv_map); | |
9c915a8c | 1314 | |
d889344e SC |
1315 | /* Get PD1 Dev Handle */ |
1316 | ||
1317 | pd1_dev_handle = MR_PdDevHandleGet(pd1, drv_map); | |
1318 | ||
33203bc4 | 1319 | if (pd1_dev_handle == MR_DEVHANDLE_INVALID) { |
d889344e SC |
1320 | bestArm = arm; |
1321 | } else { | |
1322 | /* get the pending cmds for the data and mirror arms */ | |
1323 | pend0 = atomic_read(&lbInfo->scsi_pending_cmds[pd0]); | |
1324 | pend1 = atomic_read(&lbInfo->scsi_pending_cmds[pd1]); | |
9c915a8c | 1325 | |
d889344e SC |
1326 | /* Determine the disk whose head is nearer to the req. block */ |
1327 | diff0 = ABS_DIFF(block, lbInfo->last_accessed_block[pd0]); | |
1328 | diff1 = ABS_DIFF(block, lbInfo->last_accessed_block[pd1]); | |
1329 | bestArm = (diff0 <= diff1 ? arm : arm ^ 1); | |
9c915a8c | 1330 | |
d889344e SC |
1331 | /* Make balance count from 16 to 4 to |
1332 | * keep driver in sync with Firmware | |
1333 | */ | |
1334 | if ((bestArm == arm && pend0 > pend1 + lb_pending_cmds) || | |
41064f1b | 1335 | (bestArm != arm && pend1 > pend0 + lb_pending_cmds)) |
d889344e SC |
1336 | bestArm ^= 1; |
1337 | ||
1338 | /* Update the last accessed block on the correct pd */ | |
1339 | io_info->span_arm = | |
1340 | (span << RAID_CTX_SPANARM_SPAN_SHIFT) | bestArm; | |
1341 | io_info->pd_after_lb = (bestArm == arm) ? pd0 : pd1; | |
1342 | } | |
9c915a8c | 1343 | |
d2552ebe | 1344 | lbInfo->last_accessed_block[io_info->pd_after_lb] = block + count - 1; |
d2552ebe | 1345 | return io_info->pd_after_lb; |
9c915a8c AR |
1346 | } |
1347 | ||
9ab9ed38 | 1348 | __le16 get_updated_dev_handle(struct megasas_instance *instance, |
33203bc4 S |
1349 | struct LD_LOAD_BALANCE_INFO *lbInfo, |
1350 | struct IO_REQUEST_INFO *io_info, | |
1351 | struct MR_DRV_RAID_MAP_ALL *drv_map) | |
9c915a8c | 1352 | { |
d2552ebe | 1353 | u8 arm_pd; |
9ab9ed38 | 1354 | __le16 devHandle; |
9c915a8c | 1355 | |
d2552ebe | 1356 | /* get best new arm (PD ID) */ |
33203bc4 | 1357 | arm_pd = megasas_get_best_arm_pd(instance, lbInfo, io_info, drv_map); |
d2552ebe | 1358 | devHandle = MR_PdDevHandleGet(arm_pd, drv_map); |
33203bc4 | 1359 | io_info->pd_interface = MR_PdInterfaceTypeGet(arm_pd, drv_map); |
d2552ebe | 1360 | atomic_inc(&lbInfo->scsi_pending_cmds[arm_pd]); |
33203bc4 | 1361 | |
9c915a8c AR |
1362 | return devHandle; |
1363 | } |