diff options
author | Yang, Bo <Bo.Yang@lsi.com> | 2009-10-06 16:27:54 -0400 |
---|---|---|
committer | James Bottomley <James.Bottomley@suse.de> | 2009-10-29 13:03:19 -0400 |
commit | 81e403ce3c6a34cd705bf54d4cdeefdeb7068a8d (patch) | |
tree | 7437520601436026c7d90e5520fddc8230eaac56 /drivers/scsi/megaraid | |
parent | 879111224d0784eab623fe8130a1f4481e0e1966 (diff) |
[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>
Diffstat (limited to 'drivers/scsi/megaraid')
-rw-r--r-- | drivers/scsi/megaraid/megaraid_sas.c | 96 | ||||
-rw-r--r-- | drivers/scsi/megaraid/megaraid_sas.h | 88 |
2 files changed, 182 insertions, 2 deletions
diff --git a/drivers/scsi/megaraid/megaraid_sas.c b/drivers/scsi/megaraid/megaraid_sas.c index b6e43271883c..48c3658d73a7 100644 --- a/drivers/scsi/megaraid/megaraid_sas.c +++ b/drivers/scsi/megaraid/megaraid_sas.c | |||
@@ -2036,6 +2036,98 @@ static int megasas_alloc_cmds(struct megasas_instance *instance) | |||
2036 | return 0; | 2036 | return 0; |
2037 | } | 2037 | } |
2038 | 2038 | ||
2039 | /* | ||
2040 | * megasas_get_pd_list_info - Returns FW's pd_list structure | ||
2041 | * @instance: Adapter soft state | ||
2042 | * @pd_list: pd_list structure | ||
2043 | * | ||
2044 | * Issues an internal command (DCMD) to get the FW's controller PD | ||
2045 | * list structure. This information is mainly used to find out SYSTEM | ||
2046 | * supported by the FW. | ||
2047 | */ | ||
2048 | static int | ||
2049 | megasas_get_pd_list(struct megasas_instance *instance) | ||
2050 | { | ||
2051 | int ret = 0, pd_index = 0; | ||
2052 | struct megasas_cmd *cmd; | ||
2053 | struct megasas_dcmd_frame *dcmd; | ||
2054 | struct MR_PD_LIST *ci; | ||
2055 | struct MR_PD_ADDRESS *pd_addr; | ||
2056 | dma_addr_t ci_h = 0; | ||
2057 | |||
2058 | cmd = megasas_get_cmd(instance); | ||
2059 | |||
2060 | if (!cmd) { | ||
2061 | printk(KERN_DEBUG "megasas (get_pd_list): Failed to get cmd\n"); | ||
2062 | return -ENOMEM; | ||
2063 | } | ||
2064 | |||
2065 | dcmd = &cmd->frame->dcmd; | ||
2066 | |||
2067 | ci = pci_alloc_consistent(instance->pdev, | ||
2068 | MEGASAS_MAX_PD * sizeof(struct MR_PD_LIST), &ci_h); | ||
2069 | |||
2070 | if (!ci) { | ||
2071 | printk(KERN_DEBUG "Failed to alloc mem for pd_list\n"); | ||
2072 | megasas_return_cmd(instance, cmd); | ||
2073 | return -ENOMEM; | ||
2074 | } | ||
2075 | |||
2076 | memset(ci, 0, sizeof(*ci)); | ||
2077 | memset(dcmd->mbox.b, 0, MFI_MBOX_SIZE); | ||
2078 | |||
2079 | dcmd->mbox.b[0] = MR_PD_QUERY_TYPE_EXPOSED_TO_HOST; | ||
2080 | dcmd->mbox.b[1] = 0; | ||
2081 | dcmd->cmd = MFI_CMD_DCMD; | ||
2082 | dcmd->cmd_status = 0xFF; | ||
2083 | dcmd->sge_count = 1; | ||
2084 | dcmd->flags = MFI_FRAME_DIR_READ; | ||
2085 | dcmd->timeout = 0; | ||
2086 | dcmd->data_xfer_len = MEGASAS_MAX_PD * sizeof(struct MR_PD_LIST); | ||
2087 | dcmd->opcode = MR_DCMD_PD_LIST_QUERY; | ||
2088 | dcmd->sgl.sge32[0].phys_addr = ci_h; | ||
2089 | dcmd->sgl.sge32[0].length = MEGASAS_MAX_PD * sizeof(struct MR_PD_LIST); | ||
2090 | |||
2091 | if (!megasas_issue_polled(instance, cmd)) { | ||
2092 | ret = 0; | ||
2093 | } else { | ||
2094 | ret = -1; | ||
2095 | } | ||
2096 | |||
2097 | /* | ||
2098 | * the following function will get the instance PD LIST. | ||
2099 | */ | ||
2100 | |||
2101 | pd_addr = ci->addr; | ||
2102 | |||
2103 | if ( ret == 0 && | ||
2104 | (ci->count < | ||
2105 | (MEGASAS_MAX_PD_CHANNELS * MEGASAS_MAX_DEV_PER_CHANNEL))) { | ||
2106 | |||
2107 | memset(instance->pd_list, 0, | ||
2108 | MEGASAS_MAX_PD * sizeof(struct megasas_pd_list)); | ||
2109 | |||
2110 | for (pd_index = 0; pd_index < ci->count; pd_index++) { | ||
2111 | |||
2112 | instance->pd_list[pd_addr->deviceId].tid = | ||
2113 | pd_addr->deviceId; | ||
2114 | instance->pd_list[pd_addr->deviceId].driveType = | ||
2115 | pd_addr->scsiDevType; | ||
2116 | instance->pd_list[pd_addr->deviceId].driveState = | ||
2117 | MR_PD_STATE_SYSTEM; | ||
2118 | pd_addr++; | ||
2119 | } | ||
2120 | } | ||
2121 | |||
2122 | pci_free_consistent(instance->pdev, | ||
2123 | MEGASAS_MAX_PD * sizeof(struct MR_PD_LIST), | ||
2124 | ci, ci_h); | ||
2125 | megasas_return_cmd(instance, cmd); | ||
2126 | |||
2127 | return ret; | ||
2128 | } | ||
2129 | |||
2130 | |||
2039 | /** | 2131 | /** |
2040 | * megasas_get_controller_info - Returns FW's controller structure | 2132 | * megasas_get_controller_info - Returns FW's controller structure |
2041 | * @instance: Adapter soft state | 2133 | * @instance: Adapter soft state |
@@ -2326,6 +2418,10 @@ static int megasas_init_mfi(struct megasas_instance *instance) | |||
2326 | if (megasas_issue_init_mfi(instance)) | 2418 | if (megasas_issue_init_mfi(instance)) |
2327 | goto fail_fw_init; | 2419 | goto fail_fw_init; |
2328 | 2420 | ||
2421 | memset(instance->pd_list, 0 , | ||
2422 | (MEGASAS_MAX_PD * sizeof(struct megasas_pd_list))); | ||
2423 | megasas_get_pd_list(instance); | ||
2424 | |||
2329 | ctrl_info = kmalloc(sizeof(struct megasas_ctrl_info), GFP_KERNEL); | 2425 | ctrl_info = kmalloc(sizeof(struct megasas_ctrl_info), GFP_KERNEL); |
2330 | 2426 | ||
2331 | /* | 2427 | /* |
diff --git a/drivers/scsi/megaraid/megaraid_sas.h b/drivers/scsi/megaraid/megaraid_sas.h index 365a96172070..8ac6b2659c12 100644 --- a/drivers/scsi/megaraid/megaraid_sas.h +++ b/drivers/scsi/megaraid/megaraid_sas.h | |||
@@ -133,6 +133,7 @@ | |||
133 | #define MR_DCMD_CLUSTER 0x08000000 | 133 | #define MR_DCMD_CLUSTER 0x08000000 |
134 | #define MR_DCMD_CLUSTER_RESET_ALL 0x08010100 | 134 | #define MR_DCMD_CLUSTER_RESET_ALL 0x08010100 |
135 | #define MR_DCMD_CLUSTER_RESET_LD 0x08010200 | 135 | #define MR_DCMD_CLUSTER_RESET_LD 0x08010200 |
136 | #define MR_DCMD_PD_LIST_QUERY 0x02010100 | ||
136 | 137 | ||
137 | /* | 138 | /* |
138 | * MFI command completion codes | 139 | * MFI command completion codes |
@@ -253,9 +254,89 @@ enum MR_EVT_ARGS { | |||
253 | MR_EVT_ARGS_STR, | 254 | MR_EVT_ARGS_STR, |
254 | MR_EVT_ARGS_TIME, | 255 | MR_EVT_ARGS_TIME, |
255 | MR_EVT_ARGS_ECC, | 256 | MR_EVT_ARGS_ECC, |
257 | MR_EVT_ARGS_LD_PROP, | ||
258 | MR_EVT_ARGS_PD_SPARE, | ||
259 | MR_EVT_ARGS_PD_INDEX, | ||
260 | MR_EVT_ARGS_DIAG_PASS, | ||
261 | MR_EVT_ARGS_DIAG_FAIL, | ||
262 | MR_EVT_ARGS_PD_LBA_LBA, | ||
263 | MR_EVT_ARGS_PORT_PHY, | ||
264 | MR_EVT_ARGS_PD_MISSING, | ||
265 | MR_EVT_ARGS_PD_ADDRESS, | ||
266 | MR_EVT_ARGS_BITMAP, | ||
267 | MR_EVT_ARGS_CONNECTOR, | ||
268 | MR_EVT_ARGS_PD_PD, | ||
269 | MR_EVT_ARGS_PD_FRU, | ||
270 | MR_EVT_ARGS_PD_PATHINFO, | ||
271 | MR_EVT_ARGS_PD_POWER_STATE, | ||
272 | MR_EVT_ARGS_GENERIC, | ||
273 | }; | ||
256 | 274 | ||
275 | /* | ||
276 | * define constants for device list query options | ||
277 | */ | ||
278 | enum MR_PD_QUERY_TYPE { | ||
279 | MR_PD_QUERY_TYPE_ALL = 0, | ||
280 | MR_PD_QUERY_TYPE_STATE = 1, | ||
281 | MR_PD_QUERY_TYPE_POWER_STATE = 2, | ||
282 | MR_PD_QUERY_TYPE_MEDIA_TYPE = 3, | ||
283 | MR_PD_QUERY_TYPE_SPEED = 4, | ||
284 | MR_PD_QUERY_TYPE_EXPOSED_TO_HOST = 5, | ||
257 | }; | 285 | }; |
258 | 286 | ||
287 | enum MR_PD_STATE { | ||
288 | MR_PD_STATE_UNCONFIGURED_GOOD = 0x00, | ||
289 | MR_PD_STATE_UNCONFIGURED_BAD = 0x01, | ||
290 | MR_PD_STATE_HOT_SPARE = 0x02, | ||
291 | MR_PD_STATE_OFFLINE = 0x10, | ||
292 | MR_PD_STATE_FAILED = 0x11, | ||
293 | MR_PD_STATE_REBUILD = 0x14, | ||
294 | MR_PD_STATE_ONLINE = 0x18, | ||
295 | MR_PD_STATE_COPYBACK = 0x20, | ||
296 | MR_PD_STATE_SYSTEM = 0x40, | ||
297 | }; | ||
298 | |||
299 | |||
300 | /* | ||
301 | * defines the physical drive address structure | ||
302 | */ | ||
303 | struct MR_PD_ADDRESS { | ||
304 | u16 deviceId; | ||
305 | u16 enclDeviceId; | ||
306 | |||
307 | union { | ||
308 | struct { | ||
309 | u8 enclIndex; | ||
310 | u8 slotNumber; | ||
311 | } mrPdAddress; | ||
312 | struct { | ||
313 | u8 enclPosition; | ||
314 | u8 enclConnectorIndex; | ||
315 | } mrEnclAddress; | ||
316 | }; | ||
317 | u8 scsiDevType; | ||
318 | union { | ||
319 | u8 connectedPortBitmap; | ||
320 | u8 connectedPortNumbers; | ||
321 | }; | ||
322 | u64 sasAddr[2]; | ||
323 | } __packed; | ||
324 | |||
325 | /* | ||
326 | * defines the physical drive list structure | ||
327 | */ | ||
328 | struct MR_PD_LIST { | ||
329 | u32 size; | ||
330 | u32 count; | ||
331 | struct MR_PD_ADDRESS addr[1]; | ||
332 | } __packed; | ||
333 | |||
334 | struct megasas_pd_list { | ||
335 | u16 tid; | ||
336 | u8 driveType; | ||
337 | u8 driveState; | ||
338 | } __packed; | ||
339 | |||
259 | /* | 340 | /* |
260 | * SAS controller properties | 341 | * SAS controller properties |
261 | */ | 342 | */ |
@@ -284,7 +365,7 @@ struct megasas_ctrl_prop { | |||
284 | u8 expose_encl_devices; | 365 | u8 expose_encl_devices; |
285 | u8 reserved[38]; | 366 | u8 reserved[38]; |
286 | 367 | ||
287 | } __attribute__ ((packed)); | 368 | } __packed; |
288 | 369 | ||
289 | /* | 370 | /* |
290 | * SAS controller information | 371 | * SAS controller information |
@@ -527,7 +608,7 @@ struct megasas_ctrl_info { | |||
527 | 608 | ||
528 | u8 pad[0x800 - 0x6a0]; | 609 | u8 pad[0x800 - 0x6a0]; |
529 | 610 | ||
530 | } __attribute__ ((packed)); | 611 | } __packed; |
531 | 612 | ||
532 | /* | 613 | /* |
533 | * =============================== | 614 | * =============================== |
@@ -542,6 +623,8 @@ struct megasas_ctrl_info { | |||
542 | #define MEGASAS_DEFAULT_INIT_ID -1 | 623 | #define MEGASAS_DEFAULT_INIT_ID -1 |
543 | #define MEGASAS_MAX_LUN 8 | 624 | #define MEGASAS_MAX_LUN 8 |
544 | #define MEGASAS_MAX_LD 64 | 625 | #define MEGASAS_MAX_LD 64 |
626 | #define MEGASAS_MAX_PD (MEGASAS_MAX_PD_CHANNELS * \ | ||
627 | MEGASAS_MAX_DEV_PER_CHANNEL) | ||
545 | 628 | ||
546 | #define MEGASAS_DBG_LVL 1 | 629 | #define MEGASAS_DBG_LVL 1 |
547 | 630 | ||
@@ -1089,6 +1172,7 @@ struct megasas_instance { | |||
1089 | unsigned long base_addr; | 1172 | unsigned long base_addr; |
1090 | struct megasas_register_set __iomem *reg_set; | 1173 | struct megasas_register_set __iomem *reg_set; |
1091 | 1174 | ||
1175 | struct megasas_pd_list pd_list[MEGASAS_MAX_PD]; | ||
1092 | s8 init_id; | 1176 | s8 init_id; |
1093 | 1177 | ||
1094 | u16 max_num_sge; | 1178 | u16 max_num_sge; |