Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 21 Jul 2012 14:59:44 +0000 (UTC)
From:      Alexander Motin <mav@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r238673 - head/sys/dev/ata
Message-ID:  <201207211459.q6LExiNl047649@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: mav
Date: Sat Jul 21 14:59:43 2012
New Revision: 238673
URL: http://svn.freebsd.org/changeset/base/238673

Log:
  Use 16bit PIO instead of 32bit in case of misaligned buffer.
  It fixes kernel panic during CD write with cdrecord on sparc64.

Modified:
  head/sys/dev/ata/ata-lowlevel.c

Modified: head/sys/dev/ata/ata-lowlevel.c
==============================================================================
--- head/sys/dev/ata/ata-lowlevel.c	Sat Jul 21 14:07:43 2012	(r238672)
+++ head/sys/dev/ata/ata-lowlevel.c	Sat Jul 21 14:59:43 2012	(r238673)
@@ -836,23 +836,21 @@ static void
 ata_pio_read(struct ata_request *request, int length)
 {
     struct ata_channel *ch = device_get_softc(request->parent);
+    uint8_t *addr;
     int size = min(request->transfersize, length);
     int resid;
     uint8_t buf[2];
 
-    if (ch->flags & ATA_USE_16BIT || (size % sizeof(int32_t))) {
-	ATA_IDX_INSW_STRM(ch, ATA_DATA,
-			  (void*)((uintptr_t)request->data+request->donecount),
-			  size / sizeof(int16_t));
+    addr = (uint8_t *)request->data + request->donecount;
+    if (ch->flags & ATA_USE_16BIT || (size % sizeof(int32_t)) ||
+	((uintptr_t)addr % sizeof(int32_t))) {
+	ATA_IDX_INSW_STRM(ch, ATA_DATA, (void*)addr, size / sizeof(int16_t));
 	if (size & 1) {
 	    ATA_IDX_INSW_STRM(ch, ATA_DATA, (void*)buf, 1);
-	    ((uint8_t *)request->data + request->donecount +
-		(size & ~1))[0] = buf[0];
+	    (addr + (size & ~1))[0] = buf[0];
 	}
     } else
-	ATA_IDX_INSL_STRM(ch, ATA_DATA,
-			  (void*)((uintptr_t)request->data+request->donecount),
-			  size / sizeof(int32_t));
+	ATA_IDX_INSL_STRM(ch, ATA_DATA, (void*)addr, size / sizeof(int32_t));
 
     if (request->transfersize < length) {
 	device_printf(request->parent, "WARNING - %s read data overrun %d>%d\n",
@@ -867,23 +865,21 @@ static void
 ata_pio_write(struct ata_request *request, int length)
 {
     struct ata_channel *ch = device_get_softc(request->parent);
+    uint8_t *addr;
     int size = min(request->transfersize, length);
     int resid;
     uint8_t buf[2];
 
-    if (ch->flags & ATA_USE_16BIT || (size % sizeof(int32_t))) {
-	ATA_IDX_OUTSW_STRM(ch, ATA_DATA,
-			   (void*)((uintptr_t)request->data+request->donecount),
-			   size / sizeof(int16_t));
+    addr = (uint8_t *)request->data + request->donecount;
+    if (ch->flags & ATA_USE_16BIT || (size % sizeof(int32_t)) ||
+	((uintptr_t)addr % sizeof(int32_t))) {
+	ATA_IDX_OUTSW_STRM(ch, ATA_DATA, (void*)addr, size / sizeof(int16_t));
 	if (size & 1) {
-	    buf[0] = ((uint8_t *)request->data + request->donecount +
-		(size & ~1))[0];
+	    buf[0] = (addr + (size & ~1))[0];
 	    ATA_IDX_OUTSW_STRM(ch, ATA_DATA, (void*)buf, 1);
 	}
     } else
-	ATA_IDX_OUTSL_STRM(ch, ATA_DATA,
-			   (void*)((uintptr_t)request->data+request->donecount),
-			   size / sizeof(int32_t));
+	ATA_IDX_OUTSL_STRM(ch, ATA_DATA, (void*)addr, size / sizeof(int32_t));
 
     if (request->transfersize < length) {
 	device_printf(request->parent, "WARNING - %s write data underrun %d>%d\n",



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201207211459.q6LExiNl047649>