diff options
Diffstat (limited to 'drivers/scsi/ipr.c')
-rw-r--r-- | drivers/scsi/ipr.c | 266 |
1 files changed, 201 insertions, 65 deletions
diff --git a/drivers/scsi/ipr.c b/drivers/scsi/ipr.c index f820cffb7f00..fa60d7df44be 100644 --- a/drivers/scsi/ipr.c +++ b/drivers/scsi/ipr.c @@ -167,21 +167,22 @@ static const struct ipr_chip_cfg_t ipr_chip_cfg[] = { .clr_uproc_interrupt_reg32 = 0x0002C, .init_feedback_reg = 0x0005C, .dump_addr_reg = 0x00064, - .dump_data_reg = 0x00068 + .dump_data_reg = 0x00068, + .endian_swap_reg = 0x00084 } }, }; static const struct ipr_chip_t ipr_chip[] = { - { PCI_VENDOR_ID_MYLEX, PCI_DEVICE_ID_IBM_GEMSTONE, IPR_USE_LSI, IPR_SIS32, &ipr_chip_cfg[0] }, - { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_CITRINE, IPR_USE_LSI, IPR_SIS32, &ipr_chip_cfg[0] }, - { PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_OBSIDIAN, IPR_USE_LSI, IPR_SIS32, &ipr_chip_cfg[0] }, - { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_OBSIDIAN, IPR_USE_LSI, IPR_SIS32, &ipr_chip_cfg[0] }, - { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_OBSIDIAN_E, IPR_USE_MSI, IPR_SIS32, &ipr_chip_cfg[0] }, - { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_SNIPE, IPR_USE_LSI, IPR_SIS32, &ipr_chip_cfg[1] }, - { PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_SCAMP, IPR_USE_LSI, IPR_SIS32, &ipr_chip_cfg[1] }, - { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_CROC_FPGA_E2, IPR_USE_MSI, IPR_SIS64, &ipr_chip_cfg[2] }, - { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_CROC_ASIC_E2, IPR_USE_MSI, IPR_SIS64, &ipr_chip_cfg[2] } + { PCI_VENDOR_ID_MYLEX, PCI_DEVICE_ID_IBM_GEMSTONE, IPR_USE_LSI, IPR_SIS32, IPR_PCI_CFG, &ipr_chip_cfg[0] }, + { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_CITRINE, IPR_USE_LSI, IPR_SIS32, IPR_PCI_CFG, &ipr_chip_cfg[0] }, + { PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_OBSIDIAN, IPR_USE_LSI, IPR_SIS32, IPR_PCI_CFG, &ipr_chip_cfg[0] }, + { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_OBSIDIAN, IPR_USE_LSI, IPR_SIS32, IPR_PCI_CFG, &ipr_chip_cfg[0] }, + { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_OBSIDIAN_E, IPR_USE_MSI, IPR_SIS32, IPR_PCI_CFG, &ipr_chip_cfg[0] }, + { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_SNIPE, IPR_USE_LSI, IPR_SIS32, IPR_PCI_CFG, &ipr_chip_cfg[1] }, + { PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_SCAMP, IPR_USE_LSI, IPR_SIS32, IPR_PCI_CFG, &ipr_chip_cfg[1] }, + { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_CROC_FPGA_E2, IPR_USE_MSI, IPR_SIS64, IPR_MMIO, &ipr_chip_cfg[2] }, + { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_CROC_ASIC_E2, IPR_USE_MSI, IPR_SIS64, IPR_MMIO, &ipr_chip_cfg[2] } }; static int ipr_max_bus_speeds [] = { @@ -1095,6 +1096,7 @@ static void ipr_init_res_entry(struct ipr_resource_entry *res, res->bus = cfgtew->u.cfgte->res_addr.bus; res->target = cfgtew->u.cfgte->res_addr.target; res->lun = cfgtew->u.cfgte->res_addr.lun; + res->lun_wwn = get_unaligned_be64(cfgtew->u.cfgte->lun_wwn); } ipr_update_ata_class(res, proto); @@ -1141,7 +1143,7 @@ static char *ipr_format_res_path(u8 *res_path, char *buffer, int len) int i; char *p = buffer; - res_path[0] = '\0'; + *p = '\0'; p += snprintf(p, buffer + len - p, "%02X", res_path[0]); for (i = 1; res_path[i] != 0xff && ((i * 3) < len); i++) p += snprintf(p, buffer + len - p, "-%02X", res_path[i]); @@ -1167,7 +1169,7 @@ static void ipr_update_res_entry(struct ipr_resource_entry *res, if (res->ioa_cfg->sis64) { res->flags = cfgtew->u.cfgte64->flags; res->res_flags = cfgtew->u.cfgte64->res_flags; - res->type = cfgtew->u.cfgte64->res_type & 0x0f; + res->type = cfgtew->u.cfgte64->res_type; memcpy(&res->std_inq_data, &cfgtew->u.cfgte64->std_inq_data, sizeof(struct ipr_std_inq_data)); @@ -1669,7 +1671,7 @@ static void ipr_log_enhanced_array_error(struct ipr_ioa_cfg *ioa_cfg, array_entry = error->array_member; num_entries = min_t(u32, be32_to_cpu(error->num_entries), - sizeof(error->array_member)); + ARRAY_SIZE(error->array_member)); for (i = 0; i < num_entries; i++, array_entry++) { if (!memcmp(array_entry->vpd.vpd.sn, zero_sn, IPR_SERIAL_NUM_LEN)) @@ -2150,8 +2152,8 @@ static void ipr_log_sis64_array_error(struct ipr_ioa_cfg *ioa_cfg, ipr_err_separator; array_entry = error->array_member; - num_entries = min_t(u32, be32_to_cpu(error->num_entries), - sizeof(error->array_member)); + num_entries = min_t(u32, error->num_entries, + ARRAY_SIZE(error->array_member)); for (i = 0; i < num_entries; i++, array_entry++) { @@ -2165,10 +2167,10 @@ static void ipr_log_sis64_array_error(struct ipr_ioa_cfg *ioa_cfg, ipr_err("Array Member %d:\n", i); ipr_log_ext_vpd(&array_entry->vpd); - ipr_err("Current Location: %s", + ipr_err("Current Location: %s\n", ipr_format_res_path(array_entry->res_path, buffer, sizeof(buffer))); - ipr_err("Expected Location: %s", + ipr_err("Expected Location: %s\n", ipr_format_res_path(array_entry->expected_res_path, buffer, sizeof(buffer))); @@ -3761,6 +3763,36 @@ static struct device_attribute ipr_update_fw_attr = { .store = ipr_store_update_fw }; +/** + * ipr_show_fw_type - Show the adapter's firmware type. + * @dev: class device struct + * @buf: buffer + * + * Return value: + * number of bytes printed to buffer + **/ +static ssize_t ipr_show_fw_type(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct Scsi_Host *shost = class_to_shost(dev); + struct ipr_ioa_cfg *ioa_cfg = (struct ipr_ioa_cfg *)shost->hostdata; + unsigned long lock_flags = 0; + int len; + + spin_lock_irqsave(ioa_cfg->host->host_lock, lock_flags); + len = snprintf(buf, PAGE_SIZE, "%d\n", ioa_cfg->sis64); + spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags); + return len; +} + +static struct device_attribute ipr_ioa_fw_type_attr = { + .attr = { + .name = "fw_type", + .mode = S_IRUGO, + }, + .show = ipr_show_fw_type +}; + static struct device_attribute *ipr_ioa_attrs[] = { &ipr_fw_version_attr, &ipr_log_level_attr, @@ -3768,6 +3800,7 @@ static struct device_attribute *ipr_ioa_attrs[] = { &ipr_ioa_state_attr, &ipr_ioa_reset_attr, &ipr_update_fw_attr, + &ipr_ioa_fw_type_attr, NULL, }; @@ -4057,6 +4090,7 @@ static int ipr_change_queue_type(struct scsi_device *sdev, int tag_type) /** * ipr_show_adapter_handle - Show the adapter's resource handle for this device * @dev: device struct + * @attr: device attribute structure * @buf: buffer * * Return value: @@ -4090,6 +4124,7 @@ static struct device_attribute ipr_adapter_handle_attr = { * ipr_show_resource_path - Show the resource path or the resource address for * this device. * @dev: device struct + * @attr: device attribute structure * @buf: buffer * * Return value: @@ -4121,14 +4156,87 @@ static ssize_t ipr_show_resource_path(struct device *dev, struct device_attribut static struct device_attribute ipr_resource_path_attr = { .attr = { .name = "resource_path", - .mode = S_IRUSR, + .mode = S_IRUGO, }, .show = ipr_show_resource_path }; +/** + * ipr_show_device_id - Show the device_id for this device. + * @dev: device struct + * @attr: device attribute structure + * @buf: buffer + * + * Return value: + * number of bytes printed to buffer + **/ +static ssize_t ipr_show_device_id(struct device *dev, struct device_attribute *attr, char *buf) +{ + struct scsi_device *sdev = to_scsi_device(dev); + struct ipr_ioa_cfg *ioa_cfg = (struct ipr_ioa_cfg *)sdev->host->hostdata; + struct ipr_resource_entry *res; + unsigned long lock_flags = 0; + ssize_t len = -ENXIO; + + spin_lock_irqsave(ioa_cfg->host->host_lock, lock_flags); + res = (struct ipr_resource_entry *)sdev->hostdata; + if (res && ioa_cfg->sis64) + len = snprintf(buf, PAGE_SIZE, "0x%llx\n", res->dev_id); + else if (res) + len = snprintf(buf, PAGE_SIZE, "0x%llx\n", res->lun_wwn); + + spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags); + return len; +} + +static struct device_attribute ipr_device_id_attr = { + .attr = { + .name = "device_id", + .mode = S_IRUGO, + }, + .show = ipr_show_device_id +}; + +/** + * ipr_show_resource_type - Show the resource type for this device. + * @dev: device struct + * @attr: device attribute structure + * @buf: buffer + * + * Return value: + * number of bytes printed to buffer + **/ +static ssize_t ipr_show_resource_type(struct device *dev, struct device_attribute *attr, char *buf) +{ + struct scsi_device *sdev = to_scsi_device(dev); + struct ipr_ioa_cfg *ioa_cfg = (struct ipr_ioa_cfg *)sdev->host->hostdata; + struct ipr_resource_entry *res; + unsigned long lock_flags = 0; + ssize_t len = -ENXIO; + + spin_lock_irqsave(ioa_cfg->host->host_lock, lock_flags); + res = (struct ipr_resource_entry *)sdev->hostdata; + + if (res) + len = snprintf(buf, PAGE_SIZE, "%x\n", res->type); + + spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags); + return len; +} + +static struct device_attribute ipr_resource_type_attr = { + .attr = { + .name = "resource_type", + .mode = S_IRUGO, + }, + .show = ipr_show_resource_type +}; + static struct device_attribute *ipr_dev_attrs[] = { &ipr_adapter_handle_attr, &ipr_resource_path_attr, + &ipr_device_id_attr, + &ipr_resource_type_attr, NULL, }; @@ -4352,8 +4460,6 @@ static int ipr_slave_configure(struct scsi_device *sdev) IPR_VSET_RW_TIMEOUT); blk_queue_max_hw_sectors(sdev->request_queue, IPR_VSET_MAX_SECTORS); } - if (ipr_is_vset_device(res) || ipr_is_scsi_disk(res)) - sdev->allow_restart = 1; if (ipr_is_gata(res) && res->sata_port) ap = res->sata_port->ap; spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags); @@ -4833,39 +4939,15 @@ static int ipr_eh_abort(struct scsi_cmnd * scsi_cmd) /** * ipr_handle_other_interrupt - Handle "other" interrupts * @ioa_cfg: ioa config struct + * @int_reg: interrupt register * * Return value: * IRQ_NONE / IRQ_HANDLED **/ -static irqreturn_t ipr_handle_other_interrupt(struct ipr_ioa_cfg *ioa_cfg) +static irqreturn_t ipr_handle_other_interrupt(struct ipr_ioa_cfg *ioa_cfg, + volatile u32 int_reg) { irqreturn_t rc = IRQ_HANDLED; - volatile u32 int_reg, int_mask_reg; - - int_mask_reg = readl(ioa_cfg->regs.sense_interrupt_mask_reg32); - int_reg = readl(ioa_cfg->regs.sense_interrupt_reg32) & ~int_mask_reg; - - /* If an interrupt on the adapter did not occur, ignore it. - * Or in the case of SIS 64, check for a stage change interrupt. - */ - if ((int_reg & IPR_PCII_OPER_INTERRUPTS) == 0) { - if (ioa_cfg->sis64) { - int_mask_reg = readl(ioa_cfg->regs.sense_interrupt_mask_reg); - int_reg = readl(ioa_cfg->regs.sense_interrupt_reg) & ~int_mask_reg; - if (int_reg & IPR_PCII_IPL_STAGE_CHANGE) { - - /* clear stage change */ - writel(IPR_PCII_IPL_STAGE_CHANGE, ioa_cfg->regs.clr_interrupt_reg); - int_reg = readl(ioa_cfg->regs.sense_interrupt_reg) & ~int_mask_reg; - list_del(&ioa_cfg->reset_cmd->queue); - del_timer(&ioa_cfg->reset_cmd->timer); - ipr_reset_ioa_job(ioa_cfg->reset_cmd); - return IRQ_HANDLED; - } - } - - return IRQ_NONE; - } if (int_reg & IPR_PCII_IOA_TRANS_TO_OPER) { /* Mask the interrupt */ @@ -4926,7 +5008,7 @@ static irqreturn_t ipr_isr(int irq, void *devp) { struct ipr_ioa_cfg *ioa_cfg = (struct ipr_ioa_cfg *)devp; unsigned long lock_flags = 0; - volatile u32 int_reg; + volatile u32 int_reg, int_mask_reg; u32 ioasc; u16 cmd_index; int num_hrrq = 0; @@ -4941,6 +5023,33 @@ static irqreturn_t ipr_isr(int irq, void *devp) return IRQ_NONE; } + int_mask_reg = readl(ioa_cfg->regs.sense_interrupt_mask_reg32); + int_reg = readl(ioa_cfg->regs.sense_interrupt_reg32) & ~int_mask_reg; + + /* If an interrupt on the adapter did not occur, ignore it. + * Or in the case of SIS 64, check for a stage change interrupt. + */ + if (unlikely((int_reg & IPR_PCII_OPER_INTERRUPTS) == 0)) { + if (ioa_cfg->sis64) { + int_mask_reg = readl(ioa_cfg->regs.sense_interrupt_mask_reg); + int_reg = readl(ioa_cfg->regs.sense_interrupt_reg) & ~int_mask_reg; + if (int_reg & IPR_PCII_IPL_STAGE_CHANGE) { + + /* clear stage change */ + writel(IPR_PCII_IPL_STAGE_CHANGE, ioa_cfg->regs.clr_interrupt_reg); + int_reg = readl(ioa_cfg->regs.sense_interrupt_reg) & ~int_mask_reg; + list_del(&ioa_cfg->reset_cmd->queue); + del_timer(&ioa_cfg->reset_cmd->timer); + ipr_reset_ioa_job(ioa_cfg->reset_cmd); + spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags); + return IRQ_HANDLED; + } + } + + spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags); + return IRQ_NONE; + } + while (1) { ipr_cmd = NULL; @@ -4980,7 +5089,7 @@ static irqreturn_t ipr_isr(int irq, void *devp) /* Clear the PCI interrupt */ do { writel(IPR_PCII_HRRQ_UPDATED, ioa_cfg->regs.clr_interrupt_reg32); - int_reg = readl(ioa_cfg->regs.sense_interrupt_reg32); + int_reg = readl(ioa_cfg->regs.sense_interrupt_reg32) & ~int_mask_reg; } while (int_reg & IPR_PCII_HRRQ_UPDATED && num_hrrq++ < IPR_MAX_HRRQ_RETRIES); @@ -4995,7 +5104,7 @@ static irqreturn_t ipr_isr(int irq, void *devp) } if (unlikely(rc == IRQ_NONE)) - rc = ipr_handle_other_interrupt(ioa_cfg); + rc = ipr_handle_other_interrupt(ioa_cfg, int_reg); spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags); return rc; @@ -6770,7 +6879,8 @@ static int ipr_init_res_table(struct ipr_cmnd *ipr_cmd) list_move_tail(&res->queue, &ioa_cfg->used_res_q); ipr_init_res_entry(res, &cfgtew); res->add_to_ml = 1; - } + } else if (res->sdev && (ipr_is_vset_device(res) || ipr_is_scsi_disk(res))) + res->sdev->allow_restart = 1; if (found) ipr_update_res_entry(res, &cfgtew); @@ -7169,12 +7279,15 @@ static int ipr_reset_next_stage(struct ipr_cmnd *ipr_cmd) stage_time = ioa_cfg->transop_timeout; ipr_cmd->job_step = ipr_ioafp_identify_hrrq; } else if (stage == IPR_IPL_INIT_STAGE_TRANSOP) { - ipr_cmd->job_step = ipr_ioafp_identify_hrrq; - maskval = IPR_PCII_IPL_STAGE_CHANGE; - maskval = (maskval << 32) | IPR_PCII_IOA_TRANS_TO_OPER; - writeq(maskval, ioa_cfg->regs.set_interrupt_mask_reg); - int_reg = readl(ioa_cfg->regs.sense_interrupt_mask_reg); - return IPR_RC_JOB_CONTINUE; + int_reg = readl(ioa_cfg->regs.sense_interrupt_reg32); + if (int_reg & IPR_PCII_IOA_TRANS_TO_OPER) { + ipr_cmd->job_step = ipr_ioafp_identify_hrrq; + maskval = IPR_PCII_IPL_STAGE_CHANGE; + maskval = (maskval << 32) | IPR_PCII_IOA_TRANS_TO_OPER; + writeq(maskval, ioa_cfg->regs.set_interrupt_mask_reg); + int_reg = readl(ioa_cfg->regs.sense_interrupt_mask_reg); + return IPR_RC_JOB_CONTINUE; + } } ipr_cmd->timer.data = (unsigned long) ipr_cmd; @@ -7208,6 +7321,12 @@ static int ipr_reset_enable_ioa(struct ipr_cmnd *ipr_cmd) ipr_init_ioa_mem(ioa_cfg); ioa_cfg->allow_interrupts = 1; + if (ioa_cfg->sis64) { + /* Set the adapter to the correct endian mode. */ + writel(IPR_ENDIAN_SWAP_KEY, ioa_cfg->regs.endian_swap_reg); + int_reg = readl(ioa_cfg->regs.endian_swap_reg); + } + int_reg = readl(ioa_cfg->regs.sense_interrupt_reg32); if (int_reg & IPR_PCII_IOA_TRANS_TO_OPER) { @@ -7365,6 +7484,7 @@ static void ipr_get_unit_check_buffer(struct ipr_ioa_cfg *ioa_cfg) static int ipr_reset_restore_cfg_space(struct ipr_cmnd *ipr_cmd) { struct ipr_ioa_cfg *ioa_cfg = ipr_cmd->ioa_cfg; + volatile u32 int_reg; int rc; ENTER; @@ -7383,6 +7503,12 @@ static int ipr_reset_restore_cfg_space(struct ipr_cmnd *ipr_cmd) ipr_fail_all_ops(ioa_cfg); + if (ioa_cfg->sis64) { + /* Set the adapter to the correct endian mode. */ + writel(IPR_ENDIAN_SWAP_KEY, ioa_cfg->regs.endian_swap_reg); + int_reg = readl(ioa_cfg->regs.endian_swap_reg); + } + if (ioa_cfg->ioa_unit_checked) { ioa_cfg->ioa_unit_checked = 0; ipr_get_unit_check_buffer(ioa_cfg); @@ -7438,20 +7564,25 @@ static int ipr_reset_bist_done(struct ipr_cmnd *ipr_cmd) static int ipr_reset_start_bist(struct ipr_cmnd *ipr_cmd) { struct ipr_ioa_cfg *ioa_cfg = ipr_cmd->ioa_cfg; - int rc; + int rc = PCIBIOS_SUCCESSFUL; ENTER; pci_block_user_cfg_access(ioa_cfg->pdev); - rc = pci_write_config_byte(ioa_cfg->pdev, PCI_BIST, PCI_BIST_START); - if (rc != PCIBIOS_SUCCESSFUL) { - pci_unblock_user_cfg_access(ipr_cmd->ioa_cfg->pdev); - ipr_cmd->s.ioasa.hdr.ioasc = cpu_to_be32(IPR_IOASC_PCI_ACCESS_ERROR); - rc = IPR_RC_JOB_CONTINUE; - } else { + if (ioa_cfg->ipr_chip->bist_method == IPR_MMIO) + writel(IPR_UPROCI_SIS64_START_BIST, + ioa_cfg->regs.set_uproc_interrupt_reg32); + else + rc = pci_write_config_byte(ioa_cfg->pdev, PCI_BIST, PCI_BIST_START); + + if (rc == PCIBIOS_SUCCESSFUL) { ipr_cmd->job_step = ipr_reset_bist_done; ipr_reset_start_timer(ipr_cmd, IPR_WAIT_FOR_BIST_TIMEOUT); rc = IPR_RC_JOB_RETURN; + } else { + pci_unblock_user_cfg_access(ipr_cmd->ioa_cfg->pdev); + ipr_cmd->s.ioasa.hdr.ioasc = cpu_to_be32(IPR_IOASC_PCI_ACCESS_ERROR); + rc = IPR_RC_JOB_CONTINUE; } LEAVE; @@ -7547,7 +7678,7 @@ static int ipr_reset_wait_to_start_bist(struct ipr_cmnd *ipr_cmd) } /** - * ipr_reset_alert_part2 - Alert the adapter of a pending reset + * ipr_reset_alert - Alert the adapter of a pending reset * @ipr_cmd: ipr command struct * * Description: This function alerts the adapter that it will be reset. @@ -8318,6 +8449,7 @@ static void __devinit ipr_init_ioa_cfg(struct ipr_ioa_cfg *ioa_cfg, t->init_feedback_reg = base + p->init_feedback_reg; t->dump_addr_reg = base + p->dump_addr_reg; t->dump_data_reg = base + p->dump_data_reg; + t->endian_swap_reg = base + p->endian_swap_reg; } } @@ -8873,6 +9005,8 @@ static struct pci_device_id ipr_pci_table[] __devinitdata = { { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_OBSIDIAN_E, PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_57B3, 0, 0, 0 }, { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_OBSIDIAN_E, + PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_57CC, 0, 0, 0 }, + { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_OBSIDIAN_E, PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_57B7, 0, 0, IPR_USE_LONG_TRANSOP_TIMEOUT | IPR_USE_PCI_WARM_RESET }, { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_SNIPE, @@ -8891,6 +9025,8 @@ static struct pci_device_id ipr_pci_table[] __devinitdata = { PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_574D, 0, 0, 0 }, { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_CROC_FPGA_E2, PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_57B2, 0, 0, 0 }, + { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_CROC_FPGA_E2, + PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_57C4, 0, 0, 0 }, { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_CROC_ASIC_E2, PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_57B4, 0, 0, 0 }, { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_CROC_ASIC_E2, |