NetBSD Problem Report #46599

From www@NetBSD.org  Thu Jun 14 19:36:22 2012
Return-Path: <www@NetBSD.org>
Received: from mail.netbsd.org (mail.netbsd.org [149.20.53.66])
	by www.NetBSD.org (Postfix) with ESMTP id 2B32D63B8E6
	for <gnats-bugs@gnats.NetBSD.org>; Thu, 14 Jun 2012 19:36:22 +0000 (UTC)
Message-Id: <20120614193621.5B59963B882@www.NetBSD.org>
Date: Thu, 14 Jun 2012 19:36:21 +0000 (UTC)
From: o.vd.linden@quicknet.nl
Reply-To: o.vd.linden@quicknet.nl
To: gnats-bugs@NetBSD.org
Subject: atapi xfers through a sil 3112 controller of an odd number of bytes or less than 4 bytes causes system lockup
X-Send-Pr-Version: www-1.0

>Number:         46599
>Category:       kern
>Synopsis:       atapi xfers through a sil 3112 controller of an odd number of bytes or less than 4 bytes causes system lockup
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    kern-bug-people
>State:          closed
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Thu Jun 14 19:40:00 +0000 2012
>Closed-Date:    Fri Dec 21 20:44:08 +0000 2012
>Last-Modified:  Fri Dec 21 20:44:08 +0000 2012
>Originator:     Onno van der Linden
>Release:        6.99.7
>Organization:
>Environment:
NetBSD sheep 6.99.7 NetBSD 6.99.7 (SHEEP) #3: Fri Jun  8 20:53:24 MEST 2012  root@sheep:/usr/src/sys/arch/i386/compile/SHEEP i386
>Description:
Running one of the cdrtool commands with the -scanbus option causes a system
with a sil 3112 controller and an atapi device to lockup solidly after which a hard reset
is the only way out. 
>How-To-Repeat:
#include <sys/param.h>
#include <sys/scsiio.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>

#include <dev/scsipi/scsi_spc.h>
#include <dev/scsipi/scsipiconf.h>

/* XXX hardcoded devicename attached to the sil 3112 ctrl */
const char      *dvname = "/dev/rcd0d";

void
scsi_command(int fd, const void *cmd, size_t cmdlen,
        void *data, size_t datalen, int timeout, int flags)
{
        scsireq_t req;

        memset(&req, 0, sizeof(req));        req.datalen = datalen;
        req.timeout = timeout;
        req.flags = flags;
        req.senselen = SENSEBUFLEN;

        if (ioctl(fd, SCIOCCOMMAND, &req) == -1)
                err(1, "SCIOCCOMMAND");

        if (req.retsts == SCCMD_OK)
                return;

        /* Some problem; report it and exit. */
        if (req.retsts == SCCMD_TIMEOUT)
                fprintf(stderr, "%s: SCSI command timed out\n", dvname);
        else if (req.retsts == SCCMD_BUSY)
                fprintf(stderr, "%s: device is busy\n", dvname);
        else if (req.retsts == SCCMD_SENSE)
                fprintf(stderr, "%s: device returned sense data\n", dvname);
        else
                fprintf(stderr, "%s: device had unknown status %x\n", dvname,
                    req.retsts);

        exit(1);
}
void
scsi_mode_sense10(int fd, u_int8_t pgcode, u_int8_t pctl, void *buf, size_t len)
{
        struct scsi_mode_sense_10 cmd;

        memset(&cmd, 0, sizeof(cmd));
        memset(buf, 0, len);

        cmd.opcode = SCSI_MODE_SENSE_10;
        cmd.page = pgcode | pctl;
        _lto2b(len, &cmd.length[0]);

        scsi_command(fd, &cmd, sizeof(cmd), buf, len, 60000,
                        SCCMD_READ|SCCMD_ESCAPE);
}


main(int argc, char *argv[])
{
        int     fd;        close(fd);


        char    buf[256];

        fd = open(dvname,O_RDWR,0);
/* 2,3 or any odd number will cause a lockup with satalink(4) */
        scsi_mode_sense10(fd, 0x2A, 0, buf, 2);
        close(fd);
}

>Fix:
Looks like the silicon image controller doesn't like small (< 4 bytes) or
transfers with an odd number of bytes at all even if the code in
atapi_wdc.c  uses PIO instead of DMA in such cases.

Force transfers of at least 4 bytes in even numbers.

>Release-Note:

