aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi
diff options
context:
space:
mode:
authorAnand Kumar Santhanam <AnandKumar.Santhanam@pmcs.com>2013-09-04 03:27:00 -0400
committerJames Bottomley <JBottomley@Parallels.com>2013-10-25 04:58:16 -0400
commitd078b5117f18dce57b895df640d9bf2614864829 (patch)
tree6d6141a83ba64f24848a0348804e3522866ae815 /drivers/scsi
parent279094079a442c19ff7e7c0fd9511d9404cb2518 (diff)
[SCSI] pm80xx: Firmware logging support.
Supports below logging facilities, Inbound outbound queues dump. Non fatal dump in case of IO failures. Fatal dump in case of firmware failure. [jejb: checkpatch spacing fixes] Signed-off-by: Anandkumar.Santhanam@pmcs.com Reviewed-by: Jack Wang <jinpu.wang@profitbricks.com> Signed-off-by: James Bottomley <JBottomley@Parallels.com>
Diffstat (limited to 'drivers/scsi')
-rw-r--r--drivers/scsi/pm8001/pm8001_ctl.c119
-rw-r--r--drivers/scsi/pm8001/pm8001_ctl.h4
-rw-r--r--drivers/scsi/pm8001/pm8001_defs.h3
-rw-r--r--drivers/scsi/pm8001/pm8001_hwi.c83
-rw-r--r--drivers/scsi/pm8001/pm8001_hwi.h3
-rw-r--r--drivers/scsi/pm8001/pm8001_init.c4
-rw-r--r--drivers/scsi/pm8001/pm8001_sas.h68
-rw-r--r--drivers/scsi/pm8001/pm80xx_hwi.c225
-rw-r--r--drivers/scsi/pm8001/pm80xx_hwi.h2
9 files changed, 510 insertions, 1 deletions
diff --git a/drivers/scsi/pm8001/pm8001_ctl.c b/drivers/scsi/pm8001/pm8001_ctl.c
index 5a19e1930b4b..a04b4ff8c7f6 100644
--- a/drivers/scsi/pm8001/pm8001_ctl.c
+++ b/drivers/scsi/pm8001/pm8001_ctl.c
@@ -309,6 +309,84 @@ static ssize_t pm8001_ctl_aap_log_show(struct device *cdev,
309} 309}
310static DEVICE_ATTR(aap_log, S_IRUGO, pm8001_ctl_aap_log_show, NULL); 310static 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 */
317static 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
349static 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
357static 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}
388static DEVICE_ATTR(ob_log, S_IRUGO, pm8001_ctl_ob_queue_log_show, NULL);
389/**
312 * pm8001_ctl_bios_version_show - Bios version Display 390 * pm8001_ctl_bios_version_show - Bios version Display
313 * @cdev:pointer to embedded class device 391 * @cdev:pointer to embedded class device
314 * @buf:the buffer returned 392 * @buf:the buffer returned
@@ -377,6 +455,43 @@ static ssize_t pm8001_ctl_iop_log_show(struct device *cdev,
377} 455}
378static DEVICE_ATTR(iop_log, S_IRUGO, pm8001_ctl_iop_log_show, NULL); 456static DEVICE_ATTR(iop_log, S_IRUGO, pm8001_ctl_iop_log_show, NULL);
379 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
466static 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
475static 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 **/
484static 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
493static DEVICE_ATTR(gsm_log, S_IRUGO, pm8001_ctl_gsm_log_show, NULL);
494
380#define FLASH_CMD_NONE 0x00 495#define FLASH_CMD_NONE 0x00
381#define FLASH_CMD_UPDATE 0x01 496#define FLASH_CMD_UPDATE 0x01
382#define FLASH_CMD_SET_NVMD 0x02 497#define FLASH_CMD_SET_NVMD 0x02
@@ -636,6 +751,8 @@ struct device_attribute *pm8001_host_attrs[] = {
636 &dev_attr_update_fw, 751 &dev_attr_update_fw,
637 &dev_attr_aap_log, 752 &dev_attr_aap_log,
638 &dev_attr_iop_log, 753 &dev_attr_iop_log,
754 &dev_attr_fatal_log,
755 &dev_attr_gsm_log,
639 &dev_attr_max_out_io, 756 &dev_attr_max_out_io,
640 &dev_attr_max_devices, 757 &dev_attr_max_devices,
641 &dev_attr_max_sg_list, 758 &dev_attr_max_sg_list,
@@ -643,6 +760,8 @@ struct device_attribute *pm8001_host_attrs[] = {
643 &dev_attr_logging_level, 760 &dev_attr_logging_level,
644 &dev_attr_host_sas_address, 761 &dev_attr_host_sas_address,
645 &dev_attr_bios_version, 762 &dev_attr_bios_version,
763 &dev_attr_ib_log,
764 &dev_attr_ob_log,
646 NULL, 765 NULL,
647}; 766};
648 767
diff --git a/drivers/scsi/pm8001/pm8001_ctl.h b/drivers/scsi/pm8001/pm8001_ctl.h
index c6d8fdd3b9b9..d0d43a250b9e 100644
--- a/drivers/scsi/pm8001/pm8001_ctl.h
+++ b/drivers/scsi/pm8001/pm8001_ctl.h
@@ -55,5 +55,9 @@
55#define FAIL_OUT_MEMORY 0x000c00 55#define FAIL_OUT_MEMORY 0x000c00
56#define FLASH_IN_PROGRESS 0x001000 56#define FLASH_IN_PROGRESS 0x001000
57 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)
58#endif /* PM8001_CTL_H_INCLUDED */ 62#endif /* PM8001_CTL_H_INCLUDED */
59 63
diff --git a/drivers/scsi/pm8001/pm8001_defs.h b/drivers/scsi/pm8001/pm8001_defs.h
index 4bb304d379da..74a4bb9af07b 100644
--- a/drivers/scsi/pm8001/pm8001_defs.h
+++ b/drivers/scsi/pm8001/pm8001_defs.h
@@ -102,7 +102,8 @@ enum memory_region_num {
102 NVMD, /* NVM device */ 102 NVMD, /* NVM device */
103 DEV_MEM, /* memory for devices */ 103 DEV_MEM, /* memory for devices */
104 CCB_MEM, /* memory for command control block */ 104 CCB_MEM, /* memory for command control block */
105 FW_FLASH /* memory for fw flash update */ 105 FW_FLASH, /* memory for fw flash update */
106 FORENSIC_MEM /* memory for fw forensic data */
106}; 107};
107#define PM8001_EVENT_LOG_SIZE (128 * 1024) 108#define PM8001_EVENT_LOG_SIZE (128 * 1024)
108 109
diff --git a/drivers/scsi/pm8001/pm8001_hwi.c b/drivers/scsi/pm8001/pm8001_hwi.c
index 9d1178bcf689..f16ece91b94a 100644
--- a/drivers/scsi/pm8001/pm8001_hwi.c
+++ b/drivers/scsi/pm8001/pm8001_hwi.c
@@ -5001,6 +5001,89 @@ pm8001_chip_fw_flash_update_req(struct pm8001_hba_info *pm8001_ha,
5001 return rc; 5001 return rc;
5002} 5002}
5003 5003
5004ssize_t
5005pm8001_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
5004int 5087int
5005pm8001_chip_set_dev_state_req(struct pm8001_hba_info *pm8001_ha, 5088pm8001_chip_set_dev_state_req(struct pm8001_hba_info *pm8001_ha,
5006 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 92a18c4d2ebb..662bf13c42f0 100644
--- a/drivers/scsi/pm8001/pm8001_init.c
+++ b/drivers/scsi/pm8001/pm8001_init.c
@@ -347,6 +347,10 @@ static int pm8001_alloc(struct pm8001_hba_info *pm8001_ha,
347 /* Memory region for fw flash */ 347 /* Memory region for fw flash */
348 pm8001_ha->memoryMap.region[FW_FLASH].total_len = 4096; 348 pm8001_ha->memoryMap.region[FW_FLASH].total_len = 4096;
349 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;
350 for (i = 0; i < USI_MAX_MEMCNT; i++) { 354 for (i = 0; i < USI_MAX_MEMCNT; i++) {
351 if (pm8001_mem_alloc(pm8001_ha->pdev, 355 if (pm8001_mem_alloc(pm8001_ha->pdev,
352 &pm8001_ha->memoryMap.region[i].virt_ptr, 356 &pm8001_ha->memoryMap.region[i].virt_ptr,
diff --git a/drivers/scsi/pm8001/pm8001_sas.h b/drivers/scsi/pm8001/pm8001_sas.h
index cbde11a57a92..6037d477a183 100644
--- a/drivers/scsi/pm8001/pm8001_sas.h
+++ b/drivers/scsi/pm8001/pm8001_sas.h
@@ -132,6 +132,61 @@ struct pm8001_ioctl_payload {
132 u8 *func_specific; 132 u8 *func_specific;
133}; 133};
134 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
155struct 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
135struct pm8001_dispatch { 190struct pm8001_dispatch {
136 char *name; 191 char *name;
137 int (*chip_init)(struct pm8001_hba_info *pm8001_ha); 192 int (*chip_init)(struct pm8001_hba_info *pm8001_ha);
@@ -346,6 +401,7 @@ union main_cfg_table {
346 u32 phy_attr_table_offset; 401 u32 phy_attr_table_offset;
347 u32 port_recovery_timer; 402 u32 port_recovery_timer;
348 u32 interrupt_reassertion_delay; 403 u32 interrupt_reassertion_delay;
404 u32 fatal_n_non_fatal_dump; /* 0x28 */
349 } pm80xx_tbl; 405 } pm80xx_tbl;
350}; 406};
351 407
@@ -420,6 +476,13 @@ struct pm8001_hba_info {
420 struct pm8001_hba_memspace io_mem[6]; 476 struct pm8001_hba_memspace io_mem[6];
421 struct mpi_mem_req memoryMap; 477 struct mpi_mem_req memoryMap;
422 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;
423 void __iomem *msg_unit_tbl_addr;/*Message Unit Table Addr*/ 486 void __iomem *msg_unit_tbl_addr;/*Message Unit Table Addr*/
424 void __iomem *main_cfg_tbl_addr;/*Main Config Table Addr*/ 487 void __iomem *main_cfg_tbl_addr;/*Main Config Table Addr*/
425 void __iomem *general_stat_tbl_addr;/*General Status Table Addr*/ 488 void __iomem *general_stat_tbl_addr;/*General Status Table Addr*/
@@ -428,6 +491,7 @@ struct pm8001_hba_info {
428 void __iomem *pspa_q_tbl_addr; 491 void __iomem *pspa_q_tbl_addr;
429 /*MPI SAS PHY attributes Queue Config Table Addr*/ 492 /*MPI SAS PHY attributes Queue Config Table Addr*/
430 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 */
431 union main_cfg_table main_cfg_tbl; 495 union main_cfg_table main_cfg_tbl;
432 union general_status_table gs_tbl; 496 union general_status_table gs_tbl;
433 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];
@@ -634,6 +698,10 @@ int pm80xx_set_thermal_config(struct pm8001_hba_info *pm8001_ha);
634int pm8001_bar4_shift(struct pm8001_hba_info *pm8001_ha, u32 shiftValue); 698int pm8001_bar4_shift(struct pm8001_hba_info *pm8001_ha, u32 shiftValue);
635void pm8001_set_phy_profile(struct pm8001_hba_info *pm8001_ha, 699void pm8001_set_phy_profile(struct pm8001_hba_info *pm8001_ha,
636 u32 length, u8 *buf); 700 u32 length, u8 *buf);
701int pm80xx_bar4_shift(struct pm8001_hba_info *pm8001_ha, u32 shiftValue);
702ssize_t pm80xx_get_fatal_dump(struct device *cdev,
703 struct device_attribute *attr, char *buf);
704ssize_t pm8001_get_gsm_dump(struct device *cdev, u32, char *buf);
637/* ctl shared API */ 705/* ctl shared API */
638extern struct device_attribute *pm8001_host_attrs[]; 706extern struct device_attribute *pm8001_host_attrs[];
639 707
diff --git a/drivers/scsi/pm8001/pm80xx_hwi.c b/drivers/scsi/pm8001/pm80xx_hwi.c
index 91cf4242a03d..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
50int 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
69void 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
87ssize_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) {
149moreData:
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
@@ -583,6 +805,9 @@ static void init_pci_device_addresses(struct pm8001_hba_info *pm8001_ha)
583 pm8001_ha->pspa_q_tbl_addr = 805 pm8001_ha->pspa_q_tbl_addr =
584 base_addr + (pm8001_cr32(pm8001_ha, pcibar, offset + 0x90) & 806 base_addr + (pm8001_cr32(pm8001_ha, pcibar, offset + 0x90) &
585 0xFFFFFF); 807 0xFFFFFF);
808 pm8001_ha->fatal_tbl_addr =
809 base_addr + (pm8001_cr32(pm8001_ha, pcibar, offset + 0xA0) &
810 0xFFFFFF);
586 811
587 PM8001_INIT_DBG(pm8001_ha, 812 PM8001_INIT_DBG(pm8001_ha,
588 pm8001_printk("GST OFFSET 0x%x\n", 813 pm8001_printk("GST OFFSET 0x%x\n",
diff --git a/drivers/scsi/pm8001/pm80xx_hwi.h b/drivers/scsi/pm8001/pm80xx_hwi.h
index 872d5cff824f..c86816bea424 100644
--- a/drivers/scsi/pm8001/pm80xx_hwi.h
+++ b/drivers/scsi/pm8001/pm80xx_hwi.h
@@ -1525,4 +1525,6 @@ typedef struct SASProtocolTimerConfig SASProtocolTimerConfig_t;
1525#define DEVREG_FAILURE_PORT_NOT_VALID_STATE 0x06 1525#define DEVREG_FAILURE_PORT_NOT_VALID_STATE 0x06
1526#define DEVREG_FAILURE_DEVICE_TYPE_NOT_VALID 0x07 1526#define DEVREG_FAILURE_DEVICE_TYPE_NOT_VALID 0x07
1527 1527
1528
1529#define MEMBASE_II_SHIFT_REGISTER 0x1010
1528#endif 1530#endif