dect
/
linux-2.6
Archived
13
0
Fork 0

[SCSI] megaraid_sas: infrastructure to get PDs from FW

Add system PDs to OS.  Driver implemented the get_pd_list function to
get the system PD from FW.

Signed-off-by Bo Yang<bo.yang@lsi.com>
Signed-off-by: James Bottomley <James.Bottomley@suse.de>
This commit is contained in:
Yang, Bo 2009-10-06 14:27:54 -06:00 committed by James Bottomley
parent 879111224d
commit 81e403ce3c
2 changed files with 183 additions and 3 deletions

View File

@ -2036,6 +2036,98 @@ static int megasas_alloc_cmds(struct megasas_instance *instance)
return 0;
}
/*
* megasas_get_pd_list_info - Returns FW's pd_list structure
* @instance: Adapter soft state
* @pd_list: pd_list structure
*
* Issues an internal command (DCMD) to get the FW's controller PD
* list structure. This information is mainly used to find out SYSTEM
* supported by the FW.
*/
static int
megasas_get_pd_list(struct megasas_instance *instance)
{
int ret = 0, pd_index = 0;
struct megasas_cmd *cmd;
struct megasas_dcmd_frame *dcmd;
struct MR_PD_LIST *ci;
struct MR_PD_ADDRESS *pd_addr;
dma_addr_t ci_h = 0;
cmd = megasas_get_cmd(instance);
if (!cmd) {
printk(KERN_DEBUG "megasas (get_pd_list): Failed to get cmd\n");
return -ENOMEM;
}
dcmd = &cmd->frame->dcmd;
ci = pci_alloc_consistent(instance->pdev,
MEGASAS_MAX_PD * sizeof(struct MR_PD_LIST), &ci_h);
if (!ci) {
printk(KERN_DEBUG "Failed to alloc mem for pd_list\n");
megasas_return_cmd(instance, cmd);
return -ENOMEM;
}
memset(ci, 0, sizeof(*ci));
memset(dcmd->mbox.b, 0, MFI_MBOX_SIZE);
dcmd->mbox.b[0] = MR_PD_QUERY_TYPE_EXPOSED_TO_HOST;
dcmd->mbox.b[1] = 0;
dcmd->cmd = MFI_CMD_DCMD;
dcmd->cmd_status = 0xFF;
dcmd->sge_count = 1;
dcmd->flags = MFI_FRAME_DIR_READ;
dcmd->timeout = 0;
dcmd->data_xfer_len = MEGASAS_MAX_PD * sizeof(struct MR_PD_LIST);
dcmd->opcode = MR_DCMD_PD_LIST_QUERY;
dcmd->sgl.sge32[0].phys_addr = ci_h;
dcmd->sgl.sge32[0].length = MEGASAS_MAX_PD * sizeof(struct MR_PD_LIST);
if (!megasas_issue_polled(instance, cmd)) {
ret = 0;
} else {
ret = -1;
}
/*
* the following function will get the instance PD LIST.
*/
pd_addr = ci->addr;
if ( ret == 0 &&
(ci->count <
(MEGASAS_MAX_PD_CHANNELS * MEGASAS_MAX_DEV_PER_CHANNEL))) {
memset(instance->pd_list, 0,
MEGASAS_MAX_PD * sizeof(struct megasas_pd_list));
for (pd_index = 0; pd_index < ci->count; pd_index++) {
instance->pd_list[pd_addr->deviceId].tid =
pd_addr->deviceId;
instance->pd_list[pd_addr->deviceId].driveType =
pd_addr->scsiDevType;
instance->pd_list[pd_addr->deviceId].driveState =
MR_PD_STATE_SYSTEM;
pd_addr++;
}
}
pci_free_consistent(instance->pdev,
MEGASAS_MAX_PD * sizeof(struct MR_PD_LIST),
ci, ci_h);
megasas_return_cmd(instance, cmd);
return ret;
}
/**
* megasas_get_controller_info - Returns FW's controller structure
* @instance: Adapter soft state
@ -2326,6 +2418,10 @@ static int megasas_init_mfi(struct megasas_instance *instance)
if (megasas_issue_init_mfi(instance))
goto fail_fw_init;
memset(instance->pd_list, 0 ,
(MEGASAS_MAX_PD * sizeof(struct megasas_pd_list)));
megasas_get_pd_list(instance);
ctrl_info = kmalloc(sizeof(struct megasas_ctrl_info), GFP_KERNEL);
/*

View File

@ -133,6 +133,7 @@
#define MR_DCMD_CLUSTER 0x08000000
#define MR_DCMD_CLUSTER_RESET_ALL 0x08010100
#define MR_DCMD_CLUSTER_RESET_LD 0x08010200
#define MR_DCMD_PD_LIST_QUERY 0x02010100
/*
* MFI command completion codes
@ -253,9 +254,89 @@ enum MR_EVT_ARGS {
MR_EVT_ARGS_STR,
MR_EVT_ARGS_TIME,
MR_EVT_ARGS_ECC,
MR_EVT_ARGS_LD_PROP,
MR_EVT_ARGS_PD_SPARE,
MR_EVT_ARGS_PD_INDEX,
MR_EVT_ARGS_DIAG_PASS,
MR_EVT_ARGS_DIAG_FAIL,
MR_EVT_ARGS_PD_LBA_LBA,
MR_EVT_ARGS_PORT_PHY,
MR_EVT_ARGS_PD_MISSING,
MR_EVT_ARGS_PD_ADDRESS,
MR_EVT_ARGS_BITMAP,
MR_EVT_ARGS_CONNECTOR,
MR_EVT_ARGS_PD_PD,
MR_EVT_ARGS_PD_FRU,
MR_EVT_ARGS_PD_PATHINFO,
MR_EVT_ARGS_PD_POWER_STATE,
MR_EVT_ARGS_GENERIC,
};
/*
* define constants for device list query options
*/
enum MR_PD_QUERY_TYPE {
MR_PD_QUERY_TYPE_ALL = 0,
MR_PD_QUERY_TYPE_STATE = 1,
MR_PD_QUERY_TYPE_POWER_STATE = 2,
MR_PD_QUERY_TYPE_MEDIA_TYPE = 3,
MR_PD_QUERY_TYPE_SPEED = 4,
MR_PD_QUERY_TYPE_EXPOSED_TO_HOST = 5,
};
enum MR_PD_STATE {
MR_PD_STATE_UNCONFIGURED_GOOD = 0x00,
MR_PD_STATE_UNCONFIGURED_BAD = 0x01,
MR_PD_STATE_HOT_SPARE = 0x02,
MR_PD_STATE_OFFLINE = 0x10,
MR_PD_STATE_FAILED = 0x11,
MR_PD_STATE_REBUILD = 0x14,
MR_PD_STATE_ONLINE = 0x18,
MR_PD_STATE_COPYBACK = 0x20,
MR_PD_STATE_SYSTEM = 0x40,
};
/*
* defines the physical drive address structure
*/
struct MR_PD_ADDRESS {
u16 deviceId;
u16 enclDeviceId;
union {
struct {
u8 enclIndex;
u8 slotNumber;
} mrPdAddress;
struct {
u8 enclPosition;
u8 enclConnectorIndex;
} mrEnclAddress;
};
u8 scsiDevType;
union {
u8 connectedPortBitmap;
u8 connectedPortNumbers;
};
u64 sasAddr[2];
} __packed;
/*
* defines the physical drive list structure
*/
struct MR_PD_LIST {
u32 size;
u32 count;
struct MR_PD_ADDRESS addr[1];
} __packed;
struct megasas_pd_list {
u16 tid;
u8 driveType;
u8 driveState;
} __packed;
/*
* SAS controller properties
*/
@ -284,7 +365,7 @@ struct megasas_ctrl_prop {
u8 expose_encl_devices;
u8 reserved[38];
} __attribute__ ((packed));
} __packed;
/*
* SAS controller information
@ -527,7 +608,7 @@ struct megasas_ctrl_info {
u8 pad[0x800 - 0x6a0];
} __attribute__ ((packed));
} __packed;
/*
* ===============================
@ -542,6 +623,8 @@ struct megasas_ctrl_info {
#define MEGASAS_DEFAULT_INIT_ID -1
#define MEGASAS_MAX_LUN 8
#define MEGASAS_MAX_LD 64
#define MEGASAS_MAX_PD (MEGASAS_MAX_PD_CHANNELS * \
MEGASAS_MAX_DEV_PER_CHANNEL)
#define MEGASAS_DBG_LVL 1
@ -1089,6 +1172,7 @@ struct megasas_instance {
unsigned long base_addr;
struct megasas_register_set __iomem *reg_set;
struct megasas_pd_list pd_list[MEGASAS_MAX_PD];
s8 init_id;
u16 max_num_sge;