diff options
-rw-r--r-- | drivers/scsi/megaraid/megaraid_sas.c | 95 | ||||
-rw-r--r-- | drivers/scsi/megaraid/megaraid_sas.h | 30 |
2 files changed, 125 insertions, 0 deletions
diff --git a/drivers/scsi/megaraid/megaraid_sas.c b/drivers/scsi/megaraid/megaraid_sas.c index 18d3a312c29f..a92998fe2468 100644 --- a/drivers/scsi/megaraid/megaraid_sas.c +++ b/drivers/scsi/megaraid/megaraid_sas.c | |||
@@ -875,6 +875,12 @@ megasas_build_dcdb(struct megasas_instance *instance, struct scsi_cmnd *scp, | |||
875 | pthru->sge_count = megasas_make_sgl32(instance, scp, | 875 | pthru->sge_count = megasas_make_sgl32(instance, scp, |
876 | &pthru->sgl); | 876 | &pthru->sgl); |
877 | 877 | ||
878 | if (pthru->sge_count > instance->max_num_sge) { | ||
879 | printk(KERN_ERR "megasas: DCDB two many SGE NUM=%x\n", | ||
880 | pthru->sge_count); | ||
881 | return 0; | ||
882 | } | ||
883 | |||
878 | /* | 884 | /* |
879 | * Sense info specific | 885 | * Sense info specific |
880 | */ | 886 | */ |
@@ -1001,6 +1007,12 @@ megasas_build_ldio(struct megasas_instance *instance, struct scsi_cmnd *scp, | |||
1001 | } else | 1007 | } else |
1002 | ldio->sge_count = megasas_make_sgl32(instance, scp, &ldio->sgl); | 1008 | ldio->sge_count = megasas_make_sgl32(instance, scp, &ldio->sgl); |
1003 | 1009 | ||
1010 | if (ldio->sge_count > instance->max_num_sge) { | ||
1011 | printk(KERN_ERR "megasas: build_ld_io: sge_count = %x\n", | ||
1012 | ldio->sge_count); | ||
1013 | return 0; | ||
1014 | } | ||
1015 | |||
1004 | /* | 1016 | /* |
1005 | * Sense info specific | 1017 | * Sense info specific |
1006 | */ | 1018 | */ |
@@ -2296,6 +2308,86 @@ megasas_get_pd_list(struct megasas_instance *instance) | |||
2296 | return ret; | 2308 | return ret; |
2297 | } | 2309 | } |
2298 | 2310 | ||
2311 | /* | ||
2312 | * megasas_get_ld_list_info - Returns FW's ld_list structure | ||
2313 | * @instance: Adapter soft state | ||
2314 | * @ld_list: ld_list structure | ||
2315 | * | ||
2316 | * Issues an internal command (DCMD) to get the FW's controller PD | ||
2317 | * list structure. This information is mainly used to find out SYSTEM | ||
2318 | * supported by the FW. | ||
2319 | */ | ||
2320 | static int | ||
2321 | megasas_get_ld_list(struct megasas_instance *instance) | ||
2322 | { | ||
2323 | int ret = 0, ld_index = 0, ids = 0; | ||
2324 | struct megasas_cmd *cmd; | ||
2325 | struct megasas_dcmd_frame *dcmd; | ||
2326 | struct MR_LD_LIST *ci; | ||
2327 | dma_addr_t ci_h = 0; | ||
2328 | |||
2329 | cmd = megasas_get_cmd(instance); | ||
2330 | |||
2331 | if (!cmd) { | ||
2332 | printk(KERN_DEBUG "megasas_get_ld_list: Failed to get cmd\n"); | ||
2333 | return -ENOMEM; | ||
2334 | } | ||
2335 | |||
2336 | dcmd = &cmd->frame->dcmd; | ||
2337 | |||
2338 | ci = pci_alloc_consistent(instance->pdev, | ||
2339 | sizeof(struct MR_LD_LIST), | ||
2340 | &ci_h); | ||
2341 | |||
2342 | if (!ci) { | ||
2343 | printk(KERN_DEBUG "Failed to alloc mem in get_ld_list\n"); | ||
2344 | megasas_return_cmd(instance, cmd); | ||
2345 | return -ENOMEM; | ||
2346 | } | ||
2347 | |||
2348 | memset(ci, 0, sizeof(*ci)); | ||
2349 | memset(dcmd->mbox.b, 0, MFI_MBOX_SIZE); | ||
2350 | |||
2351 | dcmd->cmd = MFI_CMD_DCMD; | ||
2352 | dcmd->cmd_status = 0xFF; | ||
2353 | dcmd->sge_count = 1; | ||
2354 | dcmd->flags = MFI_FRAME_DIR_READ; | ||
2355 | dcmd->timeout = 0; | ||
2356 | dcmd->data_xfer_len = sizeof(struct MR_LD_LIST); | ||
2357 | dcmd->opcode = MR_DCMD_LD_GET_LIST; | ||
2358 | dcmd->sgl.sge32[0].phys_addr = ci_h; | ||
2359 | dcmd->sgl.sge32[0].length = sizeof(struct MR_LD_LIST); | ||
2360 | dcmd->pad_0 = 0; | ||
2361 | |||
2362 | if (!megasas_issue_polled(instance, cmd)) { | ||
2363 | ret = 0; | ||
2364 | } else { | ||
2365 | ret = -1; | ||
2366 | } | ||
2367 | |||
2368 | /* the following function will get the instance PD LIST */ | ||
2369 | |||
2370 | if ((ret == 0) && (ci->ldCount < MAX_LOGICAL_DRIVES)) { | ||
2371 | memset(instance->ld_ids, 0xff, MEGASAS_MAX_LD_IDS); | ||
2372 | |||
2373 | for (ld_index = 0; ld_index < ci->ldCount; ld_index++) { | ||
2374 | if (ci->ldList[ld_index].state != 0) { | ||
2375 | ids = ci->ldList[ld_index].ref.targetId; | ||
2376 | instance->ld_ids[ids] = | ||
2377 | ci->ldList[ld_index].ref.targetId; | ||
2378 | } | ||
2379 | } | ||
2380 | } | ||
2381 | |||
2382 | pci_free_consistent(instance->pdev, | ||
2383 | sizeof(struct MR_LD_LIST), | ||
2384 | ci, | ||
2385 | ci_h); | ||
2386 | |||
2387 | megasas_return_cmd(instance, cmd); | ||
2388 | return ret; | ||
2389 | } | ||
2390 | |||
2299 | /** | 2391 | /** |
2300 | * megasas_get_controller_info - Returns FW's controller structure | 2392 | * megasas_get_controller_info - Returns FW's controller structure |
2301 | * @instance: Adapter soft state | 2393 | * @instance: Adapter soft state |
@@ -2593,6 +2685,9 @@ static int megasas_init_mfi(struct megasas_instance *instance) | |||
2593 | (MEGASAS_MAX_PD * sizeof(struct megasas_pd_list))); | 2685 | (MEGASAS_MAX_PD * sizeof(struct megasas_pd_list))); |
2594 | megasas_get_pd_list(instance); | 2686 | megasas_get_pd_list(instance); |
2595 | 2687 | ||
2688 | memset(instance->ld_ids, 0xff, MEGASAS_MAX_LD_IDS); | ||
2689 | megasas_get_ld_list(instance); | ||
2690 | |||
2596 | ctrl_info = kmalloc(sizeof(struct megasas_ctrl_info), GFP_KERNEL); | 2691 | ctrl_info = kmalloc(sizeof(struct megasas_ctrl_info), GFP_KERNEL); |
2597 | 2692 | ||
2598 | /* | 2693 | /* |
diff --git a/drivers/scsi/megaraid/megaraid_sas.h b/drivers/scsi/megaraid/megaraid_sas.h index 72b28e436e32..1135c94bedbd 100644 --- a/drivers/scsi/megaraid/megaraid_sas.h +++ b/drivers/scsi/megaraid/megaraid_sas.h | |||
@@ -117,6 +117,7 @@ | |||
117 | #define MFI_CMD_STP 0x08 | 117 | #define MFI_CMD_STP 0x08 |
118 | 118 | ||
119 | #define MR_DCMD_CTRL_GET_INFO 0x01010000 | 119 | #define MR_DCMD_CTRL_GET_INFO 0x01010000 |
120 | #define MR_DCMD_LD_GET_LIST 0x03010000 | ||
120 | 121 | ||
121 | #define MR_DCMD_CTRL_CACHE_FLUSH 0x01101000 | 122 | #define MR_DCMD_CTRL_CACHE_FLUSH 0x01101000 |
122 | #define MR_FLUSH_CTRL_CACHE 0x01 | 123 | #define MR_FLUSH_CTRL_CACHE 0x01 |
@@ -349,6 +350,32 @@ struct megasas_pd_list { | |||
349 | u8 driveState; | 350 | u8 driveState; |
350 | } __packed; | 351 | } __packed; |
351 | 352 | ||
353 | /* | ||
354 | * defines the logical drive reference structure | ||
355 | */ | ||
356 | union MR_LD_REF { | ||
357 | struct { | ||
358 | u8 targetId; | ||
359 | u8 reserved; | ||
360 | u16 seqNum; | ||
361 | }; | ||
362 | u32 ref; | ||
363 | } __packed; | ||
364 | |||
365 | /* | ||
366 | * defines the logical drive list structure | ||
367 | */ | ||
368 | struct MR_LD_LIST { | ||
369 | u32 ldCount; | ||
370 | u32 reserved; | ||
371 | struct { | ||
372 | union MR_LD_REF ref; | ||
373 | u8 state; | ||
374 | u8 reserved[3]; | ||
375 | u64 size; | ||
376 | } ldList[MAX_LOGICAL_DRIVES]; | ||
377 | } __packed; | ||
378 | |||
352 | /* | 379 | /* |
353 | * SAS controller properties | 380 | * SAS controller properties |
354 | */ | 381 | */ |
@@ -637,6 +664,8 @@ struct megasas_ctrl_info { | |||
637 | #define MEGASAS_MAX_LD 64 | 664 | #define MEGASAS_MAX_LD 64 |
638 | #define MEGASAS_MAX_PD (MEGASAS_MAX_PD_CHANNELS * \ | 665 | #define MEGASAS_MAX_PD (MEGASAS_MAX_PD_CHANNELS * \ |
639 | MEGASAS_MAX_DEV_PER_CHANNEL) | 666 | MEGASAS_MAX_DEV_PER_CHANNEL) |
667 | #define MEGASAS_MAX_LD_IDS (MEGASAS_MAX_LD_CHANNELS * \ | ||
668 | MEGASAS_MAX_DEV_PER_CHANNEL) | ||
640 | 669 | ||
641 | #define MEGASAS_DBG_LVL 1 | 670 | #define MEGASAS_DBG_LVL 1 |
642 | 671 | ||
@@ -1187,6 +1216,7 @@ struct megasas_instance { | |||
1187 | struct megasas_register_set __iomem *reg_set; | 1216 | struct megasas_register_set __iomem *reg_set; |
1188 | 1217 | ||
1189 | struct megasas_pd_list pd_list[MEGASAS_MAX_PD]; | 1218 | struct megasas_pd_list pd_list[MEGASAS_MAX_PD]; |
1219 | u8 ld_ids[MEGASAS_MAX_LD_IDS]; | ||
1190 | s8 init_id; | 1220 | s8 init_id; |
1191 | 1221 | ||
1192 | u16 max_num_sge; | 1222 | u16 max_num_sge; |