aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/megaraid/megaraid_sas_base.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/scsi/megaraid/megaraid_sas_base.c')
-rw-r--r--drivers/scsi/megaraid/megaraid_sas_base.c106
1 files changed, 97 insertions, 9 deletions
diff --git a/drivers/scsi/megaraid/megaraid_sas_base.c b/drivers/scsi/megaraid/megaraid_sas_base.c
index 1f0ca68409d4..9f7c4a169222 100644
--- a/drivers/scsi/megaraid/megaraid_sas_base.c
+++ b/drivers/scsi/megaraid/megaraid_sas_base.c
@@ -92,6 +92,8 @@ MODULE_DESCRIPTION("LSI MegaRAID SAS Driver");
92 92
93int megasas_transition_to_ready(struct megasas_instance *instance, int ocr); 93int megasas_transition_to_ready(struct megasas_instance *instance, int ocr);
94static int megasas_get_pd_list(struct megasas_instance *instance); 94static int megasas_get_pd_list(struct megasas_instance *instance);
95static int megasas_ld_list_query(struct megasas_instance *instance,
96 u8 query_type);
95static int megasas_issue_init_mfi(struct megasas_instance *instance); 97static int megasas_issue_init_mfi(struct megasas_instance *instance);
96static int megasas_register_aen(struct megasas_instance *instance, 98static int megasas_register_aen(struct megasas_instance *instance,
97 u32 seq_num, u32 class_locale_word); 99 u32 seq_num, u32 class_locale_word);
@@ -3271,6 +3273,84 @@ megasas_get_ld_list(struct megasas_instance *instance)
3271} 3273}
3272 3274
3273/** 3275/**
3276 * megasas_ld_list_query - Returns FW's ld_list structure
3277 * @instance: Adapter soft state
3278 * @ld_list: ld_list structure
3279 *
3280 * Issues an internal command (DCMD) to get the FW's controller PD
3281 * list structure. This information is mainly used to find out SYSTEM
3282 * supported by the FW.
3283 */
3284static int
3285megasas_ld_list_query(struct megasas_instance *instance, u8 query_type)
3286{
3287 int ret = 0, ld_index = 0, ids = 0;
3288 struct megasas_cmd *cmd;
3289 struct megasas_dcmd_frame *dcmd;
3290 struct MR_LD_TARGETID_LIST *ci;
3291 dma_addr_t ci_h = 0;
3292
3293 cmd = megasas_get_cmd(instance);
3294
3295 if (!cmd) {
3296 printk(KERN_WARNING
3297 "megasas:(megasas_ld_list_query): Failed to get cmd\n");
3298 return -ENOMEM;
3299 }
3300
3301 dcmd = &cmd->frame->dcmd;
3302
3303 ci = pci_alloc_consistent(instance->pdev,
3304 sizeof(struct MR_LD_TARGETID_LIST), &ci_h);
3305
3306 if (!ci) {
3307 printk(KERN_WARNING
3308 "megasas: Failed to alloc mem for ld_list_query\n");
3309 megasas_return_cmd(instance, cmd);
3310 return -ENOMEM;
3311 }
3312
3313 memset(ci, 0, sizeof(*ci));
3314 memset(dcmd->mbox.b, 0, MFI_MBOX_SIZE);
3315
3316 dcmd->mbox.b[0] = query_type;
3317
3318 dcmd->cmd = MFI_CMD_DCMD;
3319 dcmd->cmd_status = 0xFF;
3320 dcmd->sge_count = 1;
3321 dcmd->flags = MFI_FRAME_DIR_READ;
3322 dcmd->timeout = 0;
3323 dcmd->data_xfer_len = sizeof(struct MR_LD_TARGETID_LIST);
3324 dcmd->opcode = MR_DCMD_LD_LIST_QUERY;
3325 dcmd->sgl.sge32[0].phys_addr = ci_h;
3326 dcmd->sgl.sge32[0].length = sizeof(struct MR_LD_TARGETID_LIST);
3327 dcmd->pad_0 = 0;
3328
3329 if (!megasas_issue_polled(instance, cmd) && !dcmd->cmd_status) {
3330 ret = 0;
3331 } else {
3332 /* On failure, call older LD list DCMD */
3333 ret = 1;
3334 }
3335
3336 if ((ret == 0) && (ci->count <= (MAX_LOGICAL_DRIVES))) {
3337 memset(instance->ld_ids, 0xff, MEGASAS_MAX_LD_IDS);
3338 for (ld_index = 0; ld_index < ci->count; ld_index++) {
3339 ids = ci->targetId[ld_index];
3340 instance->ld_ids[ids] = ci->targetId[ld_index];
3341 }
3342
3343 }
3344
3345 pci_free_consistent(instance->pdev, sizeof(struct MR_LD_TARGETID_LIST),
3346 ci, ci_h);
3347
3348 megasas_return_cmd(instance, cmd);
3349
3350 return ret;
3351}
3352
3353/**
3274 * megasas_get_controller_info - Returns FW's controller structure 3354 * megasas_get_controller_info - Returns FW's controller structure
3275 * @instance: Adapter soft state 3355 * @instance: Adapter soft state
3276 * @ctrl_info: Controller information structure 3356 * @ctrl_info: Controller information structure
@@ -3648,7 +3728,9 @@ static int megasas_init_fw(struct megasas_instance *instance)
3648 megasas_get_pd_list(instance); 3728 megasas_get_pd_list(instance);
3649 3729
3650 memset(instance->ld_ids, 0xff, MEGASAS_MAX_LD_IDS); 3730 memset(instance->ld_ids, 0xff, MEGASAS_MAX_LD_IDS);
3651 megasas_get_ld_list(instance); 3731 if (megasas_ld_list_query(instance,
3732 MR_LD_QUERY_TYPE_EXPOSED_TO_HOST))
3733 megasas_get_ld_list(instance);
3652 3734
3653 ctrl_info = kmalloc(sizeof(struct megasas_ctrl_info), GFP_KERNEL); 3735 ctrl_info = kmalloc(sizeof(struct megasas_ctrl_info), GFP_KERNEL);
3654 3736
@@ -5389,7 +5471,9 @@ megasas_aen_polling(struct work_struct *work)
5389 case MR_EVT_LD_OFFLINE: 5471 case MR_EVT_LD_OFFLINE:
5390 case MR_EVT_CFG_CLEARED: 5472 case MR_EVT_CFG_CLEARED:
5391 case MR_EVT_LD_DELETED: 5473 case MR_EVT_LD_DELETED:
5392 megasas_get_ld_list(instance); 5474 if (megasas_ld_list_query(instance,
5475 MR_LD_QUERY_TYPE_EXPOSED_TO_HOST))
5476 megasas_get_ld_list(instance);
5393 for (i = 0; i < MEGASAS_MAX_LD_CHANNELS; i++) { 5477 for (i = 0; i < MEGASAS_MAX_LD_CHANNELS; i++) {
5394 for (j = 0; 5478 for (j = 0;
5395 j < MEGASAS_MAX_DEV_PER_CHANNEL; 5479 j < MEGASAS_MAX_DEV_PER_CHANNEL;
@@ -5399,7 +5483,7 @@ megasas_aen_polling(struct work_struct *work)
5399 (i * MEGASAS_MAX_DEV_PER_CHANNEL) + j; 5483 (i * MEGASAS_MAX_DEV_PER_CHANNEL) + j;
5400 5484
5401 sdev1 = scsi_device_lookup(host, 5485 sdev1 = scsi_device_lookup(host,
5402 i + MEGASAS_MAX_LD_CHANNELS, 5486 MEGASAS_MAX_PD_CHANNELS + i,
5403 j, 5487 j,
5404 0); 5488 0);
5405 5489
@@ -5418,7 +5502,9 @@ megasas_aen_polling(struct work_struct *work)
5418 doscan = 0; 5502 doscan = 0;
5419 break; 5503 break;
5420 case MR_EVT_LD_CREATED: 5504 case MR_EVT_LD_CREATED:
5421 megasas_get_ld_list(instance); 5505 if (megasas_ld_list_query(instance,
5506 MR_LD_QUERY_TYPE_EXPOSED_TO_HOST))
5507 megasas_get_ld_list(instance);
5422 for (i = 0; i < MEGASAS_MAX_LD_CHANNELS; i++) { 5508 for (i = 0; i < MEGASAS_MAX_LD_CHANNELS; i++) {
5423 for (j = 0; 5509 for (j = 0;
5424 j < MEGASAS_MAX_DEV_PER_CHANNEL; 5510 j < MEGASAS_MAX_DEV_PER_CHANNEL;
@@ -5427,14 +5513,14 @@ megasas_aen_polling(struct work_struct *work)
5427 (i * MEGASAS_MAX_DEV_PER_CHANNEL) + j; 5513 (i * MEGASAS_MAX_DEV_PER_CHANNEL) + j;
5428 5514
5429 sdev1 = scsi_device_lookup(host, 5515 sdev1 = scsi_device_lookup(host,
5430 i+MEGASAS_MAX_LD_CHANNELS, 5516 MEGASAS_MAX_PD_CHANNELS + i,
5431 j, 0); 5517 j, 0);
5432 5518
5433 if (instance->ld_ids[ld_index] != 5519 if (instance->ld_ids[ld_index] !=
5434 0xff) { 5520 0xff) {
5435 if (!sdev1) { 5521 if (!sdev1) {
5436 scsi_add_device(host, 5522 scsi_add_device(host,
5437 i + 2, 5523 MEGASAS_MAX_PD_CHANNELS + i,
5438 j, 0); 5524 j, 0);
5439 } 5525 }
5440 } 5526 }
@@ -5483,18 +5569,20 @@ megasas_aen_polling(struct work_struct *work)
5483 } 5569 }
5484 } 5570 }
5485 5571
5486 megasas_get_ld_list(instance); 5572 if (megasas_ld_list_query(instance,
5573 MR_LD_QUERY_TYPE_EXPOSED_TO_HOST))
5574 megasas_get_ld_list(instance);
5487 for (i = 0; i < MEGASAS_MAX_LD_CHANNELS; i++) { 5575 for (i = 0; i < MEGASAS_MAX_LD_CHANNELS; i++) {
5488 for (j = 0; j < MEGASAS_MAX_DEV_PER_CHANNEL; j++) { 5576 for (j = 0; j < MEGASAS_MAX_DEV_PER_CHANNEL; j++) {
5489 ld_index = 5577 ld_index =
5490 (i * MEGASAS_MAX_DEV_PER_CHANNEL) + j; 5578 (i * MEGASAS_MAX_DEV_PER_CHANNEL) + j;
5491 5579
5492 sdev1 = scsi_device_lookup(host, 5580 sdev1 = scsi_device_lookup(host,
5493 i+MEGASAS_MAX_LD_CHANNELS, j, 0); 5581 MEGASAS_MAX_PD_CHANNELS + i, j, 0);
5494 if (instance->ld_ids[ld_index] != 0xff) { 5582 if (instance->ld_ids[ld_index] != 0xff) {
5495 if (!sdev1) { 5583 if (!sdev1) {
5496 scsi_add_device(host, 5584 scsi_add_device(host,
5497 i+2, 5585 MEGASAS_MAX_PD_CHANNELS + i,
5498 j, 0); 5586 j, 0);
5499 } else { 5587 } else {
5500 scsi_device_put(sdev1); 5588 scsi_device_put(sdev1);