diff options
Diffstat (limited to 'drivers/scsi/pm8001')
-rw-r--r-- | drivers/scsi/pm8001/pm8001_ctl.c | 153 | ||||
-rw-r--r-- | drivers/scsi/pm8001/pm8001_ctl.h | 6 | ||||
-rw-r--r-- | drivers/scsi/pm8001/pm8001_defs.h | 8 | ||||
-rw-r--r-- | drivers/scsi/pm8001/pm8001_hwi.c | 152 | ||||
-rw-r--r-- | drivers/scsi/pm8001/pm8001_hwi.h | 3 | ||||
-rw-r--r-- | drivers/scsi/pm8001/pm8001_init.c | 65 | ||||
-rw-r--r-- | drivers/scsi/pm8001/pm8001_sas.c | 9 | ||||
-rw-r--r-- | drivers/scsi/pm8001/pm8001_sas.h | 74 | ||||
-rw-r--r-- | drivers/scsi/pm8001/pm80xx_hwi.c | 523 | ||||
-rw-r--r-- | drivers/scsi/pm8001/pm80xx_hwi.h | 15 |
10 files changed, 965 insertions, 43 deletions
diff --git a/drivers/scsi/pm8001/pm8001_ctl.c b/drivers/scsi/pm8001/pm8001_ctl.c index d99f41c2ca13..a04b4ff8c7f6 100644 --- a/drivers/scsi/pm8001/pm8001_ctl.c +++ b/drivers/scsi/pm8001/pm8001_ctl.c | |||
@@ -309,6 +309,117 @@ static ssize_t pm8001_ctl_aap_log_show(struct device *cdev, | |||
309 | } | 309 | } |
310 | static DEVICE_ATTR(aap_log, S_IRUGO, pm8001_ctl_aap_log_show, NULL); | 310 | static DEVICE_ATTR(aap_log, S_IRUGO, pm8001_ctl_aap_log_show, NULL); |
311 | /** | 311 | /** |
312 | * pm8001_ctl_ib_queue_log_show - Out bound Queue log | ||
313 | * @cdev:pointer to embedded class device | ||
314 | * @buf: the buffer returned | ||
315 | * A sysfs 'read-only' shost attribute. | ||
316 | */ | ||
317 | static ssize_t pm8001_ctl_ib_queue_log_show(struct device *cdev, | ||
318 | struct device_attribute *attr, char *buf) | ||
319 | { | ||
320 | struct Scsi_Host *shost = class_to_shost(cdev); | ||
321 | struct sas_ha_struct *sha = SHOST_TO_SAS_HA(shost); | ||
322 | struct pm8001_hba_info *pm8001_ha = sha->lldd_ha; | ||
323 | int offset; | ||
324 | char *str = buf; | ||
325 | int start = 0; | ||
326 | #define IB_MEMMAP(c) \ | ||
327 | (*(u32 *)((u8 *)pm8001_ha-> \ | ||
328 | memoryMap.region[IB].virt_ptr + \ | ||
329 | pm8001_ha->evtlog_ib_offset + (c))) | ||
330 | |||
331 | for (offset = 0; offset < IB_OB_READ_TIMES; offset++) { | ||
332 | if (pm8001_ha->chip_id != chip_8001) | ||
333 | str += sprintf(str, "0x%08x\n", IB_MEMMAP(start)); | ||
334 | else | ||
335 | str += sprintf(str, "0x%08x\n", IB_MEMMAP(start)); | ||
336 | start = start + 4; | ||
337 | } | ||
338 | pm8001_ha->evtlog_ib_offset += SYSFS_OFFSET; | ||
339 | if ((((pm8001_ha->evtlog_ib_offset) % (PM80XX_IB_OB_QUEUE_SIZE)) == 0) | ||
340 | && (pm8001_ha->chip_id != chip_8001)) | ||
341 | pm8001_ha->evtlog_ib_offset = 0; | ||
342 | if ((((pm8001_ha->evtlog_ib_offset) % (PM8001_IB_OB_QUEUE_SIZE)) == 0) | ||
343 | && (pm8001_ha->chip_id == chip_8001)) | ||
344 | pm8001_ha->evtlog_ib_offset = 0; | ||
345 | |||
346 | return str - buf; | ||
347 | } | ||
348 | |||
349 | static DEVICE_ATTR(ib_log, S_IRUGO, pm8001_ctl_ib_queue_log_show, NULL); | ||
350 | /** | ||
351 | * pm8001_ctl_ob_queue_log_show - Out bound Queue log | ||
352 | * @cdev:pointer to embedded class device | ||
353 | * @buf: the buffer returned | ||
354 | * A sysfs 'read-only' shost attribute. | ||
355 | */ | ||
356 | |||
357 | static ssize_t pm8001_ctl_ob_queue_log_show(struct device *cdev, | ||
358 | struct device_attribute *attr, char *buf) | ||
359 | { | ||
360 | struct Scsi_Host *shost = class_to_shost(cdev); | ||
361 | struct sas_ha_struct *sha = SHOST_TO_SAS_HA(shost); | ||
362 | struct pm8001_hba_info *pm8001_ha = sha->lldd_ha; | ||
363 | int offset; | ||
364 | char *str = buf; | ||
365 | int start = 0; | ||
366 | #define OB_MEMMAP(c) \ | ||
367 | (*(u32 *)((u8 *)pm8001_ha-> \ | ||
368 | memoryMap.region[OB].virt_ptr + \ | ||
369 | pm8001_ha->evtlog_ob_offset + (c))) | ||
370 | |||
371 | for (offset = 0; offset < IB_OB_READ_TIMES; offset++) { | ||
372 | if (pm8001_ha->chip_id != chip_8001) | ||
373 | str += sprintf(str, "0x%08x\n", OB_MEMMAP(start)); | ||
374 | else | ||
375 | str += sprintf(str, "0x%08x\n", OB_MEMMAP(start)); | ||
376 | start = start + 4; | ||
377 | } | ||
378 | pm8001_ha->evtlog_ob_offset += SYSFS_OFFSET; | ||
379 | if ((((pm8001_ha->evtlog_ob_offset) % (PM80XX_IB_OB_QUEUE_SIZE)) == 0) | ||
380 | && (pm8001_ha->chip_id != chip_8001)) | ||
381 | pm8001_ha->evtlog_ob_offset = 0; | ||
382 | if ((((pm8001_ha->evtlog_ob_offset) % (PM8001_IB_OB_QUEUE_SIZE)) == 0) | ||
383 | && (pm8001_ha->chip_id == chip_8001)) | ||
384 | pm8001_ha->evtlog_ob_offset = 0; | ||
385 | |||
386 | return str - buf; | ||
387 | } | ||
388 | static DEVICE_ATTR(ob_log, S_IRUGO, pm8001_ctl_ob_queue_log_show, NULL); | ||
389 | /** | ||
390 | * pm8001_ctl_bios_version_show - Bios version Display | ||
391 | * @cdev:pointer to embedded class device | ||
392 | * @buf:the buffer returned | ||
393 | * A sysfs 'read-only' shost attribute. | ||
394 | */ | ||
395 | static ssize_t pm8001_ctl_bios_version_show(struct device *cdev, | ||
396 | struct device_attribute *attr, char *buf) | ||
397 | { | ||
398 | struct Scsi_Host *shost = class_to_shost(cdev); | ||
399 | struct sas_ha_struct *sha = SHOST_TO_SAS_HA(shost); | ||
400 | struct pm8001_hba_info *pm8001_ha = sha->lldd_ha; | ||
401 | char *str = buf; | ||
402 | void *virt_addr; | ||
403 | int bios_index; | ||
404 | DECLARE_COMPLETION_ONSTACK(completion); | ||
405 | struct pm8001_ioctl_payload payload; | ||
406 | |||
407 | pm8001_ha->nvmd_completion = &completion; | ||
408 | payload.minor_function = 7; | ||
409 | payload.offset = 0; | ||
410 | payload.length = 4096; | ||
411 | payload.func_specific = kzalloc(4096, GFP_KERNEL); | ||
412 | PM8001_CHIP_DISP->get_nvmd_req(pm8001_ha, &payload); | ||
413 | wait_for_completion(&completion); | ||
414 | virt_addr = pm8001_ha->memoryMap.region[NVMD].virt_ptr; | ||
415 | for (bios_index = BIOSOFFSET; bios_index < BIOS_OFFSET_LIMIT; | ||
416 | bios_index++) | ||
417 | str += sprintf(str, "%c", | ||
418 | *((u8 *)((u8 *)virt_addr+bios_index))); | ||
419 | return str - buf; | ||
420 | } | ||
421 | static DEVICE_ATTR(bios_version, S_IRUGO, pm8001_ctl_bios_version_show, NULL); | ||
422 | /** | ||
312 | * pm8001_ctl_aap_log_show - IOP event log | 423 | * pm8001_ctl_aap_log_show - IOP event log |
313 | * @cdev: pointer to embedded class device | 424 | * @cdev: pointer to embedded class device |
314 | * @buf: the buffer returned | 425 | * @buf: the buffer returned |
@@ -344,6 +455,43 @@ static ssize_t pm8001_ctl_iop_log_show(struct device *cdev, | |||
344 | } | 455 | } |
345 | static DEVICE_ATTR(iop_log, S_IRUGO, pm8001_ctl_iop_log_show, NULL); | 456 | static DEVICE_ATTR(iop_log, S_IRUGO, pm8001_ctl_iop_log_show, NULL); |
346 | 457 | ||
458 | /** | ||
459 | ** pm8001_ctl_fatal_log_show - fatal error logging | ||
460 | ** @cdev:pointer to embedded class device | ||
461 | ** @buf: the buffer returned | ||
462 | ** | ||
463 | ** A sysfs 'read-only' shost attribute. | ||
464 | **/ | ||
465 | |||
466 | static ssize_t pm8001_ctl_fatal_log_show(struct device *cdev, | ||
467 | struct device_attribute *attr, char *buf) | ||
468 | { | ||
469 | u32 count; | ||
470 | |||
471 | count = pm80xx_get_fatal_dump(cdev, attr, buf); | ||
472 | return count; | ||
473 | } | ||
474 | |||
475 | static DEVICE_ATTR(fatal_log, S_IRUGO, pm8001_ctl_fatal_log_show, NULL); | ||
476 | |||
477 | |||
478 | /** | ||
479 | ** pm8001_ctl_gsm_log_show - gsm dump collection | ||
480 | ** @cdev:pointer to embedded class device | ||
481 | ** @buf: the buffer returned | ||
482 | **A sysfs 'read-only' shost attribute. | ||
483 | **/ | ||
484 | static ssize_t pm8001_ctl_gsm_log_show(struct device *cdev, | ||
485 | struct device_attribute *attr, char *buf) | ||
486 | { | ||
487 | u32 count; | ||
488 | |||
489 | count = pm8001_get_gsm_dump(cdev, SYSFS_OFFSET, buf); | ||
490 | return count; | ||
491 | } | ||
492 | |||
493 | static DEVICE_ATTR(gsm_log, S_IRUGO, pm8001_ctl_gsm_log_show, NULL); | ||
494 | |||
347 | #define FLASH_CMD_NONE 0x00 | 495 | #define FLASH_CMD_NONE 0x00 |
348 | #define FLASH_CMD_UPDATE 0x01 | 496 | #define FLASH_CMD_UPDATE 0x01 |
349 | #define FLASH_CMD_SET_NVMD 0x02 | 497 | #define FLASH_CMD_SET_NVMD 0x02 |
@@ -603,12 +751,17 @@ struct device_attribute *pm8001_host_attrs[] = { | |||
603 | &dev_attr_update_fw, | 751 | &dev_attr_update_fw, |
604 | &dev_attr_aap_log, | 752 | &dev_attr_aap_log, |
605 | &dev_attr_iop_log, | 753 | &dev_attr_iop_log, |
754 | &dev_attr_fatal_log, | ||
755 | &dev_attr_gsm_log, | ||
606 | &dev_attr_max_out_io, | 756 | &dev_attr_max_out_io, |
607 | &dev_attr_max_devices, | 757 | &dev_attr_max_devices, |
608 | &dev_attr_max_sg_list, | 758 | &dev_attr_max_sg_list, |
609 | &dev_attr_sas_spec_support, | 759 | &dev_attr_sas_spec_support, |
610 | &dev_attr_logging_level, | 760 | &dev_attr_logging_level, |
611 | &dev_attr_host_sas_address, | 761 | &dev_attr_host_sas_address, |
762 | &dev_attr_bios_version, | ||
763 | &dev_attr_ib_log, | ||
764 | &dev_attr_ob_log, | ||
612 | NULL, | 765 | NULL, |
613 | }; | 766 | }; |
614 | 767 | ||
diff --git a/drivers/scsi/pm8001/pm8001_ctl.h b/drivers/scsi/pm8001/pm8001_ctl.h index 63ad4aa0c422..d0d43a250b9e 100644 --- a/drivers/scsi/pm8001/pm8001_ctl.h +++ b/drivers/scsi/pm8001/pm8001_ctl.h | |||
@@ -45,6 +45,8 @@ | |||
45 | #define HEADER_LEN 28 | 45 | #define HEADER_LEN 28 |
46 | #define SIZE_OFFSET 16 | 46 | #define SIZE_OFFSET 16 |
47 | 47 | ||
48 | #define BIOSOFFSET 56 | ||
49 | #define BIOS_OFFSET_LIMIT 61 | ||
48 | 50 | ||
49 | #define FLASH_OK 0x000000 | 51 | #define FLASH_OK 0x000000 |
50 | #define FAIL_OPEN_BIOS_FILE 0x000100 | 52 | #define FAIL_OPEN_BIOS_FILE 0x000100 |
@@ -53,5 +55,9 @@ | |||
53 | #define FAIL_OUT_MEMORY 0x000c00 | 55 | #define FAIL_OUT_MEMORY 0x000c00 |
54 | #define FLASH_IN_PROGRESS 0x001000 | 56 | #define FLASH_IN_PROGRESS 0x001000 |
55 | 57 | ||
58 | #define IB_OB_READ_TIMES 256 | ||
59 | #define SYSFS_OFFSET 1024 | ||
60 | #define PM80XX_IB_OB_QUEUE_SIZE (32 * 1024) | ||
61 | #define PM8001_IB_OB_QUEUE_SIZE (16 * 1024) | ||
56 | #endif /* PM8001_CTL_H_INCLUDED */ | 62 | #endif /* PM8001_CTL_H_INCLUDED */ |
57 | 63 | ||
diff --git a/drivers/scsi/pm8001/pm8001_defs.h b/drivers/scsi/pm8001/pm8001_defs.h index 479c5a7a863a..74a4bb9af07b 100644 --- a/drivers/scsi/pm8001/pm8001_defs.h +++ b/drivers/scsi/pm8001/pm8001_defs.h | |||
@@ -46,7 +46,10 @@ enum chip_flavors { | |||
46 | chip_8008, | 46 | chip_8008, |
47 | chip_8009, | 47 | chip_8009, |
48 | chip_8018, | 48 | chip_8018, |
49 | chip_8019 | 49 | chip_8019, |
50 | chip_8074, | ||
51 | chip_8076, | ||
52 | chip_8077 | ||
50 | }; | 53 | }; |
51 | 54 | ||
52 | enum phy_speed { | 55 | enum phy_speed { |
@@ -99,7 +102,8 @@ enum memory_region_num { | |||
99 | NVMD, /* NVM device */ | 102 | NVMD, /* NVM device */ |
100 | DEV_MEM, /* memory for devices */ | 103 | DEV_MEM, /* memory for devices */ |
101 | CCB_MEM, /* memory for command control block */ | 104 | CCB_MEM, /* memory for command control block */ |
102 | FW_FLASH /* memory for fw flash update */ | 105 | FW_FLASH, /* memory for fw flash update */ |
106 | FORENSIC_MEM /* memory for fw forensic data */ | ||
103 | }; | 107 | }; |
104 | #define PM8001_EVENT_LOG_SIZE (128 * 1024) | 108 | #define PM8001_EVENT_LOG_SIZE (128 * 1024) |
105 | 109 | ||
diff --git a/drivers/scsi/pm8001/pm8001_hwi.c b/drivers/scsi/pm8001/pm8001_hwi.c index 4a2195752198..f16ece91b94a 100644 --- a/drivers/scsi/pm8001/pm8001_hwi.c +++ b/drivers/scsi/pm8001/pm8001_hwi.c | |||
@@ -1868,6 +1868,13 @@ mpi_ssp_completion(struct pm8001_hba_info *pm8001_ha , void *piomb) | |||
1868 | if (unlikely(!t || !t->lldd_task || !t->dev)) | 1868 | if (unlikely(!t || !t->lldd_task || !t->dev)) |
1869 | return; | 1869 | return; |
1870 | ts = &t->task_status; | 1870 | ts = &t->task_status; |
1871 | /* Print sas address of IO failed device */ | ||
1872 | if ((status != IO_SUCCESS) && (status != IO_OVERFLOW) && | ||
1873 | (status != IO_UNDERFLOW)) | ||
1874 | PM8001_FAIL_DBG(pm8001_ha, | ||
1875 | pm8001_printk("SAS Address of IO Failure Drive:" | ||
1876 | "%016llx", SAS_ADDR(t->dev->sas_addr))); | ||
1877 | |||
1871 | switch (status) { | 1878 | switch (status) { |
1872 | case IO_SUCCESS: | 1879 | case IO_SUCCESS: |
1873 | PM8001_IO_DBG(pm8001_ha, pm8001_printk("IO_SUCCESS" | 1880 | PM8001_IO_DBG(pm8001_ha, pm8001_printk("IO_SUCCESS" |
@@ -2276,6 +2283,11 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, void *piomb) | |||
2276 | u32 param; | 2283 | u32 param; |
2277 | u32 status; | 2284 | u32 status; |
2278 | u32 tag; | 2285 | u32 tag; |
2286 | int i, j; | ||
2287 | u8 sata_addr_low[4]; | ||
2288 | u32 temp_sata_addr_low; | ||
2289 | u8 sata_addr_hi[4]; | ||
2290 | u32 temp_sata_addr_hi; | ||
2279 | struct sata_completion_resp *psataPayload; | 2291 | struct sata_completion_resp *psataPayload; |
2280 | struct task_status_struct *ts; | 2292 | struct task_status_struct *ts; |
2281 | struct ata_task_resp *resp ; | 2293 | struct ata_task_resp *resp ; |
@@ -2325,7 +2337,46 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, void *piomb) | |||
2325 | pm8001_printk("ts null\n")); | 2337 | pm8001_printk("ts null\n")); |
2326 | return; | 2338 | return; |
2327 | } | 2339 | } |
2328 | 2340 | /* Print sas address of IO failed device */ | |
2341 | if ((status != IO_SUCCESS) && (status != IO_OVERFLOW) && | ||
2342 | (status != IO_UNDERFLOW)) { | ||
2343 | if (!((t->dev->parent) && | ||
2344 | (DEV_IS_EXPANDER(t->dev->parent->dev_type)))) { | ||
2345 | for (i = 0 , j = 4; j <= 7 && i <= 3; i++ , j++) | ||
2346 | sata_addr_low[i] = pm8001_ha->sas_addr[j]; | ||
2347 | for (i = 0 , j = 0; j <= 3 && i <= 3; i++ , j++) | ||
2348 | sata_addr_hi[i] = pm8001_ha->sas_addr[j]; | ||
2349 | memcpy(&temp_sata_addr_low, sata_addr_low, | ||
2350 | sizeof(sata_addr_low)); | ||
2351 | memcpy(&temp_sata_addr_hi, sata_addr_hi, | ||
2352 | sizeof(sata_addr_hi)); | ||
2353 | temp_sata_addr_hi = (((temp_sata_addr_hi >> 24) & 0xff) | ||
2354 | |((temp_sata_addr_hi << 8) & | ||
2355 | 0xff0000) | | ||
2356 | ((temp_sata_addr_hi >> 8) | ||
2357 | & 0xff00) | | ||
2358 | ((temp_sata_addr_hi << 24) & | ||
2359 | 0xff000000)); | ||
2360 | temp_sata_addr_low = ((((temp_sata_addr_low >> 24) | ||
2361 | & 0xff) | | ||
2362 | ((temp_sata_addr_low << 8) | ||
2363 | & 0xff0000) | | ||
2364 | ((temp_sata_addr_low >> 8) | ||
2365 | & 0xff00) | | ||
2366 | ((temp_sata_addr_low << 24) | ||
2367 | & 0xff000000)) + | ||
2368 | pm8001_dev->attached_phy + | ||
2369 | 0x10); | ||
2370 | PM8001_FAIL_DBG(pm8001_ha, | ||
2371 | pm8001_printk("SAS Address of IO Failure Drive:" | ||
2372 | "%08x%08x", temp_sata_addr_hi, | ||
2373 | temp_sata_addr_low)); | ||
2374 | } else { | ||
2375 | PM8001_FAIL_DBG(pm8001_ha, | ||
2376 | pm8001_printk("SAS Address of IO Failure Drive:" | ||
2377 | "%016llx", SAS_ADDR(t->dev->sas_addr))); | ||
2378 | } | ||
2379 | } | ||
2329 | switch (status) { | 2380 | switch (status) { |
2330 | case IO_SUCCESS: | 2381 | case IO_SUCCESS: |
2331 | PM8001_IO_DBG(pm8001_ha, pm8001_printk("IO_SUCCESS\n")); | 2382 | PM8001_IO_DBG(pm8001_ha, pm8001_printk("IO_SUCCESS\n")); |
@@ -3087,8 +3138,8 @@ void pm8001_mpi_set_dev_state_resp(struct pm8001_hba_info *pm8001_ha, | |||
3087 | struct pm8001_device *pm8001_dev = ccb->device; | 3138 | struct pm8001_device *pm8001_dev = ccb->device; |
3088 | u32 status = le32_to_cpu(pPayload->status); | 3139 | u32 status = le32_to_cpu(pPayload->status); |
3089 | u32 device_id = le32_to_cpu(pPayload->device_id); | 3140 | u32 device_id = le32_to_cpu(pPayload->device_id); |
3090 | u8 pds = le32_to_cpu(pPayload->pds_nds) | PDS_BITS; | 3141 | u8 pds = le32_to_cpu(pPayload->pds_nds) & PDS_BITS; |
3091 | u8 nds = le32_to_cpu(pPayload->pds_nds) | NDS_BITS; | 3142 | u8 nds = le32_to_cpu(pPayload->pds_nds) & NDS_BITS; |
3092 | PM8001_MSG_DBG(pm8001_ha, pm8001_printk("Set device id = 0x%x state " | 3143 | PM8001_MSG_DBG(pm8001_ha, pm8001_printk("Set device id = 0x%x state " |
3093 | "from 0x%x to 0x%x status = 0x%x!\n", | 3144 | "from 0x%x to 0x%x status = 0x%x!\n", |
3094 | device_id, pds, nds, status)); | 3145 | device_id, pds, nds, status)); |
@@ -4700,6 +4751,8 @@ int pm8001_chip_ssp_tm_req(struct pm8001_hba_info *pm8001_ha, | |||
4700 | sspTMCmd.tmf = cpu_to_le32(tmf->tmf); | 4751 | sspTMCmd.tmf = cpu_to_le32(tmf->tmf); |
4701 | memcpy(sspTMCmd.lun, task->ssp_task.LUN, 8); | 4752 | memcpy(sspTMCmd.lun, task->ssp_task.LUN, 8); |
4702 | sspTMCmd.tag = cpu_to_le32(ccb->ccb_tag); | 4753 | sspTMCmd.tag = cpu_to_le32(ccb->ccb_tag); |
4754 | if (pm8001_ha->chip_id != chip_8001) | ||
4755 | sspTMCmd.ds_ads_m = 0x08; | ||
4703 | circularQ = &pm8001_ha->inbnd_q_tbl[0]; | 4756 | circularQ = &pm8001_ha->inbnd_q_tbl[0]; |
4704 | ret = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &sspTMCmd, 0); | 4757 | ret = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &sspTMCmd, 0); |
4705 | return ret; | 4758 | return ret; |
@@ -4778,6 +4831,16 @@ int pm8001_chip_get_nvmd_req(struct pm8001_hba_info *pm8001_ha, | |||
4778 | cpu_to_le32(pm8001_ha->memoryMap.region[NVMD].phys_addr_lo); | 4831 | cpu_to_le32(pm8001_ha->memoryMap.region[NVMD].phys_addr_lo); |
4779 | break; | 4832 | break; |
4780 | } | 4833 | } |
4834 | case IOP_RDUMP: { | ||
4835 | nvmd_req.len_ir_vpdd = cpu_to_le32(IPMode | IOP_RDUMP); | ||
4836 | nvmd_req.resp_len = cpu_to_le32(ioctl_payload->length); | ||
4837 | nvmd_req.vpd_offset = cpu_to_le32(ioctl_payload->offset); | ||
4838 | nvmd_req.resp_addr_hi = | ||
4839 | cpu_to_le32(pm8001_ha->memoryMap.region[NVMD].phys_addr_hi); | ||
4840 | nvmd_req.resp_addr_lo = | ||
4841 | cpu_to_le32(pm8001_ha->memoryMap.region[NVMD].phys_addr_lo); | ||
4842 | break; | ||
4843 | } | ||
4781 | default: | 4844 | default: |
4782 | break; | 4845 | break; |
4783 | } | 4846 | } |
@@ -4938,6 +5001,89 @@ pm8001_chip_fw_flash_update_req(struct pm8001_hba_info *pm8001_ha, | |||
4938 | return rc; | 5001 | return rc; |
4939 | } | 5002 | } |
4940 | 5003 | ||
5004 | ssize_t | ||
5005 | pm8001_get_gsm_dump(struct device *cdev, u32 length, char *buf) | ||
5006 | { | ||
5007 | u32 value, rem, offset = 0, bar = 0; | ||
5008 | u32 index, work_offset, dw_length; | ||
5009 | u32 shift_value, gsm_base, gsm_dump_offset; | ||
5010 | char *direct_data; | ||
5011 | struct Scsi_Host *shost = class_to_shost(cdev); | ||
5012 | struct sas_ha_struct *sha = SHOST_TO_SAS_HA(shost); | ||
5013 | struct pm8001_hba_info *pm8001_ha = sha->lldd_ha; | ||
5014 | |||
5015 | direct_data = buf; | ||
5016 | gsm_dump_offset = pm8001_ha->fatal_forensic_shift_offset; | ||
5017 | |||
5018 | /* check max is 1 Mbytes */ | ||
5019 | if ((length > 0x100000) || (gsm_dump_offset & 3) || | ||
5020 | ((gsm_dump_offset + length) > 0x1000000)) | ||
5021 | return 1; | ||
5022 | |||
5023 | if (pm8001_ha->chip_id == chip_8001) | ||
5024 | bar = 2; | ||
5025 | else | ||
5026 | bar = 1; | ||
5027 | |||
5028 | work_offset = gsm_dump_offset & 0xFFFF0000; | ||
5029 | offset = gsm_dump_offset & 0x0000FFFF; | ||
5030 | gsm_dump_offset = work_offset; | ||
5031 | /* adjust length to dword boundary */ | ||
5032 | rem = length & 3; | ||
5033 | dw_length = length >> 2; | ||
5034 | |||
5035 | for (index = 0; index < dw_length; index++) { | ||
5036 | if ((work_offset + offset) & 0xFFFF0000) { | ||
5037 | if (pm8001_ha->chip_id == chip_8001) | ||
5038 | shift_value = ((gsm_dump_offset + offset) & | ||
5039 | SHIFT_REG_64K_MASK); | ||
5040 | else | ||
5041 | shift_value = (((gsm_dump_offset + offset) & | ||
5042 | SHIFT_REG_64K_MASK) >> | ||
5043 | SHIFT_REG_BIT_SHIFT); | ||
5044 | |||
5045 | if (pm8001_ha->chip_id == chip_8001) { | ||
5046 | gsm_base = GSM_BASE; | ||
5047 | if (-1 == pm8001_bar4_shift(pm8001_ha, | ||
5048 | (gsm_base + shift_value))) | ||
5049 | return 1; | ||
5050 | } else { | ||
5051 | gsm_base = 0; | ||
5052 | if (-1 == pm80xx_bar4_shift(pm8001_ha, | ||
5053 | (gsm_base + shift_value))) | ||
5054 | return 1; | ||
5055 | } | ||
5056 | gsm_dump_offset = (gsm_dump_offset + offset) & | ||
5057 | 0xFFFF0000; | ||
5058 | work_offset = 0; | ||
5059 | offset = offset & 0x0000FFFF; | ||
5060 | } | ||
5061 | value = pm8001_cr32(pm8001_ha, bar, (work_offset + offset) & | ||
5062 | 0x0000FFFF); | ||
5063 | direct_data += sprintf(direct_data, "%08x ", value); | ||
5064 | offset += 4; | ||
5065 | } | ||
5066 | if (rem != 0) { | ||
5067 | value = pm8001_cr32(pm8001_ha, bar, (work_offset + offset) & | ||
5068 | 0x0000FFFF); | ||
5069 | /* xfr for non_dw */ | ||
5070 | direct_data += sprintf(direct_data, "%08x ", value); | ||
5071 | } | ||
5072 | /* Shift back to BAR4 original address */ | ||
5073 | if (pm8001_ha->chip_id == chip_8001) { | ||
5074 | if (-1 == pm8001_bar4_shift(pm8001_ha, 0)) | ||
5075 | return 1; | ||
5076 | } else { | ||
5077 | if (-1 == pm80xx_bar4_shift(pm8001_ha, 0)) | ||
5078 | return 1; | ||
5079 | } | ||
5080 | pm8001_ha->fatal_forensic_shift_offset += 1024; | ||
5081 | |||
5082 | if (pm8001_ha->fatal_forensic_shift_offset >= 0x100000) | ||
5083 | pm8001_ha->fatal_forensic_shift_offset = 0; | ||
5084 | return direct_data - buf; | ||
5085 | } | ||
5086 | |||
4941 | int | 5087 | int |
4942 | pm8001_chip_set_dev_state_req(struct pm8001_hba_info *pm8001_ha, | 5088 | pm8001_chip_set_dev_state_req(struct pm8001_hba_info *pm8001_ha, |
4943 | struct pm8001_device *pm8001_dev, u32 state) | 5089 | struct pm8001_device *pm8001_dev, u32 state) |
diff --git a/drivers/scsi/pm8001/pm8001_hwi.h b/drivers/scsi/pm8001/pm8001_hwi.h index d7c1e2034226..6d91e2446542 100644 --- a/drivers/scsi/pm8001/pm8001_hwi.h +++ b/drivers/scsi/pm8001/pm8001_hwi.h | |||
@@ -1027,5 +1027,8 @@ struct set_dev_state_resp { | |||
1027 | #define DEVREG_FAILURE_PORT_NOT_VALID_STATE 0x06 | 1027 | #define DEVREG_FAILURE_PORT_NOT_VALID_STATE 0x06 |
1028 | #define DEVREG_FAILURE_DEVICE_TYPE_NOT_VALID 0x07 | 1028 | #define DEVREG_FAILURE_DEVICE_TYPE_NOT_VALID 0x07 |
1029 | 1029 | ||
1030 | #define GSM_BASE 0x4F0000 | ||
1031 | #define SHIFT_REG_64K_MASK 0xffff0000 | ||
1032 | #define SHIFT_REG_BIT_SHIFT 8 | ||
1030 | #endif | 1033 | #endif |
1031 | 1034 | ||
diff --git a/drivers/scsi/pm8001/pm8001_init.c b/drivers/scsi/pm8001/pm8001_init.c index f7c189606b84..662bf13c42f0 100644 --- a/drivers/scsi/pm8001/pm8001_init.c +++ b/drivers/scsi/pm8001/pm8001_init.c | |||
@@ -54,6 +54,9 @@ static const struct pm8001_chip_info pm8001_chips[] = { | |||
54 | [chip_8009] = {1, 8, &pm8001_80xx_dispatch,}, | 54 | [chip_8009] = {1, 8, &pm8001_80xx_dispatch,}, |
55 | [chip_8018] = {0, 16, &pm8001_80xx_dispatch,}, | 55 | [chip_8018] = {0, 16, &pm8001_80xx_dispatch,}, |
56 | [chip_8019] = {1, 16, &pm8001_80xx_dispatch,}, | 56 | [chip_8019] = {1, 16, &pm8001_80xx_dispatch,}, |
57 | [chip_8074] = {0, 8, &pm8001_80xx_dispatch,}, | ||
58 | [chip_8076] = {0, 16, &pm8001_80xx_dispatch,}, | ||
59 | [chip_8077] = {0, 16, &pm8001_80xx_dispatch,}, | ||
57 | }; | 60 | }; |
58 | static int pm8001_id; | 61 | static int pm8001_id; |
59 | 62 | ||
@@ -344,6 +347,10 @@ static int pm8001_alloc(struct pm8001_hba_info *pm8001_ha, | |||
344 | /* Memory region for fw flash */ | 347 | /* Memory region for fw flash */ |
345 | pm8001_ha->memoryMap.region[FW_FLASH].total_len = 4096; | 348 | pm8001_ha->memoryMap.region[FW_FLASH].total_len = 4096; |
346 | 349 | ||
350 | pm8001_ha->memoryMap.region[FORENSIC_MEM].num_elements = 1; | ||
351 | pm8001_ha->memoryMap.region[FORENSIC_MEM].total_len = 0x10000; | ||
352 | pm8001_ha->memoryMap.region[FORENSIC_MEM].element_size = 0x10000; | ||
353 | pm8001_ha->memoryMap.region[FORENSIC_MEM].alignment = 0x10000; | ||
347 | for (i = 0; i < USI_MAX_MEMCNT; i++) { | 354 | for (i = 0; i < USI_MAX_MEMCNT; i++) { |
348 | if (pm8001_mem_alloc(pm8001_ha->pdev, | 355 | if (pm8001_mem_alloc(pm8001_ha->pdev, |
349 | &pm8001_ha->memoryMap.region[i].virt_ptr, | 356 | &pm8001_ha->memoryMap.region[i].virt_ptr, |
@@ -664,6 +671,31 @@ static void pm8001_init_sas_add(struct pm8001_hba_info *pm8001_ha) | |||
664 | #endif | 671 | #endif |
665 | } | 672 | } |
666 | 673 | ||
674 | /* | ||
675 | * pm8001_get_phy_settings_info : Read phy setting values. | ||
676 | * @pm8001_ha : our hba. | ||
677 | */ | ||
678 | void pm8001_get_phy_settings_info(struct pm8001_hba_info *pm8001_ha) | ||
679 | { | ||
680 | |||
681 | #ifdef PM8001_READ_VPD | ||
682 | /*OPTION ROM FLASH read for the SPC cards */ | ||
683 | DECLARE_COMPLETION_ONSTACK(completion); | ||
684 | struct pm8001_ioctl_payload payload; | ||
685 | |||
686 | pm8001_ha->nvmd_completion = &completion; | ||
687 | /* SAS ADDRESS read from flash / EEPROM */ | ||
688 | payload.minor_function = 6; | ||
689 | payload.offset = 0; | ||
690 | payload.length = 4096; | ||
691 | payload.func_specific = kzalloc(4096, GFP_KERNEL); | ||
692 | /* Read phy setting values from flash */ | ||
693 | PM8001_CHIP_DISP->get_nvmd_req(pm8001_ha, &payload); | ||
694 | wait_for_completion(&completion); | ||
695 | pm8001_set_phy_profile(pm8001_ha, sizeof(u8), payload.func_specific); | ||
696 | #endif | ||
697 | } | ||
698 | |||
667 | #ifdef PM8001_USE_MSIX | 699 | #ifdef PM8001_USE_MSIX |
668 | /** | 700 | /** |
669 | * pm8001_setup_msix - enable MSI-X interrupt | 701 | * pm8001_setup_msix - enable MSI-X interrupt |
@@ -844,6 +876,10 @@ static int pm8001_pci_probe(struct pci_dev *pdev, | |||
844 | } | 876 | } |
845 | 877 | ||
846 | pm8001_init_sas_add(pm8001_ha); | 878 | pm8001_init_sas_add(pm8001_ha); |
879 | /* phy setting support for motherboard controller */ | ||
880 | if (pdev->subsystem_vendor != PCI_VENDOR_ID_ADAPTEC2 && | ||
881 | pdev->subsystem_vendor != 0) | ||
882 | pm8001_get_phy_settings_info(pm8001_ha); | ||
847 | pm8001_post_sas_ha_init(shost, chip); | 883 | pm8001_post_sas_ha_init(shost, chip); |
848 | rc = sas_register_ha(SHOST_TO_SAS_HA(shost)); | 884 | rc = sas_register_ha(SHOST_TO_SAS_HA(shost)); |
849 | if (rc) | 885 | if (rc) |
@@ -1037,6 +1073,12 @@ static struct pci_device_id pm8001_pci_table[] = { | |||
1037 | { PCI_VDEVICE(ADAPTEC2, 0x8009), chip_8009 }, | 1073 | { PCI_VDEVICE(ADAPTEC2, 0x8009), chip_8009 }, |
1038 | { PCI_VDEVICE(PMC_Sierra, 0x8019), chip_8019 }, | 1074 | { PCI_VDEVICE(PMC_Sierra, 0x8019), chip_8019 }, |
1039 | { PCI_VDEVICE(ADAPTEC2, 0x8019), chip_8019 }, | 1075 | { PCI_VDEVICE(ADAPTEC2, 0x8019), chip_8019 }, |
1076 | { PCI_VDEVICE(PMC_Sierra, 0x8074), chip_8074 }, | ||
1077 | { PCI_VDEVICE(ADAPTEC2, 0x8074), chip_8074 }, | ||
1078 | { PCI_VDEVICE(PMC_Sierra, 0x8076), chip_8076 }, | ||
1079 | { PCI_VDEVICE(ADAPTEC2, 0x8076), chip_8076 }, | ||
1080 | { PCI_VDEVICE(PMC_Sierra, 0x8077), chip_8077 }, | ||
1081 | { PCI_VDEVICE(ADAPTEC2, 0x8077), chip_8077 }, | ||
1040 | { PCI_VENDOR_ID_ADAPTEC2, 0x8081, | 1082 | { PCI_VENDOR_ID_ADAPTEC2, 0x8081, |
1041 | PCI_VENDOR_ID_ADAPTEC2, 0x0400, 0, 0, chip_8001 }, | 1083 | PCI_VENDOR_ID_ADAPTEC2, 0x0400, 0, 0, chip_8001 }, |
1042 | { PCI_VENDOR_ID_ADAPTEC2, 0x8081, | 1084 | { PCI_VENDOR_ID_ADAPTEC2, 0x8081, |
@@ -1057,6 +1099,24 @@ static struct pci_device_id pm8001_pci_table[] = { | |||
1057 | PCI_VENDOR_ID_ADAPTEC2, 0x0016, 0, 0, chip_8019 }, | 1099 | PCI_VENDOR_ID_ADAPTEC2, 0x0016, 0, 0, chip_8019 }, |
1058 | { PCI_VENDOR_ID_ADAPTEC2, 0x8089, | 1100 | { PCI_VENDOR_ID_ADAPTEC2, 0x8089, |
1059 | PCI_VENDOR_ID_ADAPTEC2, 0x1600, 0, 0, chip_8019 }, | 1101 | PCI_VENDOR_ID_ADAPTEC2, 0x1600, 0, 0, chip_8019 }, |
1102 | { PCI_VENDOR_ID_ADAPTEC2, 0x8074, | ||
1103 | PCI_VENDOR_ID_ADAPTEC2, 0x0800, 0, 0, chip_8074 }, | ||
1104 | { PCI_VENDOR_ID_ADAPTEC2, 0x8076, | ||
1105 | PCI_VENDOR_ID_ADAPTEC2, 0x1600, 0, 0, chip_8076 }, | ||
1106 | { PCI_VENDOR_ID_ADAPTEC2, 0x8077, | ||
1107 | PCI_VENDOR_ID_ADAPTEC2, 0x1600, 0, 0, chip_8077 }, | ||
1108 | { PCI_VENDOR_ID_ADAPTEC2, 0x8074, | ||
1109 | PCI_VENDOR_ID_ADAPTEC2, 0x0008, 0, 0, chip_8074 }, | ||
1110 | { PCI_VENDOR_ID_ADAPTEC2, 0x8076, | ||
1111 | PCI_VENDOR_ID_ADAPTEC2, 0x0016, 0, 0, chip_8076 }, | ||
1112 | { PCI_VENDOR_ID_ADAPTEC2, 0x8077, | ||
1113 | PCI_VENDOR_ID_ADAPTEC2, 0x0016, 0, 0, chip_8077 }, | ||
1114 | { PCI_VENDOR_ID_ADAPTEC2, 0x8076, | ||
1115 | PCI_VENDOR_ID_ADAPTEC2, 0x0808, 0, 0, chip_8076 }, | ||
1116 | { PCI_VENDOR_ID_ADAPTEC2, 0x8077, | ||
1117 | PCI_VENDOR_ID_ADAPTEC2, 0x0808, 0, 0, chip_8077 }, | ||
1118 | { PCI_VENDOR_ID_ADAPTEC2, 0x8074, | ||
1119 | PCI_VENDOR_ID_ADAPTEC2, 0x0404, 0, 0, chip_8074 }, | ||
1060 | {} /* terminate list */ | 1120 | {} /* terminate list */ |
1061 | }; | 1121 | }; |
1062 | 1122 | ||
@@ -1108,8 +1168,11 @@ module_init(pm8001_init); | |||
1108 | module_exit(pm8001_exit); | 1168 | module_exit(pm8001_exit); |
1109 | 1169 | ||
1110 | MODULE_AUTHOR("Jack Wang <jack_wang@usish.com>"); | 1170 | MODULE_AUTHOR("Jack Wang <jack_wang@usish.com>"); |
1171 | MODULE_AUTHOR("Anand Kumar Santhanam <AnandKumar.Santhanam@pmcs.com>"); | ||
1172 | MODULE_AUTHOR("Sangeetha Gnanasekaran <Sangeetha.Gnanasekaran@pmcs.com>"); | ||
1111 | MODULE_DESCRIPTION( | 1173 | MODULE_DESCRIPTION( |
1112 | "PMC-Sierra PM8001/8081/8088/8089 SAS/SATA controller driver"); | 1174 | "PMC-Sierra PM8001/8081/8088/8089/8074/8076/8077 " |
1175 | "SAS/SATA controller driver"); | ||
1113 | MODULE_VERSION(DRV_VERSION); | 1176 | MODULE_VERSION(DRV_VERSION); |
1114 | MODULE_LICENSE("GPL"); | 1177 | MODULE_LICENSE("GPL"); |
1115 | MODULE_DEVICE_TABLE(pci, pm8001_pci_table); | 1178 | MODULE_DEVICE_TABLE(pci, pm8001_pci_table); |
diff --git a/drivers/scsi/pm8001/pm8001_sas.c b/drivers/scsi/pm8001/pm8001_sas.c index a85d73de7c80..f4eb18e51631 100644 --- a/drivers/scsi/pm8001/pm8001_sas.c +++ b/drivers/scsi/pm8001/pm8001_sas.c | |||
@@ -447,7 +447,6 @@ static int pm8001_task_exec(struct sas_task *task, const int num, | |||
447 | break; | 447 | break; |
448 | case SAS_PROTOCOL_SATA: | 448 | case SAS_PROTOCOL_SATA: |
449 | case SAS_PROTOCOL_STP: | 449 | case SAS_PROTOCOL_STP: |
450 | case SAS_PROTOCOL_SATA | SAS_PROTOCOL_STP: | ||
451 | rc = pm8001_task_prep_ata(pm8001_ha, ccb); | 450 | rc = pm8001_task_prep_ata(pm8001_ha, ccb); |
452 | break; | 451 | break; |
453 | default: | 452 | default: |
@@ -704,6 +703,8 @@ static int pm8001_exec_internal_tmf_task(struct domain_device *dev, | |||
704 | int res, retry; | 703 | int res, retry; |
705 | struct sas_task *task = NULL; | 704 | struct sas_task *task = NULL; |
706 | struct pm8001_hba_info *pm8001_ha = pm8001_find_ha_by_dev(dev); | 705 | struct pm8001_hba_info *pm8001_ha = pm8001_find_ha_by_dev(dev); |
706 | struct pm8001_device *pm8001_dev = dev->lldd_dev; | ||
707 | DECLARE_COMPLETION_ONSTACK(completion_setstate); | ||
707 | 708 | ||
708 | for (retry = 0; retry < 3; retry++) { | 709 | for (retry = 0; retry < 3; retry++) { |
709 | task = sas_alloc_slow_task(GFP_KERNEL); | 710 | task = sas_alloc_slow_task(GFP_KERNEL); |
@@ -729,6 +730,12 @@ static int pm8001_exec_internal_tmf_task(struct domain_device *dev, | |||
729 | goto ex_err; | 730 | goto ex_err; |
730 | } | 731 | } |
731 | wait_for_completion(&task->slow_task->completion); | 732 | wait_for_completion(&task->slow_task->completion); |
733 | if (pm8001_ha->chip_id != chip_8001) { | ||
734 | pm8001_dev->setds_completion = &completion_setstate; | ||
735 | PM8001_CHIP_DISP->set_dev_state_req(pm8001_ha, | ||
736 | pm8001_dev, 0x01); | ||
737 | wait_for_completion(&completion_setstate); | ||
738 | } | ||
732 | res = -TMF_RESP_FUNC_FAILED; | 739 | res = -TMF_RESP_FUNC_FAILED; |
733 | /* Even TMF timed out, return direct. */ | 740 | /* Even TMF timed out, return direct. */ |
734 | if ((task->task_state_flags & SAS_TASK_STATE_ABORTED)) { | 741 | if ((task->task_state_flags & SAS_TASK_STATE_ABORTED)) { |
diff --git a/drivers/scsi/pm8001/pm8001_sas.h b/drivers/scsi/pm8001/pm8001_sas.h index 570819464d90..6037d477a183 100644 --- a/drivers/scsi/pm8001/pm8001_sas.h +++ b/drivers/scsi/pm8001/pm8001_sas.h | |||
@@ -104,6 +104,9 @@ do { \ | |||
104 | 104 | ||
105 | 105 | ||
106 | #define DEV_IS_EXPANDER(type) ((type == SAS_EDGE_EXPANDER_DEVICE) || (type == SAS_FANOUT_EXPANDER_DEVICE)) | 106 | #define DEV_IS_EXPANDER(type) ((type == SAS_EDGE_EXPANDER_DEVICE) || (type == SAS_FANOUT_EXPANDER_DEVICE)) |
107 | #define IS_SPCV_12G(dev) ((dev->device == 0X8074) \ | ||
108 | || (dev->device == 0X8076) \ | ||
109 | || (dev->device == 0X8077)) | ||
107 | 110 | ||
108 | #define PM8001_NAME_LENGTH 32/* generic length of strings */ | 111 | #define PM8001_NAME_LENGTH 32/* generic length of strings */ |
109 | extern struct list_head hba_list; | 112 | extern struct list_head hba_list; |
@@ -129,6 +132,61 @@ struct pm8001_ioctl_payload { | |||
129 | u8 *func_specific; | 132 | u8 *func_specific; |
130 | }; | 133 | }; |
131 | 134 | ||
135 | #define MPI_FATAL_ERROR_TABLE_OFFSET_MASK 0xFFFFFF | ||
136 | #define MPI_FATAL_ERROR_TABLE_SIZE(value) ((0xFF000000 & value) >> SHIFT24) | ||
137 | #define MPI_FATAL_EDUMP_TABLE_LO_OFFSET 0x00 /* HNFBUFL */ | ||
138 | #define MPI_FATAL_EDUMP_TABLE_HI_OFFSET 0x04 /* HNFBUFH */ | ||
139 | #define MPI_FATAL_EDUMP_TABLE_LENGTH 0x08 /* HNFBLEN */ | ||
140 | #define MPI_FATAL_EDUMP_TABLE_HANDSHAKE 0x0C /* FDDHSHK */ | ||
141 | #define MPI_FATAL_EDUMP_TABLE_STATUS 0x10 /* FDDTSTAT */ | ||
142 | #define MPI_FATAL_EDUMP_TABLE_ACCUM_LEN 0x14 /* ACCDDLEN */ | ||
143 | #define MPI_FATAL_EDUMP_HANDSHAKE_RDY 0x1 | ||
144 | #define MPI_FATAL_EDUMP_HANDSHAKE_BUSY 0x0 | ||
145 | #define MPI_FATAL_EDUMP_TABLE_STAT_RSVD 0x0 | ||
146 | #define MPI_FATAL_EDUMP_TABLE_STAT_DMA_FAILED 0x1 | ||
147 | #define MPI_FATAL_EDUMP_TABLE_STAT_NF_SUCCESS_MORE_DATA 0x2 | ||
148 | #define MPI_FATAL_EDUMP_TABLE_STAT_NF_SUCCESS_DONE 0x3 | ||
149 | #define TYPE_GSM_SPACE 1 | ||
150 | #define TYPE_QUEUE 2 | ||
151 | #define TYPE_FATAL 3 | ||
152 | #define TYPE_NON_FATAL 4 | ||
153 | #define TYPE_INBOUND 1 | ||
154 | #define TYPE_OUTBOUND 2 | ||
155 | struct forensic_data { | ||
156 | u32 data_type; | ||
157 | union { | ||
158 | struct { | ||
159 | u32 direct_len; | ||
160 | u32 direct_offset; | ||
161 | void *direct_data; | ||
162 | } gsm_buf; | ||
163 | struct { | ||
164 | u16 queue_type; | ||
165 | u16 queue_index; | ||
166 | u32 direct_len; | ||
167 | void *direct_data; | ||
168 | } queue_buf; | ||
169 | struct { | ||
170 | u32 direct_len; | ||
171 | u32 direct_offset; | ||
172 | u32 read_len; | ||
173 | void *direct_data; | ||
174 | } data_buf; | ||
175 | }; | ||
176 | }; | ||
177 | |||
178 | /* bit31-26 - mask bar */ | ||
179 | #define SCRATCH_PAD0_BAR_MASK 0xFC000000 | ||
180 | /* bit25-0 - offset mask */ | ||
181 | #define SCRATCH_PAD0_OFFSET_MASK 0x03FFFFFF | ||
182 | /* if AAP error state */ | ||
183 | #define SCRATCH_PAD0_AAPERR_MASK 0xFFFFFFFF | ||
184 | /* Inbound doorbell bit7 */ | ||
185 | #define SPCv_MSGU_CFG_TABLE_NONFATAL_DUMP 0x80 | ||
186 | /* Inbound doorbell bit7 SPCV */ | ||
187 | #define SPCV_MSGU_CFG_TABLE_TRANSFER_DEBUG_INFO 0x80 | ||
188 | #define MAIN_MERRDCTO_MERRDCES 0xA0/* DWORD 0x28) */ | ||
189 | |||
132 | struct pm8001_dispatch { | 190 | struct pm8001_dispatch { |
133 | char *name; | 191 | char *name; |
134 | int (*chip_init)(struct pm8001_hba_info *pm8001_ha); | 192 | int (*chip_init)(struct pm8001_hba_info *pm8001_ha); |
@@ -343,6 +401,7 @@ union main_cfg_table { | |||
343 | u32 phy_attr_table_offset; | 401 | u32 phy_attr_table_offset; |
344 | u32 port_recovery_timer; | 402 | u32 port_recovery_timer; |
345 | u32 interrupt_reassertion_delay; | 403 | u32 interrupt_reassertion_delay; |
404 | u32 fatal_n_non_fatal_dump; /* 0x28 */ | ||
346 | } pm80xx_tbl; | 405 | } pm80xx_tbl; |
347 | }; | 406 | }; |
348 | 407 | ||
@@ -417,6 +476,13 @@ struct pm8001_hba_info { | |||
417 | struct pm8001_hba_memspace io_mem[6]; | 476 | struct pm8001_hba_memspace io_mem[6]; |
418 | struct mpi_mem_req memoryMap; | 477 | struct mpi_mem_req memoryMap; |
419 | struct encrypt encrypt_info; /* support encryption */ | 478 | struct encrypt encrypt_info; /* support encryption */ |
479 | struct forensic_data forensic_info; | ||
480 | u32 fatal_bar_loc; | ||
481 | u32 forensic_last_offset; | ||
482 | u32 fatal_forensic_shift_offset; | ||
483 | u32 forensic_fatal_step; | ||
484 | u32 evtlog_ib_offset; | ||
485 | u32 evtlog_ob_offset; | ||
420 | void __iomem *msg_unit_tbl_addr;/*Message Unit Table Addr*/ | 486 | void __iomem *msg_unit_tbl_addr;/*Message Unit Table Addr*/ |
421 | void __iomem *main_cfg_tbl_addr;/*Main Config Table Addr*/ | 487 | void __iomem *main_cfg_tbl_addr;/*Main Config Table Addr*/ |
422 | void __iomem *general_stat_tbl_addr;/*General Status Table Addr*/ | 488 | void __iomem *general_stat_tbl_addr;/*General Status Table Addr*/ |
@@ -425,6 +491,7 @@ struct pm8001_hba_info { | |||
425 | void __iomem *pspa_q_tbl_addr; | 491 | void __iomem *pspa_q_tbl_addr; |
426 | /*MPI SAS PHY attributes Queue Config Table Addr*/ | 492 | /*MPI SAS PHY attributes Queue Config Table Addr*/ |
427 | void __iomem *ivt_tbl_addr; /*MPI IVT Table Addr */ | 493 | void __iomem *ivt_tbl_addr; /*MPI IVT Table Addr */ |
494 | void __iomem *fatal_tbl_addr; /*MPI IVT Table Addr */ | ||
428 | union main_cfg_table main_cfg_tbl; | 495 | union main_cfg_table main_cfg_tbl; |
429 | union general_status_table gs_tbl; | 496 | union general_status_table gs_tbl; |
430 | struct inbound_queue_table inbnd_q_tbl[PM8001_MAX_SPCV_INB_NUM]; | 497 | struct inbound_queue_table inbnd_q_tbl[PM8001_MAX_SPCV_INB_NUM]; |
@@ -629,7 +696,12 @@ struct pm8001_device *pm8001_find_dev(struct pm8001_hba_info *pm8001_ha, | |||
629 | int pm80xx_set_thermal_config(struct pm8001_hba_info *pm8001_ha); | 696 | int pm80xx_set_thermal_config(struct pm8001_hba_info *pm8001_ha); |
630 | 697 | ||
631 | int pm8001_bar4_shift(struct pm8001_hba_info *pm8001_ha, u32 shiftValue); | 698 | int pm8001_bar4_shift(struct pm8001_hba_info *pm8001_ha, u32 shiftValue); |
632 | 699 | void pm8001_set_phy_profile(struct pm8001_hba_info *pm8001_ha, | |
700 | u32 length, u8 *buf); | ||
701 | int pm80xx_bar4_shift(struct pm8001_hba_info *pm8001_ha, u32 shiftValue); | ||
702 | ssize_t pm80xx_get_fatal_dump(struct device *cdev, | ||
703 | struct device_attribute *attr, char *buf); | ||
704 | ssize_t pm8001_get_gsm_dump(struct device *cdev, u32, char *buf); | ||
633 | /* ctl shared API */ | 705 | /* ctl shared API */ |
634 | extern struct device_attribute *pm8001_host_attrs[]; | 706 | extern struct device_attribute *pm8001_host_attrs[]; |
635 | 707 | ||
diff --git a/drivers/scsi/pm8001/pm80xx_hwi.c b/drivers/scsi/pm8001/pm80xx_hwi.c index 9f91030211e8..8987b1706216 100644 --- a/drivers/scsi/pm8001/pm80xx_hwi.c +++ b/drivers/scsi/pm8001/pm80xx_hwi.c | |||
@@ -45,6 +45,228 @@ | |||
45 | 45 | ||
46 | #define SMP_DIRECT 1 | 46 | #define SMP_DIRECT 1 |
47 | #define SMP_INDIRECT 2 | 47 | #define SMP_INDIRECT 2 |
48 | |||
49 | |||
50 | int pm80xx_bar4_shift(struct pm8001_hba_info *pm8001_ha, u32 shift_value) | ||
51 | { | ||
52 | u32 reg_val; | ||
53 | unsigned long start; | ||
54 | pm8001_cw32(pm8001_ha, 0, MEMBASE_II_SHIFT_REGISTER, shift_value); | ||
55 | /* confirm the setting is written */ | ||
56 | start = jiffies + HZ; /* 1 sec */ | ||
57 | do { | ||
58 | reg_val = pm8001_cr32(pm8001_ha, 0, MEMBASE_II_SHIFT_REGISTER); | ||
59 | } while ((reg_val != shift_value) && time_before(jiffies, start)); | ||
60 | if (reg_val != shift_value) { | ||
61 | PM8001_FAIL_DBG(pm8001_ha, | ||
62 | pm8001_printk("TIMEOUT:MEMBASE_II_SHIFT_REGISTER" | ||
63 | " = 0x%x\n", reg_val)); | ||
64 | return -1; | ||
65 | } | ||
66 | return 0; | ||
67 | } | ||
68 | |||
69 | void pm80xx_pci_mem_copy(struct pm8001_hba_info *pm8001_ha, u32 soffset, | ||
70 | const void *destination, | ||
71 | u32 dw_count, u32 bus_base_number) | ||
72 | { | ||
73 | u32 index, value, offset; | ||
74 | u32 *destination1; | ||
75 | destination1 = (u32 *)destination; | ||
76 | |||
77 | for (index = 0; index < dw_count; index += 4, destination1++) { | ||
78 | offset = (soffset + index / 4); | ||
79 | if (offset < (64 * 1024)) { | ||
80 | value = pm8001_cr32(pm8001_ha, bus_base_number, offset); | ||
81 | *destination1 = cpu_to_le32(value); | ||
82 | } | ||
83 | } | ||
84 | return; | ||
85 | } | ||
86 | |||
87 | ssize_t pm80xx_get_fatal_dump(struct device *cdev, | ||
88 | struct device_attribute *attr, char *buf) | ||
89 | { | ||
90 | struct Scsi_Host *shost = class_to_shost(cdev); | ||
91 | struct sas_ha_struct *sha = SHOST_TO_SAS_HA(shost); | ||
92 | struct pm8001_hba_info *pm8001_ha = sha->lldd_ha; | ||
93 | void __iomem *fatal_table_address = pm8001_ha->fatal_tbl_addr; | ||
94 | u32 status = 1; | ||
95 | u32 accum_len , reg_val, index, *temp; | ||
96 | unsigned long start; | ||
97 | u8 *direct_data; | ||
98 | char *fatal_error_data = buf; | ||
99 | |||
100 | pm8001_ha->forensic_info.data_buf.direct_data = buf; | ||
101 | if (pm8001_ha->chip_id == chip_8001) { | ||
102 | pm8001_ha->forensic_info.data_buf.direct_data += | ||
103 | sprintf(pm8001_ha->forensic_info.data_buf.direct_data, | ||
104 | "Not supported for SPC controller"); | ||
105 | return (char *)pm8001_ha->forensic_info.data_buf.direct_data - | ||
106 | (char *)buf; | ||
107 | } | ||
108 | if (pm8001_ha->forensic_info.data_buf.direct_offset == 0) { | ||
109 | PM8001_IO_DBG(pm8001_ha, | ||
110 | pm8001_printk("forensic_info TYPE_NON_FATAL..............\n")); | ||
111 | direct_data = (u8 *)fatal_error_data; | ||
112 | pm8001_ha->forensic_info.data_type = TYPE_NON_FATAL; | ||
113 | pm8001_ha->forensic_info.data_buf.direct_len = SYSFS_OFFSET; | ||
114 | pm8001_ha->forensic_info.data_buf.direct_offset = 0; | ||
115 | pm8001_ha->forensic_info.data_buf.read_len = 0; | ||
116 | |||
117 | pm8001_ha->forensic_info.data_buf.direct_data = direct_data; | ||
118 | } | ||
119 | |||
120 | if (pm8001_ha->forensic_info.data_buf.direct_offset == 0) { | ||
121 | /* start to get data */ | ||
122 | /* Program the MEMBASE II Shifting Register with 0x00.*/ | ||
123 | pm8001_cw32(pm8001_ha, 0, MEMBASE_II_SHIFT_REGISTER, | ||
124 | pm8001_ha->fatal_forensic_shift_offset); | ||
125 | pm8001_ha->forensic_last_offset = 0; | ||
126 | pm8001_ha->forensic_fatal_step = 0; | ||
127 | pm8001_ha->fatal_bar_loc = 0; | ||
128 | } | ||
129 | /* Read until accum_len is retrived */ | ||
130 | accum_len = pm8001_mr32(fatal_table_address, | ||
131 | MPI_FATAL_EDUMP_TABLE_ACCUM_LEN); | ||
132 | PM8001_IO_DBG(pm8001_ha, pm8001_printk("accum_len 0x%x\n", | ||
133 | accum_len)); | ||
134 | if (accum_len == 0xFFFFFFFF) { | ||
135 | PM8001_IO_DBG(pm8001_ha, | ||
136 | pm8001_printk("Possible PCI issue 0x%x not expected\n", | ||
137 | accum_len)); | ||
138 | return status; | ||
139 | } | ||
140 | if (accum_len == 0 || accum_len >= 0x100000) { | ||
141 | pm8001_ha->forensic_info.data_buf.direct_data += | ||
142 | sprintf(pm8001_ha->forensic_info.data_buf.direct_data, | ||
143 | "%08x ", 0xFFFFFFFF); | ||
144 | return (char *)pm8001_ha->forensic_info.data_buf.direct_data - | ||
145 | (char *)buf; | ||
146 | } | ||
147 | temp = (u32 *)pm8001_ha->memoryMap.region[FORENSIC_MEM].virt_ptr; | ||
148 | if (pm8001_ha->forensic_fatal_step == 0) { | ||
149 | moreData: | ||
150 | if (pm8001_ha->forensic_info.data_buf.direct_data) { | ||
151 | /* Data is in bar, copy to host memory */ | ||
152 | pm80xx_pci_mem_copy(pm8001_ha, pm8001_ha->fatal_bar_loc, | ||
153 | pm8001_ha->memoryMap.region[FORENSIC_MEM].virt_ptr, | ||
154 | pm8001_ha->forensic_info.data_buf.direct_len , | ||
155 | 1); | ||
156 | } | ||
157 | pm8001_ha->fatal_bar_loc += | ||
158 | pm8001_ha->forensic_info.data_buf.direct_len; | ||
159 | pm8001_ha->forensic_info.data_buf.direct_offset += | ||
160 | pm8001_ha->forensic_info.data_buf.direct_len; | ||
161 | pm8001_ha->forensic_last_offset += | ||
162 | pm8001_ha->forensic_info.data_buf.direct_len; | ||
163 | pm8001_ha->forensic_info.data_buf.read_len = | ||
164 | pm8001_ha->forensic_info.data_buf.direct_len; | ||
165 | |||
166 | if (pm8001_ha->forensic_last_offset >= accum_len) { | ||
167 | pm8001_ha->forensic_info.data_buf.direct_data += | ||
168 | sprintf(pm8001_ha->forensic_info.data_buf.direct_data, | ||
169 | "%08x ", 3); | ||
170 | for (index = 0; index < (SYSFS_OFFSET / 4); index++) { | ||
171 | pm8001_ha->forensic_info.data_buf.direct_data += | ||
172 | sprintf(pm8001_ha-> | ||
173 | forensic_info.data_buf.direct_data, | ||
174 | "%08x ", *(temp + index)); | ||
175 | } | ||
176 | |||
177 | pm8001_ha->fatal_bar_loc = 0; | ||
178 | pm8001_ha->forensic_fatal_step = 1; | ||
179 | pm8001_ha->fatal_forensic_shift_offset = 0; | ||
180 | pm8001_ha->forensic_last_offset = 0; | ||
181 | status = 0; | ||
182 | return (char *)pm8001_ha-> | ||
183 | forensic_info.data_buf.direct_data - | ||
184 | (char *)buf; | ||
185 | } | ||
186 | if (pm8001_ha->fatal_bar_loc < (64 * 1024)) { | ||
187 | pm8001_ha->forensic_info.data_buf.direct_data += | ||
188 | sprintf(pm8001_ha-> | ||
189 | forensic_info.data_buf.direct_data, | ||
190 | "%08x ", 2); | ||
191 | for (index = 0; index < (SYSFS_OFFSET / 4); index++) { | ||
192 | pm8001_ha->forensic_info.data_buf.direct_data += | ||
193 | sprintf(pm8001_ha-> | ||
194 | forensic_info.data_buf.direct_data, | ||
195 | "%08x ", *(temp + index)); | ||
196 | } | ||
197 | status = 0; | ||
198 | return (char *)pm8001_ha-> | ||
199 | forensic_info.data_buf.direct_data - | ||
200 | (char *)buf; | ||
201 | } | ||
202 | |||
203 | /* Increment the MEMBASE II Shifting Register value by 0x100.*/ | ||
204 | pm8001_ha->forensic_info.data_buf.direct_data += | ||
205 | sprintf(pm8001_ha->forensic_info.data_buf.direct_data, | ||
206 | "%08x ", 2); | ||
207 | for (index = 0; index < 256; index++) { | ||
208 | pm8001_ha->forensic_info.data_buf.direct_data += | ||
209 | sprintf(pm8001_ha-> | ||
210 | forensic_info.data_buf.direct_data, | ||
211 | "%08x ", *(temp + index)); | ||
212 | } | ||
213 | pm8001_ha->fatal_forensic_shift_offset += 0x100; | ||
214 | pm8001_cw32(pm8001_ha, 0, MEMBASE_II_SHIFT_REGISTER, | ||
215 | pm8001_ha->fatal_forensic_shift_offset); | ||
216 | pm8001_ha->fatal_bar_loc = 0; | ||
217 | status = 0; | ||
218 | return (char *)pm8001_ha->forensic_info.data_buf.direct_data - | ||
219 | (char *)buf; | ||
220 | } | ||
221 | if (pm8001_ha->forensic_fatal_step == 1) { | ||
222 | pm8001_ha->fatal_forensic_shift_offset = 0; | ||
223 | /* Read 64K of the debug data. */ | ||
224 | pm8001_cw32(pm8001_ha, 0, MEMBASE_II_SHIFT_REGISTER, | ||
225 | pm8001_ha->fatal_forensic_shift_offset); | ||
226 | pm8001_mw32(fatal_table_address, | ||
227 | MPI_FATAL_EDUMP_TABLE_HANDSHAKE, | ||
228 | MPI_FATAL_EDUMP_HANDSHAKE_RDY); | ||
229 | |||
230 | /* Poll FDDHSHK until clear */ | ||
231 | start = jiffies + (2 * HZ); /* 2 sec */ | ||
232 | |||
233 | do { | ||
234 | reg_val = pm8001_mr32(fatal_table_address, | ||
235 | MPI_FATAL_EDUMP_TABLE_HANDSHAKE); | ||
236 | } while ((reg_val) && time_before(jiffies, start)); | ||
237 | |||
238 | if (reg_val != 0) { | ||
239 | PM8001_FAIL_DBG(pm8001_ha, | ||
240 | pm8001_printk("TIMEOUT:MEMBASE_II_SHIFT_REGISTER" | ||
241 | " = 0x%x\n", reg_val)); | ||
242 | return -1; | ||
243 | } | ||
244 | |||
245 | /* Read the next 64K of the debug data. */ | ||
246 | pm8001_ha->forensic_fatal_step = 0; | ||
247 | if (pm8001_mr32(fatal_table_address, | ||
248 | MPI_FATAL_EDUMP_TABLE_STATUS) != | ||
249 | MPI_FATAL_EDUMP_TABLE_STAT_NF_SUCCESS_DONE) { | ||
250 | pm8001_mw32(fatal_table_address, | ||
251 | MPI_FATAL_EDUMP_TABLE_HANDSHAKE, 0); | ||
252 | goto moreData; | ||
253 | } else { | ||
254 | pm8001_ha->forensic_info.data_buf.direct_data += | ||
255 | sprintf(pm8001_ha-> | ||
256 | forensic_info.data_buf.direct_data, | ||
257 | "%08x ", 4); | ||
258 | pm8001_ha->forensic_info.data_buf.read_len = 0xFFFFFFFF; | ||
259 | pm8001_ha->forensic_info.data_buf.direct_len = 0; | ||
260 | pm8001_ha->forensic_info.data_buf.direct_offset = 0; | ||
261 | pm8001_ha->forensic_info.data_buf.read_len = 0; | ||
262 | status = 0; | ||
263 | } | ||
264 | } | ||
265 | |||
266 | return (char *)pm8001_ha->forensic_info.data_buf.direct_data - | ||
267 | (char *)buf; | ||
268 | } | ||
269 | |||
48 | /** | 270 | /** |
49 | * read_main_config_table - read the configure table and save it. | 271 | * read_main_config_table - read the configure table and save it. |
50 | * @pm8001_ha: our hba card information | 272 | * @pm8001_ha: our hba card information |
@@ -430,7 +652,11 @@ static int mpi_init_check(struct pm8001_hba_info *pm8001_ha) | |||
430 | table is updated */ | 652 | table is updated */ |
431 | pm8001_cw32(pm8001_ha, 0, MSGU_IBDB_SET, SPCv_MSGU_CFG_TABLE_UPDATE); | 653 | pm8001_cw32(pm8001_ha, 0, MSGU_IBDB_SET, SPCv_MSGU_CFG_TABLE_UPDATE); |
432 | /* wait until Inbound DoorBell Clear Register toggled */ | 654 | /* wait until Inbound DoorBell Clear Register toggled */ |
433 | max_wait_count = 2 * 1000 * 1000;/* 2 sec for spcv/ve */ | 655 | if (IS_SPCV_12G(pm8001_ha->pdev)) { |
656 | max_wait_count = 4 * 1000 * 1000;/* 4 sec */ | ||
657 | } else { | ||
658 | max_wait_count = 2 * 1000 * 1000;/* 2 sec */ | ||
659 | } | ||
434 | do { | 660 | do { |
435 | udelay(1); | 661 | udelay(1); |
436 | value = pm8001_cr32(pm8001_ha, 0, MSGU_IBDB_SET); | 662 | value = pm8001_cr32(pm8001_ha, 0, MSGU_IBDB_SET); |
@@ -579,6 +805,9 @@ static void init_pci_device_addresses(struct pm8001_hba_info *pm8001_ha) | |||
579 | pm8001_ha->pspa_q_tbl_addr = | 805 | pm8001_ha->pspa_q_tbl_addr = |
580 | base_addr + (pm8001_cr32(pm8001_ha, pcibar, offset + 0x90) & | 806 | base_addr + (pm8001_cr32(pm8001_ha, pcibar, offset + 0x90) & |
581 | 0xFFFFFF); | 807 | 0xFFFFFF); |
808 | pm8001_ha->fatal_tbl_addr = | ||
809 | base_addr + (pm8001_cr32(pm8001_ha, pcibar, offset + 0xA0) & | ||
810 | 0xFFFFFF); | ||
582 | 811 | ||
583 | PM8001_INIT_DBG(pm8001_ha, | 812 | PM8001_INIT_DBG(pm8001_ha, |
584 | pm8001_printk("GST OFFSET 0x%x\n", | 813 | pm8001_printk("GST OFFSET 0x%x\n", |
@@ -913,7 +1142,11 @@ static int mpi_uninit_check(struct pm8001_hba_info *pm8001_ha) | |||
913 | pm8001_cw32(pm8001_ha, 0, MSGU_IBDB_SET, SPCv_MSGU_CFG_TABLE_RESET); | 1142 | pm8001_cw32(pm8001_ha, 0, MSGU_IBDB_SET, SPCv_MSGU_CFG_TABLE_RESET); |
914 | 1143 | ||
915 | /* wait until Inbound DoorBell Clear Register toggled */ | 1144 | /* wait until Inbound DoorBell Clear Register toggled */ |
916 | max_wait_count = 2 * 1000 * 1000; /* 2 sec for spcv/ve */ | 1145 | if (IS_SPCV_12G(pm8001_ha->pdev)) { |
1146 | max_wait_count = 4 * 1000 * 1000;/* 4 sec */ | ||
1147 | } else { | ||
1148 | max_wait_count = 2 * 1000 * 1000;/* 2 sec */ | ||
1149 | } | ||
917 | do { | 1150 | do { |
918 | udelay(1); | 1151 | udelay(1); |
919 | value = pm8001_cr32(pm8001_ha, 0, MSGU_IBDB_SET); | 1152 | value = pm8001_cr32(pm8001_ha, 0, MSGU_IBDB_SET); |
@@ -959,6 +1192,7 @@ pm80xx_chip_soft_rst(struct pm8001_hba_info *pm8001_ha) | |||
959 | { | 1192 | { |
960 | u32 regval; | 1193 | u32 regval; |
961 | u32 bootloader_state; | 1194 | u32 bootloader_state; |
1195 | u32 ibutton0, ibutton1; | ||
962 | 1196 | ||
963 | /* Check if MPI is in ready state to reset */ | 1197 | /* Check if MPI is in ready state to reset */ |
964 | if (mpi_uninit_check(pm8001_ha) != 0) { | 1198 | if (mpi_uninit_check(pm8001_ha) != 0) { |
@@ -1017,7 +1251,27 @@ pm80xx_chip_soft_rst(struct pm8001_hba_info *pm8001_ha) | |||
1017 | if (-1 == check_fw_ready(pm8001_ha)) { | 1251 | if (-1 == check_fw_ready(pm8001_ha)) { |
1018 | PM8001_FAIL_DBG(pm8001_ha, | 1252 | PM8001_FAIL_DBG(pm8001_ha, |
1019 | pm8001_printk("Firmware is not ready!\n")); | 1253 | pm8001_printk("Firmware is not ready!\n")); |
1020 | return -EBUSY; | 1254 | /* check iButton feature support for motherboard controller */ |
1255 | if (pm8001_ha->pdev->subsystem_vendor != | ||
1256 | PCI_VENDOR_ID_ADAPTEC2 && | ||
1257 | pm8001_ha->pdev->subsystem_vendor != 0) { | ||
1258 | ibutton0 = pm8001_cr32(pm8001_ha, 0, | ||
1259 | MSGU_HOST_SCRATCH_PAD_6); | ||
1260 | ibutton1 = pm8001_cr32(pm8001_ha, 0, | ||
1261 | MSGU_HOST_SCRATCH_PAD_7); | ||
1262 | if (!ibutton0 && !ibutton1) { | ||
1263 | PM8001_FAIL_DBG(pm8001_ha, | ||
1264 | pm8001_printk("iButton Feature is" | ||
1265 | " not Available!!!\n")); | ||
1266 | return -EBUSY; | ||
1267 | } | ||
1268 | if (ibutton0 == 0xdeadbeef && ibutton1 == 0xdeadbeef) { | ||
1269 | PM8001_FAIL_DBG(pm8001_ha, | ||
1270 | pm8001_printk("CRC Check for iButton" | ||
1271 | " Feature Failed!!!\n")); | ||
1272 | return -EBUSY; | ||
1273 | } | ||
1274 | } | ||
1021 | } | 1275 | } |
1022 | PM8001_INIT_DBG(pm8001_ha, | 1276 | PM8001_INIT_DBG(pm8001_ha, |
1023 | pm8001_printk("SPCv soft reset Complete\n")); | 1277 | pm8001_printk("SPCv soft reset Complete\n")); |
@@ -1268,6 +1522,13 @@ mpi_ssp_completion(struct pm8001_hba_info *pm8001_ha , void *piomb) | |||
1268 | if (unlikely(!t || !t->lldd_task || !t->dev)) | 1522 | if (unlikely(!t || !t->lldd_task || !t->dev)) |
1269 | return; | 1523 | return; |
1270 | ts = &t->task_status; | 1524 | ts = &t->task_status; |
1525 | /* Print sas address of IO failed device */ | ||
1526 | if ((status != IO_SUCCESS) && (status != IO_OVERFLOW) && | ||
1527 | (status != IO_UNDERFLOW)) | ||
1528 | PM8001_FAIL_DBG(pm8001_ha, | ||
1529 | pm8001_printk("SAS Address of IO Failure Drive" | ||
1530 | ":%016llx", SAS_ADDR(t->dev->sas_addr))); | ||
1531 | |||
1271 | switch (status) { | 1532 | switch (status) { |
1272 | case IO_SUCCESS: | 1533 | case IO_SUCCESS: |
1273 | PM8001_IO_DBG(pm8001_ha, | 1534 | PM8001_IO_DBG(pm8001_ha, |
@@ -1691,6 +1952,10 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, void *piomb) | |||
1691 | u32 param; | 1952 | u32 param; |
1692 | u32 status; | 1953 | u32 status; |
1693 | u32 tag; | 1954 | u32 tag; |
1955 | int i, j; | ||
1956 | u8 sata_addr_low[4]; | ||
1957 | u32 temp_sata_addr_low, temp_sata_addr_hi; | ||
1958 | u8 sata_addr_hi[4]; | ||
1694 | struct sata_completion_resp *psataPayload; | 1959 | struct sata_completion_resp *psataPayload; |
1695 | struct task_status_struct *ts; | 1960 | struct task_status_struct *ts; |
1696 | struct ata_task_resp *resp ; | 1961 | struct ata_task_resp *resp ; |
@@ -1740,7 +2005,47 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, void *piomb) | |||
1740 | pm8001_printk("ts null\n")); | 2005 | pm8001_printk("ts null\n")); |
1741 | return; | 2006 | return; |
1742 | } | 2007 | } |
2008 | /* Print sas address of IO failed device */ | ||
2009 | if ((status != IO_SUCCESS) && (status != IO_OVERFLOW) && | ||
2010 | (status != IO_UNDERFLOW)) { | ||
2011 | if (!((t->dev->parent) && | ||
2012 | (DEV_IS_EXPANDER(t->dev->parent->dev_type)))) { | ||
2013 | for (i = 0 , j = 4; i <= 3 && j <= 7; i++ , j++) | ||
2014 | sata_addr_low[i] = pm8001_ha->sas_addr[j]; | ||
2015 | for (i = 0 , j = 0; i <= 3 && j <= 3; i++ , j++) | ||
2016 | sata_addr_hi[i] = pm8001_ha->sas_addr[j]; | ||
2017 | memcpy(&temp_sata_addr_low, sata_addr_low, | ||
2018 | sizeof(sata_addr_low)); | ||
2019 | memcpy(&temp_sata_addr_hi, sata_addr_hi, | ||
2020 | sizeof(sata_addr_hi)); | ||
2021 | temp_sata_addr_hi = (((temp_sata_addr_hi >> 24) & 0xff) | ||
2022 | |((temp_sata_addr_hi << 8) & | ||
2023 | 0xff0000) | | ||
2024 | ((temp_sata_addr_hi >> 8) | ||
2025 | & 0xff00) | | ||
2026 | ((temp_sata_addr_hi << 24) & | ||
2027 | 0xff000000)); | ||
2028 | temp_sata_addr_low = ((((temp_sata_addr_low >> 24) | ||
2029 | & 0xff) | | ||
2030 | ((temp_sata_addr_low << 8) | ||
2031 | & 0xff0000) | | ||
2032 | ((temp_sata_addr_low >> 8) | ||
2033 | & 0xff00) | | ||
2034 | ((temp_sata_addr_low << 24) | ||
2035 | & 0xff000000)) + | ||
2036 | pm8001_dev->attached_phy + | ||
2037 | 0x10); | ||
2038 | PM8001_FAIL_DBG(pm8001_ha, | ||
2039 | pm8001_printk("SAS Address of IO Failure Drive:" | ||
2040 | "%08x%08x", temp_sata_addr_hi, | ||
2041 | temp_sata_addr_low)); | ||
1743 | 2042 | ||
2043 | } else { | ||
2044 | PM8001_FAIL_DBG(pm8001_ha, | ||
2045 | pm8001_printk("SAS Address of IO Failure Drive:" | ||
2046 | "%016llx", SAS_ADDR(t->dev->sas_addr))); | ||
2047 | } | ||
2048 | } | ||
1744 | switch (status) { | 2049 | switch (status) { |
1745 | case IO_SUCCESS: | 2050 | case IO_SUCCESS: |
1746 | PM8001_IO_DBG(pm8001_ha, pm8001_printk("IO_SUCCESS\n")); | 2051 | PM8001_IO_DBG(pm8001_ha, pm8001_printk("IO_SUCCESS\n")); |
@@ -3103,9 +3408,27 @@ static int mpi_flash_op_ext_resp(struct pm8001_hba_info *pm8001_ha, void *piomb) | |||
3103 | static int mpi_set_phy_profile_resp(struct pm8001_hba_info *pm8001_ha, | 3408 | static int mpi_set_phy_profile_resp(struct pm8001_hba_info *pm8001_ha, |
3104 | void *piomb) | 3409 | void *piomb) |
3105 | { | 3410 | { |
3106 | PM8001_MSG_DBG(pm8001_ha, | 3411 | u8 page_code; |
3107 | pm8001_printk(" pm80xx_addition_functionality\n")); | 3412 | struct set_phy_profile_resp *pPayload = |
3413 | (struct set_phy_profile_resp *)(piomb + 4); | ||
3414 | u32 ppc_phyid = le32_to_cpu(pPayload->ppc_phyid); | ||
3415 | u32 status = le32_to_cpu(pPayload->status); | ||
3108 | 3416 | ||
3417 | page_code = (u8)((ppc_phyid & 0xFF00) >> 8); | ||
3418 | if (status) { | ||
3419 | /* status is FAILED */ | ||
3420 | PM8001_FAIL_DBG(pm8001_ha, | ||
3421 | pm8001_printk("PhyProfile command failed with status " | ||
3422 | "0x%08X \n", status)); | ||
3423 | return -1; | ||
3424 | } else { | ||
3425 | if (page_code != SAS_PHY_ANALOG_SETTINGS_PAGE) { | ||
3426 | PM8001_FAIL_DBG(pm8001_ha, | ||
3427 | pm8001_printk("Invalid page code 0x%X\n", | ||
3428 | page_code)); | ||
3429 | return -1; | ||
3430 | } | ||
3431 | } | ||
3109 | return 0; | 3432 | return 0; |
3110 | } | 3433 | } |
3111 | 3434 | ||
@@ -3484,8 +3807,6 @@ static int pm80xx_chip_smp_req(struct pm8001_hba_info *pm8001_ha, | |||
3484 | else | 3807 | else |
3485 | pm8001_ha->smp_exp_mode = SMP_INDIRECT; | 3808 | pm8001_ha->smp_exp_mode = SMP_INDIRECT; |
3486 | 3809 | ||
3487 | /* DIRECT MODE support only in spcv/ve */ | ||
3488 | pm8001_ha->smp_exp_mode = SMP_DIRECT; | ||
3489 | 3810 | ||
3490 | tmp_addr = cpu_to_le64((u64)sg_dma_address(&task->smp_task.smp_req)); | 3811 | tmp_addr = cpu_to_le64((u64)sg_dma_address(&task->smp_task.smp_req)); |
3491 | preq_dma_addr = (char *)phys_to_virt(tmp_addr); | 3812 | preq_dma_addr = (char *)phys_to_virt(tmp_addr); |
@@ -3501,7 +3822,7 @@ static int pm80xx_chip_smp_req(struct pm8001_hba_info *pm8001_ha, | |||
3501 | /* exclude top 4 bytes for SMP req header */ | 3822 | /* exclude top 4 bytes for SMP req header */ |
3502 | smp_cmd.long_smp_req.long_req_addr = | 3823 | smp_cmd.long_smp_req.long_req_addr = |
3503 | cpu_to_le64((u64)sg_dma_address | 3824 | cpu_to_le64((u64)sg_dma_address |
3504 | (&task->smp_task.smp_req) - 4); | 3825 | (&task->smp_task.smp_req) + 4); |
3505 | /* exclude 4 bytes for SMP req header and CRC */ | 3826 | /* exclude 4 bytes for SMP req header and CRC */ |
3506 | smp_cmd.long_smp_req.long_req_size = | 3827 | smp_cmd.long_smp_req.long_req_size = |
3507 | cpu_to_le32((u32)sg_dma_len(&task->smp_task.smp_req)-8); | 3828 | cpu_to_le32((u32)sg_dma_len(&task->smp_task.smp_req)-8); |
@@ -3604,10 +3925,10 @@ static int pm80xx_chip_ssp_io_req(struct pm8001_hba_info *pm8001_ha, | |||
3604 | struct ssp_ini_io_start_req ssp_cmd; | 3925 | struct ssp_ini_io_start_req ssp_cmd; |
3605 | u32 tag = ccb->ccb_tag; | 3926 | u32 tag = ccb->ccb_tag; |
3606 | int ret; | 3927 | int ret; |
3607 | u64 phys_addr; | 3928 | u64 phys_addr, start_addr, end_addr; |
3929 | u32 end_addr_high, end_addr_low; | ||
3608 | struct inbound_queue_table *circularQ; | 3930 | struct inbound_queue_table *circularQ; |
3609 | static u32 inb; | 3931 | u32 q_index; |
3610 | static u32 outb; | ||
3611 | u32 opc = OPC_INB_SSPINIIOSTART; | 3932 | u32 opc = OPC_INB_SSPINIIOSTART; |
3612 | memset(&ssp_cmd, 0, sizeof(ssp_cmd)); | 3933 | memset(&ssp_cmd, 0, sizeof(ssp_cmd)); |
3613 | memcpy(ssp_cmd.ssp_iu.lun, task->ssp_task.LUN, 8); | 3934 | memcpy(ssp_cmd.ssp_iu.lun, task->ssp_task.LUN, 8); |
@@ -3626,7 +3947,8 @@ static int pm80xx_chip_ssp_io_req(struct pm8001_hba_info *pm8001_ha, | |||
3626 | ssp_cmd.ssp_iu.efb_prio_attr |= (task->ssp_task.task_attr & 7); | 3947 | ssp_cmd.ssp_iu.efb_prio_attr |= (task->ssp_task.task_attr & 7); |
3627 | memcpy(ssp_cmd.ssp_iu.cdb, task->ssp_task.cmd->cmnd, | 3948 | memcpy(ssp_cmd.ssp_iu.cdb, task->ssp_task.cmd->cmnd, |
3628 | task->ssp_task.cmd->cmd_len); | 3949 | task->ssp_task.cmd->cmd_len); |
3629 | circularQ = &pm8001_ha->inbnd_q_tbl[0]; | 3950 | q_index = (u32) (pm8001_dev->id & 0x00ffffff) % PM8001_MAX_INB_NUM; |
3951 | circularQ = &pm8001_ha->inbnd_q_tbl[q_index]; | ||
3630 | 3952 | ||
3631 | /* Check if encryption is set */ | 3953 | /* Check if encryption is set */ |
3632 | if (pm8001_ha->chip->encrypt && | 3954 | if (pm8001_ha->chip->encrypt && |
@@ -3658,6 +3980,30 @@ static int pm80xx_chip_ssp_io_req(struct pm8001_hba_info *pm8001_ha, | |||
3658 | cpu_to_le32(upper_32_bits(dma_addr)); | 3980 | cpu_to_le32(upper_32_bits(dma_addr)); |
3659 | ssp_cmd.enc_len = cpu_to_le32(task->total_xfer_len); | 3981 | ssp_cmd.enc_len = cpu_to_le32(task->total_xfer_len); |
3660 | ssp_cmd.enc_esgl = 0; | 3982 | ssp_cmd.enc_esgl = 0; |
3983 | /* Check 4G Boundary */ | ||
3984 | start_addr = cpu_to_le64(dma_addr); | ||
3985 | end_addr = (start_addr + ssp_cmd.enc_len) - 1; | ||
3986 | end_addr_low = cpu_to_le32(lower_32_bits(end_addr)); | ||
3987 | end_addr_high = cpu_to_le32(upper_32_bits(end_addr)); | ||
3988 | if (end_addr_high != ssp_cmd.enc_addr_high) { | ||
3989 | PM8001_FAIL_DBG(pm8001_ha, | ||
3990 | pm8001_printk("The sg list address " | ||
3991 | "start_addr=0x%016llx data_len=0x%x " | ||
3992 | "end_addr_high=0x%08x end_addr_low=" | ||
3993 | "0x%08x has crossed 4G boundary\n", | ||
3994 | start_addr, ssp_cmd.enc_len, | ||
3995 | end_addr_high, end_addr_low)); | ||
3996 | pm8001_chip_make_sg(task->scatter, 1, | ||
3997 | ccb->buf_prd); | ||
3998 | phys_addr = ccb->ccb_dma_handle + | ||
3999 | offsetof(struct pm8001_ccb_info, | ||
4000 | buf_prd[0]); | ||
4001 | ssp_cmd.enc_addr_low = | ||
4002 | cpu_to_le32(lower_32_bits(phys_addr)); | ||
4003 | ssp_cmd.enc_addr_high = | ||
4004 | cpu_to_le32(upper_32_bits(phys_addr)); | ||
4005 | ssp_cmd.enc_esgl = cpu_to_le32(1<<31); | ||
4006 | } | ||
3661 | } else if (task->num_scatter == 0) { | 4007 | } else if (task->num_scatter == 0) { |
3662 | ssp_cmd.enc_addr_low = 0; | 4008 | ssp_cmd.enc_addr_low = 0; |
3663 | ssp_cmd.enc_addr_high = 0; | 4009 | ssp_cmd.enc_addr_high = 0; |
@@ -3674,7 +4020,7 @@ static int pm80xx_chip_ssp_io_req(struct pm8001_hba_info *pm8001_ha, | |||
3674 | } else { | 4020 | } else { |
3675 | PM8001_IO_DBG(pm8001_ha, pm8001_printk( | 4021 | PM8001_IO_DBG(pm8001_ha, pm8001_printk( |
3676 | "Sending Normal SAS command 0x%x inb q %x\n", | 4022 | "Sending Normal SAS command 0x%x inb q %x\n", |
3677 | task->ssp_task.cmd->cmnd[0], inb)); | 4023 | task->ssp_task.cmd->cmnd[0], q_index)); |
3678 | /* fill in PRD (scatter/gather) table, if any */ | 4024 | /* fill in PRD (scatter/gather) table, if any */ |
3679 | if (task->num_scatter > 1) { | 4025 | if (task->num_scatter > 1) { |
3680 | pm8001_chip_make_sg(task->scatter, ccb->n_elem, | 4026 | pm8001_chip_make_sg(task->scatter, ccb->n_elem, |
@@ -3693,6 +4039,30 @@ static int pm80xx_chip_ssp_io_req(struct pm8001_hba_info *pm8001_ha, | |||
3693 | cpu_to_le32(upper_32_bits(dma_addr)); | 4039 | cpu_to_le32(upper_32_bits(dma_addr)); |
3694 | ssp_cmd.len = cpu_to_le32(task->total_xfer_len); | 4040 | ssp_cmd.len = cpu_to_le32(task->total_xfer_len); |
3695 | ssp_cmd.esgl = 0; | 4041 | ssp_cmd.esgl = 0; |
4042 | /* Check 4G Boundary */ | ||
4043 | start_addr = cpu_to_le64(dma_addr); | ||
4044 | end_addr = (start_addr + ssp_cmd.len) - 1; | ||
4045 | end_addr_low = cpu_to_le32(lower_32_bits(end_addr)); | ||
4046 | end_addr_high = cpu_to_le32(upper_32_bits(end_addr)); | ||
4047 | if (end_addr_high != ssp_cmd.addr_high) { | ||
4048 | PM8001_FAIL_DBG(pm8001_ha, | ||
4049 | pm8001_printk("The sg list address " | ||
4050 | "start_addr=0x%016llx data_len=0x%x " | ||
4051 | "end_addr_high=0x%08x end_addr_low=" | ||
4052 | "0x%08x has crossed 4G boundary\n", | ||
4053 | start_addr, ssp_cmd.len, | ||
4054 | end_addr_high, end_addr_low)); | ||
4055 | pm8001_chip_make_sg(task->scatter, 1, | ||
4056 | ccb->buf_prd); | ||
4057 | phys_addr = ccb->ccb_dma_handle + | ||
4058 | offsetof(struct pm8001_ccb_info, | ||
4059 | buf_prd[0]); | ||
4060 | ssp_cmd.addr_low = | ||
4061 | cpu_to_le32(lower_32_bits(phys_addr)); | ||
4062 | ssp_cmd.addr_high = | ||
4063 | cpu_to_le32(upper_32_bits(phys_addr)); | ||
4064 | ssp_cmd.esgl = cpu_to_le32(1<<31); | ||
4065 | } | ||
3696 | } else if (task->num_scatter == 0) { | 4066 | } else if (task->num_scatter == 0) { |
3697 | ssp_cmd.addr_low = 0; | 4067 | ssp_cmd.addr_low = 0; |
3698 | ssp_cmd.addr_high = 0; | 4068 | ssp_cmd.addr_high = 0; |
@@ -3700,11 +4070,9 @@ static int pm80xx_chip_ssp_io_req(struct pm8001_hba_info *pm8001_ha, | |||
3700 | ssp_cmd.esgl = 0; | 4070 | ssp_cmd.esgl = 0; |
3701 | } | 4071 | } |
3702 | } | 4072 | } |
3703 | ret = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &ssp_cmd, outb++); | 4073 | q_index = (u32) (pm8001_dev->id & 0x00ffffff) % PM8001_MAX_OUTB_NUM; |
3704 | 4074 | ret = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, | |
3705 | /* rotate the outb queue */ | 4075 | &ssp_cmd, q_index); |
3706 | outb = outb%PM8001_MAX_SPCV_OUTB_NUM; | ||
3707 | |||
3708 | return ret; | 4076 | return ret; |
3709 | } | 4077 | } |
3710 | 4078 | ||
@@ -3716,18 +4084,19 @@ static int pm80xx_chip_sata_req(struct pm8001_hba_info *pm8001_ha, | |||
3716 | struct pm8001_device *pm8001_ha_dev = dev->lldd_dev; | 4084 | struct pm8001_device *pm8001_ha_dev = dev->lldd_dev; |
3717 | u32 tag = ccb->ccb_tag; | 4085 | u32 tag = ccb->ccb_tag; |
3718 | int ret; | 4086 | int ret; |
3719 | static u32 inb; | 4087 | u32 q_index; |
3720 | static u32 outb; | ||
3721 | struct sata_start_req sata_cmd; | 4088 | struct sata_start_req sata_cmd; |
3722 | u32 hdr_tag, ncg_tag = 0; | 4089 | u32 hdr_tag, ncg_tag = 0; |
3723 | u64 phys_addr; | 4090 | u64 phys_addr, start_addr, end_addr; |
4091 | u32 end_addr_high, end_addr_low; | ||
3724 | u32 ATAP = 0x0; | 4092 | u32 ATAP = 0x0; |
3725 | u32 dir; | 4093 | u32 dir; |
3726 | struct inbound_queue_table *circularQ; | 4094 | struct inbound_queue_table *circularQ; |
3727 | unsigned long flags; | 4095 | unsigned long flags; |
3728 | u32 opc = OPC_INB_SATA_HOST_OPSTART; | 4096 | u32 opc = OPC_INB_SATA_HOST_OPSTART; |
3729 | memset(&sata_cmd, 0, sizeof(sata_cmd)); | 4097 | memset(&sata_cmd, 0, sizeof(sata_cmd)); |
3730 | circularQ = &pm8001_ha->inbnd_q_tbl[0]; | 4098 | q_index = (u32) (pm8001_ha_dev->id & 0x00ffffff) % PM8001_MAX_INB_NUM; |
4099 | circularQ = &pm8001_ha->inbnd_q_tbl[q_index]; | ||
3731 | 4100 | ||
3732 | if (task->data_dir == PCI_DMA_NONE) { | 4101 | if (task->data_dir == PCI_DMA_NONE) { |
3733 | ATAP = 0x04; /* no data*/ | 4102 | ATAP = 0x04; /* no data*/ |
@@ -3788,6 +4157,31 @@ static int pm80xx_chip_sata_req(struct pm8001_hba_info *pm8001_ha, | |||
3788 | sata_cmd.enc_addr_high = upper_32_bits(dma_addr); | 4157 | sata_cmd.enc_addr_high = upper_32_bits(dma_addr); |
3789 | sata_cmd.enc_len = cpu_to_le32(task->total_xfer_len); | 4158 | sata_cmd.enc_len = cpu_to_le32(task->total_xfer_len); |
3790 | sata_cmd.enc_esgl = 0; | 4159 | sata_cmd.enc_esgl = 0; |
4160 | /* Check 4G Boundary */ | ||
4161 | start_addr = cpu_to_le64(dma_addr); | ||
4162 | end_addr = (start_addr + sata_cmd.enc_len) - 1; | ||
4163 | end_addr_low = cpu_to_le32(lower_32_bits(end_addr)); | ||
4164 | end_addr_high = cpu_to_le32(upper_32_bits(end_addr)); | ||
4165 | if (end_addr_high != sata_cmd.enc_addr_high) { | ||
4166 | PM8001_FAIL_DBG(pm8001_ha, | ||
4167 | pm8001_printk("The sg list address " | ||
4168 | "start_addr=0x%016llx data_len=0x%x " | ||
4169 | "end_addr_high=0x%08x end_addr_low" | ||
4170 | "=0x%08x has crossed 4G boundary\n", | ||
4171 | start_addr, sata_cmd.enc_len, | ||
4172 | end_addr_high, end_addr_low)); | ||
4173 | pm8001_chip_make_sg(task->scatter, 1, | ||
4174 | ccb->buf_prd); | ||
4175 | phys_addr = ccb->ccb_dma_handle + | ||
4176 | offsetof(struct pm8001_ccb_info, | ||
4177 | buf_prd[0]); | ||
4178 | sata_cmd.enc_addr_low = | ||
4179 | lower_32_bits(phys_addr); | ||
4180 | sata_cmd.enc_addr_high = | ||
4181 | upper_32_bits(phys_addr); | ||
4182 | sata_cmd.enc_esgl = | ||
4183 | cpu_to_le32(1 << 31); | ||
4184 | } | ||
3791 | } else if (task->num_scatter == 0) { | 4185 | } else if (task->num_scatter == 0) { |
3792 | sata_cmd.enc_addr_low = 0; | 4186 | sata_cmd.enc_addr_low = 0; |
3793 | sata_cmd.enc_addr_high = 0; | 4187 | sata_cmd.enc_addr_high = 0; |
@@ -3808,7 +4202,7 @@ static int pm80xx_chip_sata_req(struct pm8001_hba_info *pm8001_ha, | |||
3808 | } else { | 4202 | } else { |
3809 | PM8001_IO_DBG(pm8001_ha, pm8001_printk( | 4203 | PM8001_IO_DBG(pm8001_ha, pm8001_printk( |
3810 | "Sending Normal SATA command 0x%x inb %x\n", | 4204 | "Sending Normal SATA command 0x%x inb %x\n", |
3811 | sata_cmd.sata_fis.command, inb)); | 4205 | sata_cmd.sata_fis.command, q_index)); |
3812 | /* dad (bit 0-1) is 0 */ | 4206 | /* dad (bit 0-1) is 0 */ |
3813 | sata_cmd.ncqtag_atap_dir_m_dad = | 4207 | sata_cmd.ncqtag_atap_dir_m_dad = |
3814 | cpu_to_le32(((ncg_tag & 0xff)<<16) | | 4208 | cpu_to_le32(((ncg_tag & 0xff)<<16) | |
@@ -3829,6 +4223,30 @@ static int pm80xx_chip_sata_req(struct pm8001_hba_info *pm8001_ha, | |||
3829 | sata_cmd.addr_high = upper_32_bits(dma_addr); | 4223 | sata_cmd.addr_high = upper_32_bits(dma_addr); |
3830 | sata_cmd.len = cpu_to_le32(task->total_xfer_len); | 4224 | sata_cmd.len = cpu_to_le32(task->total_xfer_len); |
3831 | sata_cmd.esgl = 0; | 4225 | sata_cmd.esgl = 0; |
4226 | /* Check 4G Boundary */ | ||
4227 | start_addr = cpu_to_le64(dma_addr); | ||
4228 | end_addr = (start_addr + sata_cmd.len) - 1; | ||
4229 | end_addr_low = cpu_to_le32(lower_32_bits(end_addr)); | ||
4230 | end_addr_high = cpu_to_le32(upper_32_bits(end_addr)); | ||
4231 | if (end_addr_high != sata_cmd.addr_high) { | ||
4232 | PM8001_FAIL_DBG(pm8001_ha, | ||
4233 | pm8001_printk("The sg list address " | ||
4234 | "start_addr=0x%016llx data_len=0x%x" | ||
4235 | "end_addr_high=0x%08x end_addr_low=" | ||
4236 | "0x%08x has crossed 4G boundary\n", | ||
4237 | start_addr, sata_cmd.len, | ||
4238 | end_addr_high, end_addr_low)); | ||
4239 | pm8001_chip_make_sg(task->scatter, 1, | ||
4240 | ccb->buf_prd); | ||
4241 | phys_addr = ccb->ccb_dma_handle + | ||
4242 | offsetof(struct pm8001_ccb_info, | ||
4243 | buf_prd[0]); | ||
4244 | sata_cmd.addr_low = | ||
4245 | lower_32_bits(phys_addr); | ||
4246 | sata_cmd.addr_high = | ||
4247 | upper_32_bits(phys_addr); | ||
4248 | sata_cmd.esgl = cpu_to_le32(1 << 31); | ||
4249 | } | ||
3832 | } else if (task->num_scatter == 0) { | 4250 | } else if (task->num_scatter == 0) { |
3833 | sata_cmd.addr_low = 0; | 4251 | sata_cmd.addr_low = 0; |
3834 | sata_cmd.addr_high = 0; | 4252 | sata_cmd.addr_high = 0; |
@@ -3905,12 +4323,9 @@ static int pm80xx_chip_sata_req(struct pm8001_hba_info *pm8001_ha, | |||
3905 | } | 4323 | } |
3906 | } | 4324 | } |
3907 | } | 4325 | } |
3908 | 4326 | q_index = (u32) (pm8001_ha_dev->id & 0x00ffffff) % PM8001_MAX_OUTB_NUM; | |
3909 | ret = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, | 4327 | ret = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, |
3910 | &sata_cmd, outb++); | 4328 | &sata_cmd, q_index); |
3911 | |||
3912 | /* rotate the outb queue */ | ||
3913 | outb = outb%PM8001_MAX_SPCV_OUTB_NUM; | ||
3914 | return ret; | 4329 | return ret; |
3915 | } | 4330 | } |
3916 | 4331 | ||
@@ -3941,9 +4356,16 @@ pm80xx_chip_phy_start_req(struct pm8001_hba_info *pm8001_ha, u8 phy_id) | |||
3941 | ** [14] 0b disable spin up hold; 1b enable spin up hold | 4356 | ** [14] 0b disable spin up hold; 1b enable spin up hold |
3942 | ** [15] ob no change in current PHY analig setup 1b enable using SPAST | 4357 | ** [15] ob no change in current PHY analig setup 1b enable using SPAST |
3943 | */ | 4358 | */ |
3944 | payload.ase_sh_lm_slr_phyid = cpu_to_le32(SPINHOLD_DISABLE | | 4359 | if (!IS_SPCV_12G(pm8001_ha->pdev)) |
3945 | LINKMODE_AUTO | LINKRATE_15 | | 4360 | payload.ase_sh_lm_slr_phyid = cpu_to_le32(SPINHOLD_DISABLE | |
3946 | LINKRATE_30 | LINKRATE_60 | phy_id); | 4361 | LINKMODE_AUTO | LINKRATE_15 | |
4362 | LINKRATE_30 | LINKRATE_60 | phy_id); | ||
4363 | else | ||
4364 | payload.ase_sh_lm_slr_phyid = cpu_to_le32(SPINHOLD_DISABLE | | ||
4365 | LINKMODE_AUTO | LINKRATE_15 | | ||
4366 | LINKRATE_30 | LINKRATE_60 | LINKRATE_120 | | ||
4367 | phy_id); | ||
4368 | |||
3947 | /* SSC Disable and SAS Analog ST configuration */ | 4369 | /* SSC Disable and SAS Analog ST configuration */ |
3948 | /** | 4370 | /** |
3949 | payload.ase_sh_lm_slr_phyid = | 4371 | payload.ase_sh_lm_slr_phyid = |
@@ -4102,6 +4524,45 @@ pm80xx_chip_isr(struct pm8001_hba_info *pm8001_ha, u8 vec) | |||
4102 | return IRQ_HANDLED; | 4524 | return IRQ_HANDLED; |
4103 | } | 4525 | } |
4104 | 4526 | ||
4527 | void mpi_set_phy_profile_req(struct pm8001_hba_info *pm8001_ha, | ||
4528 | u32 operation, u32 phyid, u32 length, u32 *buf) | ||
4529 | { | ||
4530 | u32 tag , i, j = 0; | ||
4531 | int rc; | ||
4532 | struct set_phy_profile_req payload; | ||
4533 | struct inbound_queue_table *circularQ; | ||
4534 | u32 opc = OPC_INB_SET_PHY_PROFILE; | ||
4535 | |||
4536 | memset(&payload, 0, sizeof(payload)); | ||
4537 | rc = pm8001_tag_alloc(pm8001_ha, &tag); | ||
4538 | if (rc) | ||
4539 | PM8001_FAIL_DBG(pm8001_ha, pm8001_printk("Invalid tag\n")); | ||
4540 | circularQ = &pm8001_ha->inbnd_q_tbl[0]; | ||
4541 | payload.tag = cpu_to_le32(tag); | ||
4542 | payload.ppc_phyid = (((operation & 0xF) << 8) | (phyid & 0xFF)); | ||
4543 | PM8001_INIT_DBG(pm8001_ha, | ||
4544 | pm8001_printk(" phy profile command for phy %x ,length is %d\n", | ||
4545 | payload.ppc_phyid, length)); | ||
4546 | for (i = length; i < (length + PHY_DWORD_LENGTH - 1); i++) { | ||
4547 | payload.reserved[j] = cpu_to_le32(*((u32 *)buf + i)); | ||
4548 | j++; | ||
4549 | } | ||
4550 | pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload, 0); | ||
4551 | } | ||
4552 | |||
4553 | void pm8001_set_phy_profile(struct pm8001_hba_info *pm8001_ha, | ||
4554 | u32 length, u8 *buf) | ||
4555 | { | ||
4556 | u32 page_code, i; | ||
4557 | |||
4558 | page_code = SAS_PHY_ANALOG_SETTINGS_PAGE; | ||
4559 | for (i = 0; i < pm8001_ha->chip->n_phy; i++) { | ||
4560 | mpi_set_phy_profile_req(pm8001_ha, | ||
4561 | SAS_PHY_ANALOG_SETTINGS_PAGE, i, length, (u32 *)buf); | ||
4562 | length = length + PHY_DWORD_LENGTH; | ||
4563 | } | ||
4564 | PM8001_INIT_DBG(pm8001_ha, pm8001_printk("phy settings completed\n")); | ||
4565 | } | ||
4105 | const struct pm8001_dispatch pm8001_80xx_dispatch = { | 4566 | const struct pm8001_dispatch pm8001_80xx_dispatch = { |
4106 | .name = "pmc80xx", | 4567 | .name = "pmc80xx", |
4107 | .chip_init = pm80xx_chip_init, | 4568 | .chip_init = pm80xx_chip_init, |
diff --git a/drivers/scsi/pm8001/pm80xx_hwi.h b/drivers/scsi/pm8001/pm80xx_hwi.h index 2b760ba75d7b..c86816bea424 100644 --- a/drivers/scsi/pm8001/pm80xx_hwi.h +++ b/drivers/scsi/pm8001/pm80xx_hwi.h | |||
@@ -168,6 +168,11 @@ | |||
168 | #define LINKRATE_15 (0x01 << 8) | 168 | #define LINKRATE_15 (0x01 << 8) |
169 | #define LINKRATE_30 (0x02 << 8) | 169 | #define LINKRATE_30 (0x02 << 8) |
170 | #define LINKRATE_60 (0x06 << 8) | 170 | #define LINKRATE_60 (0x06 << 8) |
171 | #define LINKRATE_120 (0x08 << 8) | ||
172 | |||
173 | /* phy_profile */ | ||
174 | #define SAS_PHY_ANALOG_SETTINGS_PAGE 0x04 | ||
175 | #define PHY_DWORD_LENGTH 0xC | ||
171 | 176 | ||
172 | /* Thermal related */ | 177 | /* Thermal related */ |
173 | #define THERMAL_ENABLE 0x1 | 178 | #define THERMAL_ENABLE 0x1 |
@@ -1223,10 +1228,10 @@ typedef struct SASProtocolTimerConfig SASProtocolTimerConfig_t; | |||
1223 | 1228 | ||
1224 | /* MSGU CONFIGURATION TABLE*/ | 1229 | /* MSGU CONFIGURATION TABLE*/ |
1225 | 1230 | ||
1226 | #define SPCv_MSGU_CFG_TABLE_UPDATE 0x01 | 1231 | #define SPCv_MSGU_CFG_TABLE_UPDATE 0x001 |
1227 | #define SPCv_MSGU_CFG_TABLE_RESET 0x02 | 1232 | #define SPCv_MSGU_CFG_TABLE_RESET 0x002 |
1228 | #define SPCv_MSGU_CFG_TABLE_FREEZE 0x04 | 1233 | #define SPCv_MSGU_CFG_TABLE_FREEZE 0x004 |
1229 | #define SPCv_MSGU_CFG_TABLE_UNFREEZE 0x08 | 1234 | #define SPCv_MSGU_CFG_TABLE_UNFREEZE 0x008 |
1230 | #define MSGU_IBDB_SET 0x00 | 1235 | #define MSGU_IBDB_SET 0x00 |
1231 | #define MSGU_HOST_INT_STATUS 0x08 | 1236 | #define MSGU_HOST_INT_STATUS 0x08 |
1232 | #define MSGU_HOST_INT_MASK 0x0C | 1237 | #define MSGU_HOST_INT_MASK 0x0C |
@@ -1520,4 +1525,6 @@ typedef struct SASProtocolTimerConfig SASProtocolTimerConfig_t; | |||
1520 | #define DEVREG_FAILURE_PORT_NOT_VALID_STATE 0x06 | 1525 | #define DEVREG_FAILURE_PORT_NOT_VALID_STATE 0x06 |
1521 | #define DEVREG_FAILURE_DEVICE_TYPE_NOT_VALID 0x07 | 1526 | #define DEVREG_FAILURE_DEVICE_TYPE_NOT_VALID 0x07 |
1522 | 1527 | ||
1528 | |||
1529 | #define MEMBASE_II_SHIFT_REGISTER 0x1010 | ||
1523 | #endif | 1530 | #endif |