Skip to content

Commit

Permalink
s390/dasd: fix read unit address configuration loop
Browse files Browse the repository at this point in the history
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: Stefan Haberland <stefan.haberland@de.ibm.com>
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
  • Loading branch information
Stefan Haberland authored and Martin Schwidefsky committed Sep 17, 2012
1 parent 12d7b10 commit 03429f3
Showing 1 changed file with 26 additions and 1 deletion.
27 changes: 26 additions & 1 deletion drivers/s390/block/dasd_alias.c
Original file line number Diff line number Diff line change
Expand Up @@ -384,6 +384,29 @@ static void _remove_device_from_lcu(struct alias_lcu *lcu,
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,
struct alias_lcu *lcu)
{
Expand Down Expand Up @@ -435,6 +458,8 @@ static int read_unit_address_configuration(struct dasd_device *device,

do {
rc = dasd_sleep_on(cqr);
if (rc && suborder_not_supported(cqr))
return -EOPNOTSUPP;
} while (rc && (cqr->retries > 0));
if (rc) {
spin_lock_irqsave(&lcu->lock, flags);
Expand Down Expand Up @@ -521,7 +546,7 @@ static void lcu_update_work(struct work_struct *work)
* processing the data
*/
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"
" alias data in lcu (rc = %d), retry later", rc);
schedule_delayed_work(&lcu->ruac_data.dwork, 30*HZ);
Expand Down

0 comments on commit 03429f3

Please sign in to comment.