mirror of
				git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
				synced 2025-09-04 20:19:47 +08:00 
			
		
		
		
	scsi: qla2xxx: Add support for setting port speed
This patch adds sysfs node 1. There is a new sysfs node port_speed 2. The possible values are 2(Auto neg), 8, 16, 32 3. A value outside of the above defaults to Auto neg 4. Any update to the setting causes a link toggle 5. This feature is currently only for ISP27xx Signed-off-by: Anil Gurumurthy <agurumurthy@marvell.com> Signed-off-by: Quinn Tran <qtran@marvell.com> Signed-off-by: Himanshu Madhani <hmadhani@marvell.com> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
This commit is contained in:
		
							parent
							
								
									192c4e9b93
								
							
						
					
					
						commit
						4910b524ac
					
				| @ -1632,6 +1632,92 @@ qla2x00_max_speed_sup_show(struct device *dev, struct device_attribute *attr, | ||||
| 	    ha->max_speed_sup ? "32Gps" : "16Gps"); | ||||
| } | ||||
| 
 | ||||
| static ssize_t | ||||
| qla2x00_port_speed_store(struct device *dev, struct device_attribute *attr, | ||||
|     const char *buf, size_t count) | ||||
| { | ||||
| 	struct scsi_qla_host *vha = shost_priv(dev_to_shost(dev)); | ||||
| 	ulong type, speed; | ||||
| 	int oldspeed, rval; | ||||
| 	int mode = QLA_SET_DATA_RATE_LR; | ||||
| 	struct qla_hw_data *ha = vha->hw; | ||||
| 
 | ||||
| 	if (!IS_QLA27XX(vha->hw)) { | ||||
| 		ql_log(ql_log_warn, vha, 0x70d8, | ||||
| 		    "Speed setting not supported \n"); | ||||
| 		return -EINVAL; | ||||
| 	} | ||||
| 
 | ||||
| 	rval = kstrtol(buf, 10, &type); | ||||
| 	speed = type; | ||||
| 	if (type == 40 || type == 80 || type == 160 || | ||||
| 	    type == 320) { | ||||
| 		ql_dbg(ql_dbg_user, vha, 0x70d9, | ||||
| 		    "Setting will be affected after a loss of sync\n"); | ||||
| 		type = type/10; | ||||
| 		mode = QLA_SET_DATA_RATE_NOLR; | ||||
| 	} | ||||
| 
 | ||||
| 	oldspeed = ha->set_data_rate; | ||||
| 
 | ||||
| 	switch (type) { | ||||
| 	case 0: | ||||
| 		ha->set_data_rate = PORT_SPEED_AUTO; | ||||
| 		break; | ||||
| 	case 4: | ||||
| 		ha->set_data_rate = PORT_SPEED_4GB; | ||||
| 		break; | ||||
| 	case 8: | ||||
| 		ha->set_data_rate = PORT_SPEED_8GB; | ||||
| 		break; | ||||
| 	case 16: | ||||
| 		ha->set_data_rate = PORT_SPEED_16GB; | ||||
| 		break; | ||||
| 	case 32: | ||||
| 		ha->set_data_rate = PORT_SPEED_32GB; | ||||
| 		break; | ||||
| 	default: | ||||
| 		ql_log(ql_log_warn, vha, 0x1199, | ||||
| 		    "Unrecognized speed setting:%lx. Setting Autoneg\n", | ||||
| 		    speed); | ||||
| 		ha->set_data_rate = PORT_SPEED_AUTO; | ||||
| 	} | ||||
| 
 | ||||
| 	if (qla2x00_chip_is_down(vha) || (oldspeed == ha->set_data_rate)) | ||||
| 		return -EINVAL; | ||||
| 
 | ||||
| 	ql_log(ql_log_info, vha, 0x70da, | ||||
| 	    "Setting speed to %lx Gbps \n", type); | ||||
| 
 | ||||
| 	rval = qla2x00_set_data_rate(vha, mode); | ||||
| 	if (rval != QLA_SUCCESS) | ||||
| 		return -EIO; | ||||
| 
 | ||||
| 	return strlen(buf); | ||||
| } | ||||
| 
 | ||||
