mirror of
https://github.com/torvalds/linux.git
synced 2024-12-02 00:51:44 +00: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