[RFC] questions about some issues in the qla2xxx module

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hello qla2xxx maintainers,

I have some questions about the qla2xxx module after investigating something downstream
and finding the same issues upstream (there are 3 issues below).

The first issue is in qla2x00_get_data_rate() there are two code segments that are
identical:

int
qla2x00_get_data_rate(scsi_qla_host_t *vha) {
	int rval;
	mbx_cmd_t mc;
	mbx_cmd_t *mcp = &mc;
	struct qla_hw_data *ha = vha->hw;

	ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1106,
	    "Entered %s.\n", __func__);

	if (!IS_FWI2_CAPABLE(ha))
		return QLA_FUNCTION_FAILED;

	mcp->mb[0] = MBC_DATA_RATE;
	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) || IS_QLA28XX(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)                   <<<<<<<<<<<<<
			ha->link_data_rate = mcp->mb[1]; <<<<<<<<<<<<<

		if (IS_QLA83XX(ha) || IS_QLA27XX(ha) || IS_QLA28XX(ha)) {
			if (mcp->mb[4] & BIT_0)
				ql_log(ql_log_info, vha, 0x11a2,
				    "FEC=enabled (data rate).\n");
		}

		ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1108,
		    "Done %s.\n", __func__);
		if (mcp->mb[1] != 0x7)                    <<<<<<<<<<<<<
			ha->link_data_rate = mcp->mb[1];  <<<<<<<<<<<<<
	}

	return rval;
}

As far as I can determine nothing in between them should change link_data_rate.

This was introduced in the change 75666f4a8c41 ("scsi: qla2xxx: Display message
for FCE enabled") and you can see the start of the duplicated code. Was the second
instance of the if meant to be removed? It's also FEC not FCE.

In the message why use "(data rate)" when you could get the speed itself from
qla2x00_get_link_speed_str()? 

The second issue is this function prints a message to the kernel message buffer but it
causes an issue in that qla2x00_get_data_rate() can be called from
qla2x00_configure_loop() and from here (that is fine for the former but not the later):

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;
	u16 i;
	char *speed = "Unknown";

	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;
	}

	for (i = 0; i < ARRAY_SIZE(port_speed_str); i++) {
		if (port_speed_str[i].rate != ha->link_data_rate)
			continue;
		speed = port_speed_str[i].str;
		break;
	}

	return scnprintf(buf, PAGE_SIZE, "%s\n", speed);
}

So every time some reads the port_speed file it can log a kernel message so if you 
read the sysfs port_speed file a lot you can generate a lot of messages in the kernel
message buffer (messages have been changed manually):

2023-06-01T11:59:11.180034+02:00 example kernel: [2399544.415344][ XXXX] qla2xxx
 [  0000:61:00.1]-11a2:1: FEC=enabled (data rate).
2023-06-01T11:59:11.810042+02:00 example kernel: [2399544.415764][ XXXX] qla2xxx
 [  0000:61:00.1]-11a2:1: FEC=enabled (data rate).

Is that a defect? I wouldn't have expected reading a sysfs file to always generate
a kernel message into the kernel message buffer. The change that introduced the
message doesn't seem to have taken into account that function can be called from
two places.

Also, why isn't qla2x00_get_link_speed_str() used instead of adding
another structure containing almost identical speed data?

That leads onto the 3rd issue the really confusing ql_log function:

2572 ql_log(uint level, scsi_qla_host_t *vha, uint id, const char *fmt, ...)
2573 {
2574         va_list va;
2575         struct va_format vaf;
2576         char pbuf[128];
2577 
2578         if (level > ql_errlev)
2579                 return;
2580 
2581         ql_ktrace(0, level, pbuf, NULL, vha, id, fmt);
2582 
2583         if (!pbuf[0]) /* set by ql_ktrace */
2584                 ql_dbg_prefix(pbuf, ARRAY_SIZE(pbuf), NULL, vha, id);
2585 
2586         va_start(va, fmt);
2587 
2588         vaf.fmt = fmt;
2589         vaf.va = &va;
2590 
2591         switch (level) {
2592         case ql_log_fatal: /* FATAL LOG */
2593                 pr_crit("%s%pV", pbuf, &vaf);
2594                 break;
2595         case ql_log_warn: <<<<<<<<<<<<<<<<<<<<<<<<
2596                 pr_err("%s%pV", pbuf, &vaf); <<<<<<<<<<<<<<<<<<<<<<<<
2597                 break;
2598         case ql_log_info: <<<<<<<<<<<<<<<<<<<<<<<<
2599                 pr_warn("%s%pV", pbuf, &vaf); <<<<<<<<<<<<<<<<<<<<<<<<
2600                 break;
2601         default:
2602                 pr_info("%s%pV", pbuf, &vaf);
2603                 break;
2604         }
2605 
2606         va_end(va);
2607 }

When I was looking at the driver I hadn't looked at ql_log() and was having issues suppressing
the kernel messages from issue #2 above. When I did look I noticed that ql_log_info messages
are printed with pr_warn() (so it's really a warning not info). Should the log levels used in the
qla2xxx driver more generally reflect the kernel usage of message levels (i.e. ql_log_info
should use pr_info, etc)?

Thanks
Shane




[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Index of Archives]     [SCSI Target Devel]     [Linux SCSI Target Infrastructure]     [Kernel Newbies]     [IDE]     [Security]     [Git]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux ATA RAID]     [Linux IIO]     [Samba]     [Device Mapper]

  Powered by Linux