| static ssize_t | ||||
| qla2x00_port_speed_show(struct device *dev, struct device_attribute *attr, | ||||
|     char *buf) | ||||
| { | ||||
| 	struct scsi_qla_host *vha = shost_priv(dev_to_shost(dev)); | ||||
| 	struct qla_hw_data *ha = vha->hw; | ||||
| 	ssize_t rval; | ||||
| 	char *spd[7] = {"0", "0", "0", "4", "8", "16", "32"}; | ||||
| 
 | ||||
| 	rval = qla2x00_get_data_rate(vha); | ||||
| 	if (rval != QLA_SUCCESS) { | ||||
| 		ql_log(ql_log_warn, vha, 0x70db, | ||||
| 		    "Unable to get port speed rval:%zd\n", rval); | ||||
| 		return -EINVAL; | ||||
| 	} | ||||
| 
 | ||||
| 	ql_log(ql_log_info, vha, 0x70d6, | ||||
| 	    "port speed:%d\n", ha->link_data_rate); | ||||
| 
 | ||||
| 	return scnprintf(buf, PAGE_SIZE, "%s\n", spd[ha->link_data_rate]); | ||||
| } | ||||
| 
 | ||||
| /* ----- */ | ||||
| 
 | ||||
| static ssize_t | ||||
| @ -2128,6 +2214,8 @@ static DEVICE_ATTR_RW(ql2xexchoffld); | ||||
| static DEVICE_ATTR_RW(ql2xiniexchg); | ||||
| static DEVICE_ATTR(dif_bundle_statistics, 0444, | ||||
|     qla2x00_dif_bundle_statistics_show, NULL); | ||||
| static DEVICE_ATTR(port_speed, 0644, qla2x00_port_speed_show, | ||||
|     qla2x00_port_speed_store); | ||||
| 
 | ||||
| 
 | ||||