>Audit-Trail:
From: Onno van der Linden <o.vd.linden@quicknet.nl>
To: gnats-bugs@NetBSD.org
Cc: 
Subject: Re: kern/46599: atapi xfers through a sil 3112 controller of an odd number of bytes or less than 4 bytes causes system lockup
Date: Sat, 28 Jul 2012 23:19:43 +0200

 > Synopsis:       atapi xfers through a sil 3112 controller
 > of an odd number of bytes or less than 4 bytes causes system lockup

 The Silicon Image 3114 controller I have doesn't seem to like
 bus_space_read_multi_{stream_}[24]() calls where count = 0.
 Below is a diff that fixes it for me. I didn't fix  the code
 after the unaligned label. 

 *** /usr/src/sys/dev/ic/wdc.c.orig	Sat Jul 28 22:19:32 2012
 --- /usr/src/sys/dev/ic/wdc.c	Sat Jul 28 23:08:25 2012
 ***************
 *** 1879,1906 ****
   #endif

   	if (flags & DRIVE_NOSTREAM) {
 ! 		if (flags & DRIVE_CAP32) {
   			bus_space_read_multi_4(wdr->data32iot,
   			    wdr->data32ioh, 0, bf, len >> 2);
   			bf = (char *)bf + (len & ~3);
   			len &= 3;
   		}
 ! 		if (len) {
   			bus_space_read_multi_2(wdr->cmd_iot,
   			    wdr->cmd_iohs[wd_data], 0, bf, len >> 1);
   		}
   	} else {
 ! 		if (flags & DRIVE_CAP32) {
   			bus_space_read_multi_stream_4(wdr->data32iot,
   			    wdr->data32ioh, 0, bf, len >> 2);
   			bf = (char *)bf + (len & ~3);
   			len &= 3;
   		}
 ! 		if (len) {
   			bus_space_read_multi_stream_2(wdr->cmd_iot,
   			    wdr->cmd_iohs[wd_data], 0, bf, len >> 1);
   		}
   	}
   	return;

   #ifndef __NO_STRICT_ALIGNMENT
 --- 1879,1913 ----
   #endif

   	if (flags & DRIVE_NOSTREAM) {
 ! 		if ((flags & DRIVE_CAP32) && len > 3) {
   			bus_space_read_multi_4(wdr->data32iot,
   			    wdr->data32ioh, 0, bf, len >> 2);
   			bf = (char *)bf + (len & ~3);
   			len &= 3;
   		}
 ! 		if (len > 1) {
   			bus_space_read_multi_2(wdr->cmd_iot,
   			    wdr->cmd_iohs[wd_data], 0, bf, len >> 1);
 + 			bf = (char *)bf + (len & ~1);
 + 			len &= 1;
   		}
   	} else {
 ! 		if ((flags & DRIVE_CAP32) && len > 3) {
   			bus_space_read_multi_stream_4(wdr->data32iot,
   			    wdr->data32ioh, 0, bf, len >> 2);
   			bf = (char *)bf + (len & ~3);
   			len &= 3;
   		}
 ! 		if (len > 1) {
   			bus_space_read_multi_stream_2(wdr->cmd_iot,
   			    wdr->cmd_iohs[wd_data], 0, bf, len >> 1);
 + 			bf = (char *)bf + (len & ~1);
 + 			len &= 1;
   		}
   	}
 + 	if (len)
 + 		*((uint8_t *)bf) = bus_space_read_1(wdr->cmd_iot,
 + 			    wdr->cmd_iohs[wd_data], 0);
   	return;

   #ifndef __NO_STRICT_ALIGNMENT

From: "Christos Zoulas" <christos@netbsd.org>
To: gnats-bugs@gnats.NetBSD.org
Cc: 
Subject: PR/46599 CVS commit: src/sys/dev/ic
Date: Sun, 29 Jul 2012 14:20:14 -0400

 Module Name:	src
 Committed By:	christos
 Date:		Sun Jul 29 18:20:14 UTC 2012

 Modified Files:
 	src/sys/dev/ic: wdc.c

 Log Message:
 PR/46599: Onno van der Linden: Don't call bus space commands with 0 len.
 Causes the sil 3112 controller to lock up.


 To generate a diff of this commit:
 cvs rdiff -u -r1.272 -r1.273 src/sys/dev/ic/wdc.c

 Please note that diffs are not public domain; they are subject to the
 copyright notices on the relevant files.

State-Changed-From-To: open->closed
State-Changed-By: dholland@NetBSD.org
State-Changed-When: Fri, 21 Dec 2012 20:44:08 +0000
State-Changed-Why:
christos committed it in july


>Unformatted:

NetBSD Home
NetBSD PR Database Search

(Contact us) $NetBSD: query-full-pr,v 1.39 2013/11/01 18:47:49 spz Exp $
$NetBSD: gnats_config.sh,v 1.8 2006/05/07 09:23:38 tsutsui Exp $
Copyright © 1994-2007 The NetBSD Foundation, Inc. ALL RIGHTS RESERVED.