Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 03429f34 authored by Stefan Haberland's avatar Stefan Haberland Committed by Martin Schwidefsky
Browse files

s390/dasd: fix read unit address configuration loop



Read unit address is done for all devices during online processing to read
out LCU features. This is also done after disconnect/connect a LCU.
Some older storage hardware does not provide the capability to read unit
address configuration.
This leads to a loop trying to read unit address configuration every 30
seconds. The device is still operational but logs are flooded with error
messages.

Fix the loop by recognizing a command reject saying that the suborder
for ruac is not supported.

Signed-off-by: default avatarStefan Haberland <stefan.haberland@de.ibm.com>
Signed-off-by: default avatarMartin Schwidefsky <schwidefsky@de.ibm.com>
parent 12d7b107
Loading
Loading
Loading
Loading
+26 −1
Original line number Original line Diff line number Diff line
@@ -384,6 +384,29 @@ static void _remove_device_from_lcu(struct alias_lcu *lcu,
		group->next = NULL;
		group->next = NULL;
};
};


static int
suborder_not_supported(struct dasd_ccw_req *cqr)
{
	char *sense;
	char reason;
	char msg_format;
	char msg_no;

	sense = dasd_get_sense(&cqr->irb);
	if (!sense)
		return 0;

	reason = sense[0];
	msg_format = (sense[7] & 0xF0);
	msg_no = (sense[7] & 0x0F);

	/* command reject, Format 0 MSG 4 - invalid parameter */
	if ((reason == 0x80) && (msg_format == 0x00) && (msg_no == 0x04))
		return 1;

	return 0;
}

static int read_unit_address_configuration(struct dasd_device *device,
static int read_unit_address_configuration(struct dasd_device *device,
					   struct alias_lcu *lcu)
					   struct alias_lcu *lcu)
{
{
@@ -435,6 +458,8 @@ static int read_unit_address_configuration(struct dasd_device *device,


	do {
	do {
		rc = dasd_sleep_on(cqr);
		rc = dasd_sleep_on(cqr);
		if (rc && suborder_not_supported(cqr))
			return -EOPNOTSUPP;
	} while (rc && (cqr->retries > 0));
	} while (rc && (cqr->retries > 0));
	if (rc) {
	if (rc) {
		spin_lock_irqsave(&lcu->lock, flags);
		spin_lock_irqsave(&lcu->lock, flags);
@@ -521,7 +546,7 @@ static void lcu_update_work(struct work_struct *work)
	 * processing the data
	 * processing the data
	 */
	 */
	spin_lock_irqsave(&lcu->lock, flags);
	spin_lock_irqsave(&lcu->lock, flags);
	if (rc || (lcu->flags & NEED_UAC_UPDATE)) {
	if ((rc && (rc != -EOPNOTSUPP)) || (lcu->flags & NEED_UAC_UPDATE)) {
		DBF_DEV_EVENT(DBF_WARNING, device, "could not update"
		DBF_DEV_EVENT(DBF_WARNING, device, "could not update"
			    " alias data in lcu (rc = %d), retry later", rc);
			    " alias data in lcu (rc = %d), retry later", rc);
		schedule_delayed_work(&lcu->ruac_data.dwork, 30*HZ);
		schedule_delayed_work(&lcu->ruac_data.dwork, 30*HZ);