aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorWayne Boyer <wayneb@linux.vnet.ibm.com>2010-02-19 16:24:14 -0500
committerJames Bottomley <James.Bottomley@suse.de>2010-03-03 05:35:00 -0500
commitdcbad00e6b403089b1846e788bc1a0c67b2bfd2d (patch)
tree75b7d0408cd07eb3d4c863ade52dfda1510f9e8a
parent4565e3706329f65b5e64328b5369c53b6ab2715c (diff)
[SCSI] ipr: add hardware assisted smart dump functionality
This patch adds the hardware assisted smart dump functionality for the next generation IOA PCI interface chip. Signea-off-by: Wayne Boyer <wayneb@linux.vnet.ibm.com> Signed-off-by: James Bottomley <James.Bottomley@suse.de>
-rw-r--r--drivers/scsi/ipr.c81
-rw-r--r--drivers/scsi/ipr.h16
2 files changed, 75 insertions, 22 deletions
diff --git a/drivers/scsi/ipr.c b/drivers/scsi/ipr.c
index b2e60bd4a0c6..dd12486ba520 100644
--- a/drivers/scsi/ipr.c
+++ b/drivers/scsi/ipr.c
@@ -142,7 +142,9 @@ static const struct ipr_chip_cfg_t ipr_chip_cfg[] = {
142 .ioarrin_reg = 0x00070, 142 .ioarrin_reg = 0x00070,
143 .sense_uproc_interrupt_reg = 0x00020, 143 .sense_uproc_interrupt_reg = 0x00020,
144 .set_uproc_interrupt_reg = 0x00020, 144 .set_uproc_interrupt_reg = 0x00020,
145 .clr_uproc_interrupt_reg = 0x00028 145 .clr_uproc_interrupt_reg = 0x00028,
146 .dump_addr_reg = 0x00064,
147 .dump_data_reg = 0x00068
146 } 148 }
147 }, 149 },
148}; 150};
@@ -2514,6 +2516,31 @@ static int ipr_wait_iodbg_ack(struct ipr_ioa_cfg *ioa_cfg, int max_delay)
2514} 2516}
2515 2517
2516/** 2518/**
2519 * ipr_get_sis64_dump_data_section - Dump IOA memory
2520 * @ioa_cfg: ioa config struct
2521 * @start_addr: adapter address to dump
2522 * @dest: destination kernel buffer
2523 * @length_in_words: length to dump in 4 byte words
2524 *
2525 * Return value:
2526 * 0 on success
2527 **/
2528static int ipr_get_sis64_dump_data_section(struct ipr_ioa_cfg *ioa_cfg,
2529 u32 start_addr,
2530 __be32 *dest, u32 length_in_words)
2531{
2532 int i;
2533
2534 for (i = 0; i < length_in_words; i++) {
2535 writel(start_addr+(i*4), ioa_cfg->regs.dump_addr_reg);
2536 *dest = cpu_to_be32(readl(ioa_cfg->regs.dump_data_reg));
2537 dest++;
2538 }
2539
2540 return 0;
2541}
2542
2543/**
2517 * ipr_get_ldump_data_section - Dump IOA memory 2544 * ipr_get_ldump_data_section - Dump IOA memory
2518 * @ioa_cfg: ioa config struct 2545 * @ioa_cfg: ioa config struct
2519 * @start_addr: adapter address to dump 2546 * @start_addr: adapter address to dump
@@ -2530,6 +2557,10 @@ static int ipr_get_ldump_data_section(struct ipr_ioa_cfg *ioa_cfg,
2530 volatile u32 temp_pcii_reg; 2557 volatile u32 temp_pcii_reg;
2531 int i, delay = 0; 2558 int i, delay = 0;
2532 2559
2560 if (ioa_cfg->sis64)
2561 return ipr_get_sis64_dump_data_section(ioa_cfg, start_addr,
2562 dest, length_in_words);
2563
2533 /* Write IOA interrupt reg starting LDUMP state */ 2564 /* Write IOA interrupt reg starting LDUMP state */
2534 writel((IPR_UPROCI_RESET_ALERT | IPR_UPROCI_IO_DEBUG_ALERT), 2565 writel((IPR_UPROCI_RESET_ALERT | IPR_UPROCI_IO_DEBUG_ALERT),
2535 ioa_cfg->regs.set_uproc_interrupt_reg); 2566 ioa_cfg->regs.set_uproc_interrupt_reg);
@@ -2787,6 +2818,7 @@ static void ipr_get_ioa_dump(struct ipr_ioa_cfg *ioa_cfg, struct ipr_dump *dump)
2787 u32 num_entries, start_off, end_off; 2818 u32 num_entries, start_off, end_off;
2788 u32 bytes_to_copy, bytes_copied, rc; 2819 u32 bytes_to_copy, bytes_copied, rc;
2789 struct ipr_sdt *sdt; 2820 struct ipr_sdt *sdt;
2821 int valid = 1;
2790 int i; 2822 int i;
2791 2823
2792 ENTER; 2824 ENTER;
@@ -2800,7 +2832,7 @@ static void ipr_get_ioa_dump(struct ipr_ioa_cfg *ioa_cfg, struct ipr_dump *dump)
2800 2832
2801 start_addr = readl(ioa_cfg->ioa_mailbox); 2833 start_addr = readl(ioa_cfg->ioa_mailbox);
2802 2834
2803 if (!ipr_sdt_is_fmt2(start_addr)) { 2835 if (!ioa_cfg->sis64 && !ipr_sdt_is_fmt2(start_addr)) {
2804 dev_err(&ioa_cfg->pdev->dev, 2836 dev_err(&ioa_cfg->pdev->dev,
2805 "Invalid dump table format: %lx\n", start_addr); 2837 "Invalid dump table format: %lx\n", start_addr);
2806 spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags); 2838 spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags);
@@ -2829,7 +2861,6 @@ static void ipr_get_ioa_dump(struct ipr_ioa_cfg *ioa_cfg, struct ipr_dump *dump)
2829 2861
2830 /* IOA Dump entry */ 2862 /* IOA Dump entry */
2831 ipr_init_dump_entry_hdr(&ioa_dump->hdr); 2863 ipr_init_dump_entry_hdr(&ioa_dump->hdr);
2832 ioa_dump->format = IPR_SDT_FMT2;
2833 ioa_dump->hdr.len = 0; 2864 ioa_dump->hdr.len = 0;
2834 ioa_dump->hdr.data_type = IPR_DUMP_DATA_TYPE_BINARY; 2865 ioa_dump->hdr.data_type = IPR_DUMP_DATA_TYPE_BINARY;
2835 ioa_dump->hdr.id = IPR_DUMP_IOA_DUMP_ID; 2866 ioa_dump->hdr.id = IPR_DUMP_IOA_DUMP_ID;
@@ -2844,7 +2875,8 @@ static void ipr_get_ioa_dump(struct ipr_ioa_cfg *ioa_cfg, struct ipr_dump *dump)
2844 sizeof(struct ipr_sdt) / sizeof(__be32)); 2875 sizeof(struct ipr_sdt) / sizeof(__be32));
2845 2876
2846 /* Smart Dump table is ready to use and the first entry is valid */ 2877 /* Smart Dump table is ready to use and the first entry is valid */
2847 if (rc || (be32_to_cpu(sdt->hdr.state) != IPR_FMT2_SDT_READY_TO_USE)) { 2878 if (rc || ((be32_to_cpu(sdt->hdr.state) != IPR_FMT3_SDT_READY_TO_USE) &&
2879 (be32_to_cpu(sdt->hdr.state) != IPR_FMT2_SDT_READY_TO_USE))) {
2848 dev_err(&ioa_cfg->pdev->dev, 2880 dev_err(&ioa_cfg->pdev->dev,
2849 "Dump of IOA failed. Dump table not valid: %d, %X.\n", 2881 "Dump of IOA failed. Dump table not valid: %d, %X.\n",
2850 rc, be32_to_cpu(sdt->hdr.state)); 2882 rc, be32_to_cpu(sdt->hdr.state));
@@ -2868,12 +2900,19 @@ static void ipr_get_ioa_dump(struct ipr_ioa_cfg *ioa_cfg, struct ipr_dump *dump)
2868 } 2900 }
2869 2901
2870 if (sdt->entry[i].flags & IPR_SDT_VALID_ENTRY) { 2902 if (sdt->entry[i].flags & IPR_SDT_VALID_ENTRY) {
2871 sdt_word = be32_to_cpu(sdt->entry[i].bar_str_offset); 2903 sdt_word = be32_to_cpu(sdt->entry[i].start_token);
2872 start_off = sdt_word & IPR_FMT2_MBX_ADDR_MASK; 2904 if (ioa_cfg->sis64)
2873 end_off = be32_to_cpu(sdt->entry[i].end_offset); 2905 bytes_to_copy = be32_to_cpu(sdt->entry[i].end_token);
2874 2906 else {
2875 if (ipr_sdt_is_fmt2(sdt_word) && sdt_word) { 2907 start_off = sdt_word & IPR_FMT2_MBX_ADDR_MASK;
2876 bytes_to_copy = end_off - start_off; 2908 end_off = be32_to_cpu(sdt->entry[i].end_token);
2909
2910 if (ipr_sdt_is_fmt2(sdt_word) && sdt_word)
2911 bytes_to_copy = end_off - start_off;
2912 else
2913 valid = 0;
2914 }
2915 if (valid) {
2877 if (bytes_to_copy > IPR_MAX_IOA_DUMP_SIZE) { 2916 if (bytes_to_copy > IPR_MAX_IOA_DUMP_SIZE) {
2878 sdt->entry[i].flags &= ~IPR_SDT_VALID_ENTRY; 2917 sdt->entry[i].flags &= ~IPR_SDT_VALID_ENTRY;
2879 continue; 2918 continue;
@@ -7202,7 +7241,7 @@ static void ipr_get_unit_check_buffer(struct ipr_ioa_cfg *ioa_cfg)
7202 7241
7203 mailbox = readl(ioa_cfg->ioa_mailbox); 7242 mailbox = readl(ioa_cfg->ioa_mailbox);
7204 7243
7205 if (!ipr_sdt_is_fmt2(mailbox)) { 7244 if (!ioa_cfg->sis64 && !ipr_sdt_is_fmt2(mailbox)) {
7206 ipr_unit_check_no_data(ioa_cfg); 7245 ipr_unit_check_no_data(ioa_cfg);
7207 return; 7246 return;
7208 } 7247 }
@@ -7211,15 +7250,20 @@ static void ipr_get_unit_check_buffer(struct ipr_ioa_cfg *ioa_cfg)
7211 rc = ipr_get_ldump_data_section(ioa_cfg, mailbox, (__be32 *) &sdt, 7250 rc = ipr_get_ldump_data_section(ioa_cfg, mailbox, (__be32 *) &sdt,
7212 (sizeof(struct ipr_uc_sdt)) / sizeof(__be32)); 7251 (sizeof(struct ipr_uc_sdt)) / sizeof(__be32));
7213 7252
7214 if (rc || (be32_to_cpu(sdt.hdr.state) != IPR_FMT2_SDT_READY_TO_USE) || 7253 if (rc || !(sdt.entry[0].flags & IPR_SDT_VALID_ENTRY) ||
7215 !(sdt.entry[0].flags & IPR_SDT_VALID_ENTRY)) { 7254 ((be32_to_cpu(sdt.hdr.state) != IPR_FMT3_SDT_READY_TO_USE) &&
7255 (be32_to_cpu(sdt.hdr.state) != IPR_FMT2_SDT_READY_TO_USE))) {
7216 ipr_unit_check_no_data(ioa_cfg); 7256 ipr_unit_check_no_data(ioa_cfg);
7217 return; 7257 return;
7218 } 7258 }
7219 7259
7220 /* Find length of the first sdt entry (UC buffer) */ 7260 /* Find length of the first sdt entry (UC buffer) */
7221 length = (be32_to_cpu(sdt.entry[0].end_offset) - 7261 if (be32_to_cpu(sdt.hdr.state) == IPR_FMT3_SDT_READY_TO_USE)
7222 be32_to_cpu(sdt.entry[0].bar_str_offset)) & IPR_FMT2_MBX_ADDR_MASK; 7262 length = be32_to_cpu(sdt.entry[0].end_token);
7263 else
7264 length = (be32_to_cpu(sdt.entry[0].end_token) -
7265 be32_to_cpu(sdt.entry[0].start_token)) &
7266 IPR_FMT2_MBX_ADDR_MASK;
7223 7267
7224 hostrcb = list_entry(ioa_cfg->hostrcb_free_q.next, 7268 hostrcb = list_entry(ioa_cfg->hostrcb_free_q.next,
7225 struct ipr_hostrcb, queue); 7269 struct ipr_hostrcb, queue);
@@ -7227,7 +7271,7 @@ static void ipr_get_unit_check_buffer(struct ipr_ioa_cfg *ioa_cfg)
7227 memset(&hostrcb->hcam, 0, sizeof(hostrcb->hcam)); 7271 memset(&hostrcb->hcam, 0, sizeof(hostrcb->hcam));
7228 7272
7229 rc = ipr_get_ldump_data_section(ioa_cfg, 7273 rc = ipr_get_ldump_data_section(ioa_cfg,
7230 be32_to_cpu(sdt.entry[0].bar_str_offset), 7274 be32_to_cpu(sdt.entry[0].start_token),
7231 (__be32 *)&hostrcb->hcam, 7275 (__be32 *)&hostrcb->hcam,
7232 min(length, (int)sizeof(hostrcb->hcam)) / sizeof(__be32)); 7276 min(length, (int)sizeof(hostrcb->hcam)) / sizeof(__be32));
7233 7277
@@ -8202,6 +8246,11 @@ static void __devinit ipr_init_ioa_cfg(struct ipr_ioa_cfg *ioa_cfg,
8202 t->sense_uproc_interrupt_reg = base + p->sense_uproc_interrupt_reg; 8246 t->sense_uproc_interrupt_reg = base + p->sense_uproc_interrupt_reg;
8203 t->set_uproc_interrupt_reg = base + p->set_uproc_interrupt_reg; 8247 t->set_uproc_interrupt_reg = base + p->set_uproc_interrupt_reg;
8204 t->clr_uproc_interrupt_reg = base + p->clr_uproc_interrupt_reg; 8248 t->clr_uproc_interrupt_reg = base + p->clr_uproc_interrupt_reg;
8249
8250 if (ioa_cfg->sis64) {
8251 t->dump_addr_reg = base + p->dump_addr_reg;
8252 t->dump_data_reg = base + p->dump_data_reg;
8253 }
8205} 8254}
8206 8255
8207/** 8256/**
diff --git a/drivers/scsi/ipr.h b/drivers/scsi/ipr.h
index e6e90179e45e..4f2f1d2e9875 100644
--- a/drivers/scsi/ipr.h
+++ b/drivers/scsi/ipr.h
@@ -228,6 +228,7 @@
228#define IPR_SDT_FMT2_BAR5_SEL 0x5 228#define IPR_SDT_FMT2_BAR5_SEL 0x5
229#define IPR_SDT_FMT2_EXP_ROM_SEL 0x8 229#define IPR_SDT_FMT2_EXP_ROM_SEL 0x8
230#define IPR_FMT2_SDT_READY_TO_USE 0xC4D4E3F2 230#define IPR_FMT2_SDT_READY_TO_USE 0xC4D4E3F2
231#define IPR_FMT3_SDT_READY_TO_USE 0xC4D4E3F3
231#define IPR_DOORBELL 0x82800000 232#define IPR_DOORBELL 0x82800000
232#define IPR_RUNTIME_RESET 0x40000000 233#define IPR_RUNTIME_RESET 0x40000000
233 234
@@ -1093,10 +1094,9 @@ struct ipr_hostrcb {
1093 1094
1094/* IPR smart dump table structures */ 1095/* IPR smart dump table structures */
1095struct ipr_sdt_entry { 1096struct ipr_sdt_entry {
1096 __be32 bar_str_offset; 1097 __be32 start_token;
1097 __be32 end_offset; 1098 __be32 end_token;
1098 u8 entry_byte; 1099 u8 reserved[4];
1099 u8 reserved[3];
1100 1100
1101 u8 flags; 1101 u8 flags;
1102#define IPR_SDT_ENDIAN 0x80 1102#define IPR_SDT_ENDIAN 0x80
@@ -1204,6 +1204,9 @@ struct ipr_interrupt_offsets {
1204 unsigned long sense_uproc_interrupt_reg; 1204 unsigned long sense_uproc_interrupt_reg;
1205 unsigned long set_uproc_interrupt_reg; 1205 unsigned long set_uproc_interrupt_reg;
1206 unsigned long clr_uproc_interrupt_reg; 1206 unsigned long clr_uproc_interrupt_reg;
1207
1208 unsigned long dump_addr_reg;
1209 unsigned long dump_data_reg;
1207}; 1210};
1208 1211
1209struct ipr_interrupts { 1212struct ipr_interrupts {
@@ -1217,6 +1220,9 @@ struct ipr_interrupts {
1217 void __iomem *sense_uproc_interrupt_reg; 1220 void __iomem *sense_uproc_interrupt_reg;
1218 void __iomem *set_uproc_interrupt_reg; 1221 void __iomem *set_uproc_interrupt_reg;
1219 void __iomem *clr_uproc_interrupt_reg; 1222 void __iomem *clr_uproc_interrupt_reg;
1223
1224 void __iomem *dump_addr_reg;
1225 void __iomem *dump_data_reg;
1220}; 1226};
1221 1227
1222struct ipr_chip_cfg_t { 1228struct ipr_chip_cfg_t {
@@ -1536,8 +1542,6 @@ struct ipr_ioa_dump {
1536 u32 next_page_index; 1542 u32 next_page_index;
1537 u32 page_offset; 1543 u32 page_offset;
1538 u32 format; 1544 u32 format;
1539#define IPR_SDT_FMT2 2
1540#define IPR_SDT_UNKNOWN 3
1541}__attribute__((packed, aligned (4))); 1545}__attribute__((packed, aligned (4)));
1542 1546
1543struct ipr_dump { 1547struct ipr_dump {