diff options
Diffstat (limited to 'drivers/scsi/pm8001/pm8001_ctl.c')
| -rw-r--r-- | drivers/scsi/pm8001/pm8001_ctl.c | 218 | 
1 files changed, 200 insertions, 18 deletions
diff --git a/drivers/scsi/pm8001/pm8001_ctl.c b/drivers/scsi/pm8001/pm8001_ctl.c index 45bc197bc22..a368d77b8d4 100644 --- a/drivers/scsi/pm8001/pm8001_ctl.c +++ b/drivers/scsi/pm8001/pm8001_ctl.c @@ -1,5 +1,5 @@  /* - * PMC-Sierra SPC 8001 SAS/SATA based host adapters driver + * PMC-Sierra 8001/8081/8088/8089 SAS/SATA based host adapters driver   *   * Copyright (c) 2008-2009 USI Co., Ltd.   * All rights reserved. @@ -58,8 +58,13 @@ static ssize_t pm8001_ctl_mpi_interface_rev_show(struct device *cdev,  	struct sas_ha_struct *sha = SHOST_TO_SAS_HA(shost);  	struct pm8001_hba_info *pm8001_ha = sha->lldd_ha; -	return snprintf(buf, PAGE_SIZE, "%d\n", -		pm8001_ha->main_cfg_tbl.interface_rev); +	if (pm8001_ha->chip_id == chip_8001) { +		return snprintf(buf, PAGE_SIZE, "%d\n", +			pm8001_ha->main_cfg_tbl.pm8001_tbl.interface_rev); +	} else { +		return snprintf(buf, PAGE_SIZE, "%d\n", +			pm8001_ha->main_cfg_tbl.pm80xx_tbl.interface_rev); +	}  }  static  DEVICE_ATTR(interface_rev, S_IRUGO, pm8001_ctl_mpi_interface_rev_show, NULL); @@ -78,11 +83,19 @@ static ssize_t pm8001_ctl_fw_version_show(struct device *cdev,  	struct sas_ha_struct *sha = SHOST_TO_SAS_HA(shost);  	struct pm8001_hba_info *pm8001_ha = sha->lldd_ha; -	return snprintf(buf, PAGE_SIZE, "%02x.%02x.%02x.%02x\n", -		       (u8)(pm8001_ha->main_cfg_tbl.firmware_rev >> 24), -		       (u8)(pm8001_ha->main_cfg_tbl.firmware_rev >> 16), -		       (u8)(pm8001_ha->main_cfg_tbl.firmware_rev >> 8), -		       (u8)(pm8001_ha->main_cfg_tbl.firmware_rev)); +	if (pm8001_ha->chip_id == chip_8001) { +		return snprintf(buf, PAGE_SIZE, "%02x.%02x.%02x.%02x\n", +		(u8)(pm8001_ha->main_cfg_tbl.pm8001_tbl.firmware_rev >> 24), +		(u8)(pm8001_ha->main_cfg_tbl.pm8001_tbl.firmware_rev >> 16), +		(u8)(pm8001_ha->main_cfg_tbl.pm8001_tbl.firmware_rev >> 8), +		(u8)(pm8001_ha->main_cfg_tbl.pm8001_tbl.firmware_rev)); +	} else { +		return snprintf(buf, PAGE_SIZE, "%02x.%02x.%02x.%02x\n", +		(u8)(pm8001_ha->main_cfg_tbl.pm80xx_tbl.firmware_rev >> 24), +		(u8)(pm8001_ha->main_cfg_tbl.pm80xx_tbl.firmware_rev >> 16), +		(u8)(pm8001_ha->main_cfg_tbl.pm80xx_tbl.firmware_rev >> 8), +		(u8)(pm8001_ha->main_cfg_tbl.pm80xx_tbl.firmware_rev)); +	}  }  static DEVICE_ATTR(fw_version, S_IRUGO, pm8001_ctl_fw_version_show, NULL);  /** @@ -99,8 +112,13 @@ static ssize_t pm8001_ctl_max_out_io_show(struct device *cdev,  	struct sas_ha_struct *sha = SHOST_TO_SAS_HA(shost);  	struct pm8001_hba_info *pm8001_ha = sha->lldd_ha; -	return snprintf(buf, PAGE_SIZE, "%d\n", -			pm8001_ha->main_cfg_tbl.max_out_io); +	if (pm8001_ha->chip_id == chip_8001) { +		return snprintf(buf, PAGE_SIZE, "%d\n", +			pm8001_ha->main_cfg_tbl.pm8001_tbl.max_out_io); +	} else { +		return snprintf(buf, PAGE_SIZE, "%d\n", +			pm8001_ha->main_cfg_tbl.pm80xx_tbl.max_out_io); +	}  }  static DEVICE_ATTR(max_out_io, S_IRUGO, pm8001_ctl_max_out_io_show, NULL);  /** @@ -117,8 +135,15 @@ static ssize_t pm8001_ctl_max_devices_show(struct device *cdev,  	struct sas_ha_struct *sha = SHOST_TO_SAS_HA(shost);  	struct pm8001_hba_info *pm8001_ha = sha->lldd_ha; -	return snprintf(buf, PAGE_SIZE, "%04d\n", -			(u16)(pm8001_ha->main_cfg_tbl.max_sgl >> 16)); +	if (pm8001_ha->chip_id == chip_8001) { +		return snprintf(buf, PAGE_SIZE, "%04d\n", +			(u16)(pm8001_ha->main_cfg_tbl.pm8001_tbl.max_sgl >> 16) +			); +	} else { +		return snprintf(buf, PAGE_SIZE, "%04d\n", +			(u16)(pm8001_ha->main_cfg_tbl.pm80xx_tbl.max_sgl >> 16) +			); +	}  }  static DEVICE_ATTR(max_devices, S_IRUGO, pm8001_ctl_max_devices_show, NULL);  /** @@ -136,8 +161,15 @@ static ssize_t pm8001_ctl_max_sg_list_show(struct device *cdev,  	struct sas_ha_struct *sha = SHOST_TO_SAS_HA(shost);  	struct pm8001_hba_info *pm8001_ha = sha->lldd_ha; -	return snprintf(buf, PAGE_SIZE, "%04d\n", -			pm8001_ha->main_cfg_tbl.max_sgl & 0x0000FFFF); +	if (pm8001_ha->chip_id == chip_8001) { +		return snprintf(buf, PAGE_SIZE, "%04d\n", +			pm8001_ha->main_cfg_tbl.pm8001_tbl.max_sgl & 0x0000FFFF +			); +	} else { +		return snprintf(buf, PAGE_SIZE, "%04d\n", +			pm8001_ha->main_cfg_tbl.pm80xx_tbl.max_sgl & 0x0000FFFF +			); +	}  }  static DEVICE_ATTR(max_sg_list, S_IRUGO, pm8001_ctl_max_sg_list_show, NULL); @@ -173,7 +205,14 @@ static ssize_t pm8001_ctl_sas_spec_support_show(struct device *cdev,  	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; -	mode = (pm8001_ha->main_cfg_tbl.ctrl_cap_flag & 0xfe000000)>>25; +	/* fe000000 means supports SAS2.1 */ +	if (pm8001_ha->chip_id == chip_8001) +		mode = (pm8001_ha->main_cfg_tbl.pm8001_tbl.ctrl_cap_flag & +							0xfe000000)>>25; +	else +		/* fe000000 means supports SAS2.1 */ +		mode = (pm8001_ha->main_cfg_tbl.pm80xx_tbl.ctrl_cap_flag & +							0xfe000000)>>25;  	return show_sas_spec_support_status(mode, buf);  }  static DEVICE_ATTR(sas_spec_support, S_IRUGO, @@ -270,6 +309,106 @@ static ssize_t pm8001_ctl_aap_log_show(struct device *cdev,  }  static DEVICE_ATTR(aap_log, S_IRUGO, pm8001_ctl_aap_log_show, NULL);  /** + * pm8001_ctl_ib_queue_log_show - Out bound Queue log + * @cdev:pointer to embedded class device + * @buf: the buffer returned + * A sysfs 'read-only' shost attribute. + */ +static ssize_t pm8001_ctl_ib_queue_log_show(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; +	int offset; +	char *str = buf; +	int start = 0; +#define IB_MEMMAP(c)	\ +		(*(u32 *)((u8 *)pm8001_ha->	\ +		memoryMap.region[IB].virt_ptr +	\ +		pm8001_ha->evtlog_ib_offset + (c))) + +	for (offset = 0; offset < IB_OB_READ_TIMES; offset++) { +		str += sprintf(str, "0x%08x\n", IB_MEMMAP(start)); +		start = start + 4; +	} +	pm8001_ha->evtlog_ib_offset += SYSFS_OFFSET; +	if (((pm8001_ha->evtlog_ib_offset) % (PM80XX_IB_OB_QUEUE_SIZE)) == 0) +		pm8001_ha->evtlog_ib_offset = 0; + +	return str - buf; +} + +static DEVICE_ATTR(ib_log, S_IRUGO, pm8001_ctl_ib_queue_log_show, NULL); +/** + * pm8001_ctl_ob_queue_log_show - Out bound Queue log + * @cdev:pointer to embedded class device + * @buf: the buffer returned + * A sysfs 'read-only' shost attribute. + */ + +static ssize_t pm8001_ctl_ob_queue_log_show(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; +	int offset; +	char *str = buf; +	int start = 0; +#define OB_MEMMAP(c)	\ +		(*(u32 *)((u8 *)pm8001_ha->	\ +		memoryMap.region[OB].virt_ptr +	\ +		pm8001_ha->evtlog_ob_offset + (c))) + +	for (offset = 0; offset < IB_OB_READ_TIMES; offset++) { +		str += sprintf(str, "0x%08x\n", OB_MEMMAP(start)); +		start = start + 4; +	} +	pm8001_ha->evtlog_ob_offset += SYSFS_OFFSET; +	if (((pm8001_ha->evtlog_ob_offset) % (PM80XX_IB_OB_QUEUE_SIZE)) == 0) +		pm8001_ha->evtlog_ob_offset = 0; + +	return str - buf; +} +static DEVICE_ATTR(ob_log, S_IRUGO, pm8001_ctl_ob_queue_log_show, NULL); +/** + * pm8001_ctl_bios_version_show - Bios version Display + * @cdev:pointer to embedded class device + * @buf:the buffer returned + * A sysfs 'read-only' shost attribute. + */ +static ssize_t pm8001_ctl_bios_version_show(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; +	char *str = buf; +	void *virt_addr; +	int bios_index; +	DECLARE_COMPLETION_ONSTACK(completion); +	struct pm8001_ioctl_payload payload; + +	pm8001_ha->nvmd_completion = &completion; +	payload.minor_function = 7; +	payload.offset = 0; +	payload.length = 4096; +	payload.func_specific = kzalloc(4096, GFP_KERNEL); +	if (!payload.func_specific) +		return -ENOMEM; +	PM8001_CHIP_DISP->get_nvmd_req(pm8001_ha, &payload); +	wait_for_completion(&completion); +	virt_addr = pm8001_ha->memoryMap.region[NVMD].virt_ptr; +	for (bios_index = BIOSOFFSET; bios_index < BIOS_OFFSET_LIMIT; +		bios_index++) +		str += sprintf(str, "%c", +			*((u8 *)((u8 *)virt_addr+bios_index))); +	kfree(payload.func_specific); +	return str - buf; +} +static DEVICE_ATTR(bios_version, S_IRUGO, pm8001_ctl_bios_version_show, NULL); +/**   * pm8001_ctl_aap_log_show - IOP event log   * @cdev: pointer to embedded class device   * @buf: the buffer returned @@ -305,6 +444,43 @@ static ssize_t pm8001_ctl_iop_log_show(struct device *cdev,  }  static DEVICE_ATTR(iop_log, S_IRUGO, pm8001_ctl_iop_log_show, NULL); +/** + ** pm8001_ctl_fatal_log_show - fatal error logging + ** @cdev:pointer to embedded class device + ** @buf: the buffer returned + ** + ** A sysfs 'read-only' shost attribute. + **/ + +static ssize_t pm8001_ctl_fatal_log_show(struct device *cdev, +	struct device_attribute *attr, char *buf) +{ +	ssize_t count; + +	count = pm80xx_get_fatal_dump(cdev, attr, buf); +	return count; +} + +static DEVICE_ATTR(fatal_log, S_IRUGO, pm8001_ctl_fatal_log_show, NULL); + + +/** + ** pm8001_ctl_gsm_log_show - gsm dump collection + ** @cdev:pointer to embedded class device + ** @buf: the buffer returned + **A sysfs 'read-only' shost attribute. + **/ +static ssize_t pm8001_ctl_gsm_log_show(struct device *cdev, +	struct device_attribute *attr, char *buf) +{ +	ssize_t count; + +	count = pm8001_get_gsm_dump(cdev, SYSFS_OFFSET, buf); +	return count; +} + +static DEVICE_ATTR(gsm_log, S_IRUGO, pm8001_ctl_gsm_log_show, NULL); +  #define FLASH_CMD_NONE      0x00  #define FLASH_CMD_UPDATE    0x01  #define FLASH_CMD_SET_NVMD    0x02 @@ -361,10 +537,11 @@ static int pm8001_set_nvmd(struct pm8001_hba_info *pm8001_ha)  		goto out;  	}  	payload = (struct pm8001_ioctl_payload *)ioctlbuffer; -	memcpy((u8 *)payload->func_specific, (u8 *)pm8001_ha->fw_image->data, +	memcpy((u8 *)&payload->func_specific, (u8 *)pm8001_ha->fw_image->data,  				pm8001_ha->fw_image->size);  	payload->length = pm8001_ha->fw_image->size;  	payload->id = 0; +	payload->minor_function = 0x1;  	pm8001_ha->nvmd_completion = &completion;  	ret = PM8001_CHIP_DISP->set_nvmd_req(pm8001_ha, payload);  	wait_for_completion(&completion); @@ -411,7 +588,7 @@ static int pm8001_update_flash(struct pm8001_hba_info *pm8001_ha)  			payload->length = 1024*16;  			payload->id = 0;  			fwControl = -			      (struct fw_control_info *)payload->func_specific; +			      (struct fw_control_info *)&payload->func_specific;  			fwControl->len = IOCTL_BUF_SIZE;   /* IN */  			fwControl->size = partitionSize + HEADER_LEN;/* IN */  			fwControl->retcode = 0;/* OUT */ @@ -555,7 +732,7 @@ static ssize_t pm8001_show_update_fw(struct device *cdev,  			flash_error_table[i].reason);  } -static DEVICE_ATTR(update_fw, S_IRUGO|S_IWUGO, +static DEVICE_ATTR(update_fw, S_IRUGO|S_IWUSR|S_IWGRP,  	pm8001_show_update_fw, pm8001_store_update_fw);  struct device_attribute *pm8001_host_attrs[] = {  	&dev_attr_interface_rev, @@ -563,12 +740,17 @@ struct device_attribute *pm8001_host_attrs[] = {  	&dev_attr_update_fw,  	&dev_attr_aap_log,  	&dev_attr_iop_log, +	&dev_attr_fatal_log, +	&dev_attr_gsm_log,  	&dev_attr_max_out_io,  	&dev_attr_max_devices,  	&dev_attr_max_sg_list,  	&dev_attr_sas_spec_support,  	&dev_attr_logging_level,  	&dev_attr_host_sas_address, +	&dev_attr_bios_version, +	&dev_attr_ib_log, +	&dev_attr_ob_log,  	NULL,  };  | 