| struct device_attribute *qla2x00_host_attrs[] = { | ||||
| @ -2167,6 +2255,7 @@ struct device_attribute *qla2x00_host_attrs[] = { | ||||
| 	&dev_attr_max_speed_sup, | ||||
| 	&dev_attr_zio_threshold, | ||||
| 	&dev_attr_dif_bundle_statistics, | ||||
| 	&dev_attr_port_speed, | ||||
| 	NULL, /* reserve for qlini_mode */ | ||||
| 	NULL, /* reserve for ql2xiniexchg */ | ||||
| 	NULL, /* reserve for ql2xexchoffld */ | ||||
|  | ||||
| @ -3698,12 +3698,14 @@ struct qla_hw_data { | ||||
| #define PORT_SPEED_UNKNOWN 0xFFFF | ||||
| #define PORT_SPEED_1GB  0x00 | ||||
| #define PORT_SPEED_2GB  0x01 | ||||
| #define PORT_SPEED_AUTO 0x02 | ||||
| #define PORT_SPEED_4GB  0x03 | ||||
| #define PORT_SPEED_8GB  0x04 | ||||
| #define PORT_SPEED_16GB 0x05 | ||||
| #define PORT_SPEED_32GB 0x06 | ||||
| #define PORT_SPEED_10GB	0x13 | ||||
| 	uint16_t	link_data_rate;         /* F/W operating speed */ | ||||
| 	uint16_t	set_data_rate;		/* Set by user */ | ||||
| 
 | ||||
| 	uint8_t		current_topology; | ||||
| 	uint8_t		prev_topology; | ||||
| @ -4232,6 +4234,10 @@ struct qla_hw_data { | ||||
| #define FW_ABILITY_MAX_SPEED(ha)	\ | ||||
| 	(ha->fw_ability_mask & FW_ABILITY_MAX_SPEED_MASK) | ||||
| 
 | ||||
| #define QLA_GET_DATA_RATE	0 | ||||
| #define QLA_SET_DATA_RATE_NOLR	1 | ||||
| #define QLA_SET_DATA_RATE_LR	2 /* Set speed and initiate LR */ | ||||
| 
 | ||||
| /*
 | ||||
|  * Qlogic scsi host structure | ||||
|  */ | ||||
|  | ||||
| @ -899,5 +899,6 @@ void qlt_update_host_map(struct scsi_qla_host *, port_id_t); | ||||
| void qlt_remove_target_resources(struct qla_hw_data *); | ||||
| void qlt_clr_qp_table(struct scsi_qla_host *vha); | ||||
| void qlt_set_mode(struct scsi_qla_host *); | ||||
| int qla2x00_set_data_rate(scsi_qla_host_t *vha, uint16_t mode); | ||||
| 
 | ||||
| #endif /* _QLA_GBL_H */ | ||||
|  | ||||
| @ -3882,8 +3882,17 @@ qla24xx_config_rings(struct scsi_qla_host *vha) | ||||
| 		WRT_REG_DWORD(®->isp24.rsp_q_in, 0); | ||||
| 		WRT_REG_DWORD(®->isp24.rsp_q_out, 0); | ||||
| 	} | ||||
| 
 | ||||
| 	qlt_24xx_config_rings(vha); | ||||
| 
 | ||||
| 	/* If the user has configured the speed, set it here */ | ||||
| 	if (ha->set_data_rate) { | ||||
| 		ql_dbg(ql_dbg_init, vha, 0x00fd, | ||||
| 		    "Speed set by user : %s Gbps \n", | ||||
| 		    qla2x00_get_link_speed_str(ha, ha->set_data_rate)); | ||||
| 		icb->firmware_options_3 = (ha->set_data_rate << 13); | ||||
| 	} | ||||
| 
 | ||||
| 	/* PCI posting */ | ||||
| 	RD_REG_DWORD(&ioreg->hccr); | ||||
| } | ||||
|  | ||||
| @ -5250,6 +5250,66 @@ qla81xx_write_mpi_register(scsi_qla_host_t *vha, uint16_t *mb) | ||||
| 	return rval; | ||||
| } | ||||
| 
 | ||||
| /* Set the specified data rate */ | ||||
| int | ||||
| qla2x00_set_data_rate(scsi_qla_host_t *vha, uint16_t mode) | ||||
| { | ||||
| 	int rval; | ||||
| 	mbx_cmd_t mc; | ||||
| 	mbx_cmd_t *mcp = &mc; | ||||
| 	struct qla_hw_data *ha = vha->hw; | ||||
| 	uint16_t val; | ||||
| 
 | ||||
| 	ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1106, | ||||
| 	    "Entered %s speed:0x%x mode:0x%x.\n", __func__, ha->set_data_rate, | ||||
| 	    mode); | ||||
| 
 | ||||
| 	if (!IS_FWI2_CAPABLE(ha)) | ||||
| 		return QLA_FUNCTION_FAILED; | ||||
| 
 | ||||
| 	memset(mcp, 0, sizeof(*mcp)); | ||||
| 	switch (ha->set_data_rate) { | ||||
| 	case PORT_SPEED_AUTO: | ||||
| 	case PORT_SPEED_4GB: | ||||
| 	case PORT_SPEED_8GB: | ||||
| 	case PORT_SPEED_16GB: | ||||
| 	case PORT_SPEED_32GB: | ||||
| 		val = ha->set_data_rate; | ||||
| 		break; | ||||
| 	default: | ||||
| 		ql_log(ql_log_warn, vha, 0x1199, | ||||
| 		    "Unrecognized speed setting:%d. Setting Autoneg\n", | ||||
| 		    ha->set_data_rate); | ||||
| 		val = ha->set_data_rate = PORT_SPEED_AUTO; | ||||
| 		break; | ||||
| 	} | ||||
| 
 | ||||
| 	mcp->mb[0] = MBC_DATA_RATE; | ||||
| 	mcp->mb[1] = mode; | ||||
| 	mcp->mb[2] = val; | ||||
| 
 | ||||
| 	mcp->out_mb = MBX_2|MBX_1|MBX_0; | ||||
| 	mcp->in_mb = MBX_2|MBX_1|MBX_0; | ||||
| 	if (IS_QLA83XX(ha) || IS_QLA27XX(ha)) | ||||
| 		mcp->in_mb |= MBX_4|MBX_3; | ||||
| 	mcp->tov = MBX_TOV_SECONDS; | ||||
| 	mcp->flags = 0; | ||||
| 	rval = qla2x00_mailbox_command(vha, mcp); | ||||
| 	if (rval != QLA_SUCCESS) { | ||||
| 		ql_dbg(ql_dbg_mbx, vha, 0x1107, | ||||
| 		    "Failed=%x mb[0]=%x.\n", rval, mcp->mb[0]); | ||||
| 	} else { | ||||
| 		if (mcp->mb[1] != 0x7) | ||||
| 			ql_dbg(ql_dbg_mbx, vha, 0x1179, | ||||
| 				"Speed set:0x%x\n", mcp->mb[1]); | ||||
| 
 | ||||
| 		ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1108, | ||||
| 		    "Done %s.\n", __func__); | ||||
| 	} | ||||
| 
 | ||||
| 	return rval; | ||||
| } | ||||
| 
 | ||||
| int | ||||
| qla2x00_get_data_rate(scsi_qla_host_t *vha) | ||||
| { | ||||
| @ -5265,7 +5325,7 @@ qla2x00_get_data_rate(scsi_qla_host_t *vha) | ||||
| 		return QLA_FUNCTION_FAILED; | ||||
| 
 | ||||
| 	mcp->mb[0] = MBC_DATA_RATE; | ||||
| 	mcp->mb[1] = 0; | ||||
| 	mcp->mb[1] = QLA_GET_DATA_RATE; | ||||
| 	mcp->out_mb = MBX_1|MBX_0; | ||||
| 	mcp->in_mb = MBX_2|MBX_1|MBX_0; | ||||
| 	if (IS_QLA83XX(ha) || IS_QLA27XX(ha)) | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user
	 Anil Gurumurthy
						Anil Gurumurthy