diff options
author | Wayne Boyer <wayneb@linux.vnet.ibm.com> | 2010-06-04 13:26:50 -0400 |
---|---|---|
committer | James Bottomley <James.Bottomley@suse.de> | 2010-07-27 13:01:30 -0400 |
commit | 8701f18504751a5b89be3203e28c5ec04c147167 (patch) | |
tree | 58f15f58a76ce73e1d92c72a21c19b350b8ded30 | |
parent | da2907ffd08a2d708c829ec171f05fe3ceab1315 (diff) |
[SCSI] ipr: add endian swap enablement for 64 bit adapters
A change in the hardware design of the chip for the new adapters changes the
default endianness of MMIO operations. This patch adds a register definition
which when written to with a predefined value will change the endianness
back to what the driver expects.
This patch also fixes two problems found during testing.
First, the first reserved field in the ipr_hostrcb64_fabirc_desc structure only
reserved one byte. The correct amount to reserve is 2 bytes.
Second, the reserved field of the ipr_hostrcb64_error structure only reserved
2 bytes. The correct amount to reserve is 16 bytes.
Signed-off-by: Wayne Boyer <wayneb@linux.vnet.ibm.com>
Acked-by: Brian King <brking@linux.vnet.ibm.com>
Signed-off-by: James Bottomley <James.Bottomley@suse.de>
-rw-r--r-- | drivers/scsi/ipr.c | 19 | ||||
-rw-r--r-- | drivers/scsi/ipr.h | 9 |
2 files changed, 24 insertions, 4 deletions
diff --git a/drivers/scsi/ipr.c b/drivers/scsi/ipr.c index f820cffb7f00..62bbe31dd47b 100644 --- a/drivers/scsi/ipr.c +++ b/drivers/scsi/ipr.c | |||
@@ -167,7 +167,8 @@ static const struct ipr_chip_cfg_t ipr_chip_cfg[] = { | |||
167 | .clr_uproc_interrupt_reg32 = 0x0002C, | 167 | .clr_uproc_interrupt_reg32 = 0x0002C, |
168 | .init_feedback_reg = 0x0005C, | 168 | .init_feedback_reg = 0x0005C, |
169 | .dump_addr_reg = 0x00064, | 169 | .dump_addr_reg = 0x00064, |
170 | .dump_data_reg = 0x00068 | 170 | .dump_data_reg = 0x00068, |
171 | .endian_swap_reg = 0x00084 | ||
171 | } | 172 | } |
172 | }, | 173 | }, |
173 | }; | 174 | }; |
@@ -7208,6 +7209,12 @@ static int ipr_reset_enable_ioa(struct ipr_cmnd *ipr_cmd) | |||
7208 | ipr_init_ioa_mem(ioa_cfg); | 7209 | ipr_init_ioa_mem(ioa_cfg); |
7209 | 7210 | ||
7210 | ioa_cfg->allow_interrupts = 1; | 7211 | ioa_cfg->allow_interrupts = 1; |
7212 | if (ioa_cfg->sis64) { | ||
7213 | /* Set the adapter to the correct endian mode. */ | ||
7214 | writel(IPR_ENDIAN_SWAP_KEY, ioa_cfg->regs.endian_swap_reg); | ||
7215 | int_reg = readl(ioa_cfg->regs.endian_swap_reg); | ||
7216 | } | ||
7217 | |||
7211 | int_reg = readl(ioa_cfg->regs.sense_interrupt_reg32); | 7218 | int_reg = readl(ioa_cfg->regs.sense_interrupt_reg32); |
7212 | 7219 | ||
7213 | if (int_reg & IPR_PCII_IOA_TRANS_TO_OPER) { | 7220 | if (int_reg & IPR_PCII_IOA_TRANS_TO_OPER) { |
@@ -7365,6 +7372,7 @@ static void ipr_get_unit_check_buffer(struct ipr_ioa_cfg *ioa_cfg) | |||
7365 | static int ipr_reset_restore_cfg_space(struct ipr_cmnd *ipr_cmd) | 7372 | static int ipr_reset_restore_cfg_space(struct ipr_cmnd *ipr_cmd) |
7366 | { | 7373 | { |
7367 | struct ipr_ioa_cfg *ioa_cfg = ipr_cmd->ioa_cfg; | 7374 | struct ipr_ioa_cfg *ioa_cfg = ipr_cmd->ioa_cfg; |
7375 | volatile u32 int_reg; | ||
7368 | int rc; | 7376 | int rc; |
7369 | 7377 | ||
7370 | ENTER; | 7378 | ENTER; |
@@ -7383,6 +7391,12 @@ static int ipr_reset_restore_cfg_space(struct ipr_cmnd *ipr_cmd) | |||
7383 | 7391 | ||
7384 | ipr_fail_all_ops(ioa_cfg); | 7392 | ipr_fail_all_ops(ioa_cfg); |
7385 | 7393 | ||
7394 | if (ioa_cfg->sis64) { | ||
7395 | /* Set the adapter to the correct endian mode. */ | ||
7396 | writel(IPR_ENDIAN_SWAP_KEY, ioa_cfg->regs.endian_swap_reg); | ||
7397 | int_reg = readl(ioa_cfg->regs.endian_swap_reg); | ||
7398 | } | ||
7399 | |||
7386 | if (ioa_cfg->ioa_unit_checked) { | 7400 | if (ioa_cfg->ioa_unit_checked) { |
7387 | ioa_cfg->ioa_unit_checked = 0; | 7401 | ioa_cfg->ioa_unit_checked = 0; |
7388 | ipr_get_unit_check_buffer(ioa_cfg); | 7402 | ipr_get_unit_check_buffer(ioa_cfg); |
@@ -7547,7 +7561,7 @@ static int ipr_reset_wait_to_start_bist(struct ipr_cmnd *ipr_cmd) | |||
7547 | } | 7561 | } |
7548 | 7562 | ||
7549 | /** | 7563 | /** |
7550 | * ipr_reset_alert_part2 - Alert the adapter of a pending reset | 7564 | * ipr_reset_alert - Alert the adapter of a pending reset |
7551 | * @ipr_cmd: ipr command struct | 7565 | * @ipr_cmd: ipr command struct |
7552 | * | 7566 | * |
7553 | * Description: This function alerts the adapter that it will be reset. | 7567 | * Description: This function alerts the adapter that it will be reset. |
@@ -8318,6 +8332,7 @@ static void __devinit ipr_init_ioa_cfg(struct ipr_ioa_cfg *ioa_cfg, | |||
8318 | t->init_feedback_reg = base + p->init_feedback_reg; | 8332 | t->init_feedback_reg = base + p->init_feedback_reg; |
8319 | t->dump_addr_reg = base + p->dump_addr_reg; | 8333 | t->dump_addr_reg = base + p->dump_addr_reg; |
8320 | t->dump_data_reg = base + p->dump_data_reg; | 8334 | t->dump_data_reg = base + p->dump_data_reg; |
8335 | t->endian_swap_reg = base + p->endian_swap_reg; | ||
8321 | } | 8336 | } |
8322 | } | 8337 | } |
8323 | 8338 | ||
diff --git a/drivers/scsi/ipr.h b/drivers/scsi/ipr.h index b965f3587c9d..ea391ffc8711 100644 --- a/drivers/scsi/ipr.h +++ b/drivers/scsi/ipr.h | |||
@@ -996,7 +996,7 @@ struct ipr_hostrcb64_fabric_desc { | |||
996 | __be16 length; | 996 | __be16 length; |
997 | u8 descriptor_id; | 997 | u8 descriptor_id; |
998 | 998 | ||
999 | u8 reserved; | 999 | u8 reserved[2]; |
1000 | u8 path_state; | 1000 | u8 path_state; |
1001 | 1001 | ||
1002 | u8 reserved2[2]; | 1002 | u8 reserved2[2]; |
@@ -1054,7 +1054,7 @@ struct ipr_hostrcb64_error { | |||
1054 | __be64 fd_lun; | 1054 | __be64 fd_lun; |
1055 | u8 fd_res_path[8]; | 1055 | u8 fd_res_path[8]; |
1056 | __be64 time_stamp; | 1056 | __be64 time_stamp; |
1057 | u8 reserved[2]; | 1057 | u8 reserved[16]; |
1058 | union { | 1058 | union { |
1059 | struct ipr_hostrcb_type_ff_error type_ff_error; | 1059 | struct ipr_hostrcb_type_ff_error type_ff_error; |
1060 | struct ipr_hostrcb_type_12_error type_12_error; | 1060 | struct ipr_hostrcb_type_12_error type_12_error; |
@@ -1254,6 +1254,9 @@ struct ipr_interrupt_offsets { | |||
1254 | 1254 | ||
1255 | unsigned long dump_addr_reg; | 1255 | unsigned long dump_addr_reg; |
1256 | unsigned long dump_data_reg; | 1256 | unsigned long dump_data_reg; |
1257 | |||
1258 | #define IPR_ENDIAN_SWAP_KEY 0x000C0C00 | ||
1259 | unsigned long endian_swap_reg; | ||
1257 | }; | 1260 | }; |
1258 | 1261 | ||
1259 | struct ipr_interrupts { | 1262 | struct ipr_interrupts { |
@@ -1279,6 +1282,8 @@ struct ipr_interrupts { | |||
1279 | 1282 | ||
1280 | void __iomem *dump_addr_reg; | 1283 | void __iomem *dump_addr_reg; |
1281 | void __iomem *dump_data_reg; | 1284 | void __iomem *dump_data_reg; |
1285 | |||
1286 | void __iomem *endian_swap_reg; | ||
1282 | }; | 1287 | }; |
1283 | 1288 | ||
1284 | struct ipr_chip_cfg_t { | 1289 | struct ipr_chip_cfg_t { |