int pm80xx_bar4_shift(struct pm8001_hba_info *pm8001_ha, u32 shift_value) { u32 reg_val; unsigned long start; pm8001_cw32(pm8001_ha, 0, MEMBASE_II_SHIFT_REGISTER, shift_value); /* confirm the setting is written */ start = jiffies + HZ; /* 1 sec */ do { reg_val = pm8001_cr32(pm8001_ha, 0, MEMBASE_II_SHIFT_REGISTER); } while ((reg_val != shift_value) && time_before(jiffies, start)); if (reg_val != shift_value) { PM8001_FAIL_DBG(pm8001_ha, pm8001_printk("TIMEOUT:MEMBASE_II_SHIFT_REGISTER" " = 0x%x\n", reg_val)); return -1; } return 0; }
static ssize_t pm8001_store_update_fw(struct device *cdev, struct device_attribute *attr, const char *buf, size_t count) { struct Scsi_Host *shost = class_to_shost(cdev); struct sas_ha_struct *sha = SHOST_TO_SAS_HA(shost); struct pm8001_hba_info *pm8001_ha = sha->lldd_ha; char *cmd_ptr, *filename_ptr; int res, i; int flash_command = FLASH_CMD_NONE; int err = 0; if (!capable(CAP_SYS_ADMIN)) return -EACCES; cmd_ptr = kzalloc(count*2, GFP_KERNEL); if (!cmd_ptr) { err = FAIL_OUT_MEMORY; goto out; } filename_ptr = cmd_ptr + count; res = sscanf(buf, "%s %s", cmd_ptr, filename_ptr); if (res != 2) { err = FAIL_PARAMETERS; goto out1; } for (i = 0; flash_command_table[i].code != FLASH_CMD_NONE; i++) { if (!memcmp(flash_command_table[i].command, cmd_ptr, strlen(cmd_ptr))) { flash_command = flash_command_table[i].code; break; } } if (flash_command == FLASH_CMD_NONE) { err = FAIL_PARAMETERS; goto out1; } if (pm8001_ha->fw_status == FLASH_IN_PROGRESS) { err = FLASH_IN_PROGRESS; goto out1; } err = request_firmware(&pm8001_ha->fw_image, filename_ptr, pm8001_ha->dev); if (err) { PM8001_FAIL_DBG(pm8001_ha, pm8001_printk("Failed to load firmware image file %s," " error %d\n", filename_ptr, err)); err = FAIL_OPEN_BIOS_FILE; goto out1; } switch (flash_command) { case FLASH_CMD_UPDATE: pm8001_ha->fw_status = FLASH_IN_PROGRESS; err = pm8001_update_flash(pm8001_ha); break; case FLASH_CMD_SET_NVMD: pm8001_ha->fw_status = FLASH_IN_PROGRESS; err = pm8001_set_nvmd(pm8001_ha); break; default: pm8001_ha->fw_status = FAIL_PARAMETERS; err = FAIL_PARAMETERS; break; } release_firmware(pm8001_ha->fw_image); out1: kfree(cmd_ptr); out: pm8001_ha->fw_status = err; if (!err) return count; else return -err; }
ssize_t pm80xx_get_fatal_dump(struct device *cdev, struct device_attribute *attr, char *buf) { struct Scsi_Host *shost = class_to_shost(cdev); struct sas_ha_struct *sha = SHOST_TO_SAS_HA(shost); struct pm8001_hba_info *pm8001_ha = sha->lldd_ha; void __iomem *fatal_table_address = pm8001_ha->fatal_tbl_addr; u32 accum_len , reg_val, index, *temp; unsigned long start; u8 *direct_data; char *fatal_error_data = buf; pm8001_ha->forensic_info.data_buf.direct_data = buf; if (pm8001_ha->chip_id == chip_8001) { pm8001_ha->forensic_info.data_buf.direct_data += sprintf(pm8001_ha->forensic_info.data_buf.direct_data, "Not supported for SPC controller"); return (char *)pm8001_ha->forensic_info.data_buf.direct_data - (char *)buf; } if (pm8001_ha->forensic_info.data_buf.direct_offset == 0) { PM8001_IO_DBG(pm8001_ha, pm8001_printk("forensic_info TYPE_NON_FATAL..............\n")); direct_data = (u8 *)fatal_error_data; pm8001_ha->forensic_info.data_type = TYPE_NON_FATAL; pm8001_ha->forensic_info.data_buf.direct_len = SYSFS_OFFSET; pm8001_ha->forensic_info.data_buf.read_len = 0; pm8001_ha->forensic_info.data_buf.direct_data = direct_data; /* start to get data */ /* Program the MEMBASE II Shifting Register with 0x00.*/ pm8001_cw32(pm8001_ha, 0, MEMBASE_II_SHIFT_REGISTER, pm8001_ha->fatal_forensic_shift_offset); pm8001_ha->forensic_last_offset = 0; pm8001_ha->forensic_fatal_step = 0; pm8001_ha->fatal_bar_loc = 0; } /* Read until accum_len is retrived */ accum_len = pm8001_mr32(fatal_table_address, MPI_FATAL_EDUMP_TABLE_ACCUM_LEN); PM8001_IO_DBG(pm8001_ha, pm8001_printk("accum_len 0x%x\n", accum_len)); if (accum_len == 0xFFFFFFFF) { PM8001_IO_DBG(pm8001_ha, pm8001_printk("Possible PCI issue 0x%x not expected\n", accum_len)); return -EIO; } if (accum_len == 0 || accum_len >= 0x100000) { pm8001_ha->forensic_info.data_buf.direct_data += sprintf(pm8001_ha->forensic_info.data_buf.direct_data, "%08x ", 0xFFFFFFFF); return (char *)pm8001_ha->forensic_info.data_buf.direct_data - (char *)buf; } temp = (u32 *)pm8001_ha->memoryMap.region[FORENSIC_MEM].virt_ptr; if (pm8001_ha->forensic_fatal_step == 0) { moreData: if (pm8001_ha->forensic_info.data_buf.direct_data) { /* Data is in bar, copy to host memory */ pm80xx_pci_mem_copy(pm8001_ha, pm8001_ha->fatal_bar_loc, pm8001_ha->memoryMap.region[FORENSIC_MEM].virt_ptr, pm8001_ha->forensic_info.data_buf.direct_len , 1); } pm8001_ha->fatal_bar_loc += pm8001_ha->forensic_info.data_buf.direct_len; pm8001_ha->forensic_info.data_buf.direct_offset += pm8001_ha->forensic_info.data_buf.direct_len; pm8001_ha->forensic_last_offset += pm8001_ha->forensic_info.data_buf.direct_len; pm8001_ha->forensic_info.data_buf.read_len = pm8001_ha->forensic_info.data_buf.direct_len; if (pm8001_ha->forensic_last_offset >= accum_len) { pm8001_ha->forensic_info.data_buf.direct_data += sprintf(pm8001_ha->forensic_info.data_buf.direct_data, "%08x ", 3); for (index = 0; index < (SYSFS_OFFSET / 4); index++) { pm8001_ha->forensic_info.data_buf.direct_data += sprintf(pm8001_ha-> forensic_info.data_buf.direct_data, "%08x ", *(temp + index)); } pm8001_ha->fatal_bar_loc = 0; pm8001_ha->forensic_fatal_step = 1; pm8001_ha->fatal_forensic_shift_offset = 0; pm8001_ha->forensic_last_offset = 0; return (char *)pm8001_ha-> forensic_info.data_buf.direct_data - (char *)buf; } if (pm8001_ha->fatal_bar_loc < (64 * 1024)) { pm8001_ha->forensic_info.data_buf.direct_data += sprintf(pm8001_ha-> forensic_info.data_buf.direct_data, "%08x ", 2); for (index = 0; index < (SYSFS_OFFSET / 4); index++) { pm8001_ha->forensic_info.data_buf.direct_data += sprintf(pm8001_ha-> forensic_info.data_buf.direct_data, "%08x ", *(temp + index)); } return (char *)pm8001_ha-> forensic_info.data_buf.direct_data - (char *)buf; } /* Increment the MEMBASE II Shifting Register value by 0x100.*/ pm8001_ha->forensic_info.data_buf.direct_data += sprintf(pm8001_ha->forensic_info.data_buf.direct_data, "%08x ", 2); for (index = 0; index < 256; index++) { pm8001_ha->forensic_info.data_buf.direct_data += sprintf(pm8001_ha-> forensic_info.data_buf.direct_data, "%08x ", *(temp + index)); } pm8001_ha->fatal_forensic_shift_offset += 0x100; pm8001_cw32(pm8001_ha, 0, MEMBASE_II_SHIFT_REGISTER, pm8001_ha->fatal_forensic_shift_offset); pm8001_ha->fatal_bar_loc = 0; return (char *)pm8001_ha->forensic_info.data_buf.direct_data - (char *)buf; } if (pm8001_ha->forensic_fatal_step == 1) { pm8001_ha->fatal_forensic_shift_offset = 0; /* Read 64K of the debug data. */ pm8001_cw32(pm8001_ha, 0, MEMBASE_II_SHIFT_REGISTER, pm8001_ha->fatal_forensic_shift_offset); pm8001_mw32(fatal_table_address, MPI_FATAL_EDUMP_TABLE_HANDSHAKE, MPI_FATAL_EDUMP_HANDSHAKE_RDY); /* Poll FDDHSHK until clear */ start = jiffies + (2 * HZ); /* 2 sec */ do { reg_val = pm8001_mr32(fatal_table_address, MPI_FATAL_EDUMP_TABLE_HANDSHAKE); } while ((reg_val) && time_before(jiffies, start)); if (reg_val != 0) { PM8001_FAIL_DBG(pm8001_ha, pm8001_printk("TIMEOUT:MEMBASE_II_SHIFT_REGISTER" " = 0x%x\n", reg_val)); return -EIO; } /* Read the next 64K of the debug data. */ pm8001_ha->forensic_fatal_step = 0; if (pm8001_mr32(fatal_table_address, MPI_FATAL_EDUMP_TABLE_STATUS) != MPI_FATAL_EDUMP_TABLE_STAT_NF_SUCCESS_DONE) { pm8001_mw32(fatal_table_address, MPI_FATAL_EDUMP_TABLE_HANDSHAKE, 0); goto moreData; } else { pm8001_ha->forensic_info.data_buf.direct_data += sprintf(pm8001_ha-> forensic_info.data_buf.direct_data, "%08x ", 4); pm8001_ha->forensic_info.data_buf.read_len = 0xFFFFFFFF; pm8001_ha->forensic_info.data_buf.direct_len = 0; pm8001_ha->forensic_info.data_buf.direct_offset = 0; pm8001_ha->forensic_info.data_buf.read_len = 0; } } return (char *)pm8001_ha->forensic_info.data_buf.direct_data - (char *)buf; }