Beispiel #1
0
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;
}
Beispiel #3
0
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;
}