From patchwork Wed Sep 30 11:57:24 2009 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Magnus Damm X-Patchwork-Id: 50678 Received: from vger.kernel.org (vger.kernel.org [209.132.176.167]) by demeter.kernel.org (8.14.2/8.14.2) with ESMTP id n8UC25jZ031082 for ; Wed, 30 Sep 2009 12:02:05 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1754139AbZI3MB7 (ORCPT ); Wed, 30 Sep 2009 08:01:59 -0400 Received: (majordomo@vger.kernel.org) by vger.kernel.org id S1753424AbZI3MB7 (ORCPT ); Wed, 30 Sep 2009 08:01:59 -0400 Received: from mail-yw0-f199.google.com ([209.85.211.199]:57175 "EHLO mail-yw0-f199.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751405AbZI3MB5 (ORCPT ); Wed, 30 Sep 2009 08:01:57 -0400 Received: by ywh37 with SMTP id 37so6108656ywh.4 for ; Wed, 30 Sep 2009 05:02:01 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=gamma; h=domainkey-signature:received:received:from:to:cc:date:message-id :subject; bh=f16obtjoynMtaBdIWZcahB774ov8Z/7ayuUYwWC/j0Q=; b=Ipne2fJR6ha0svY/mgs+yO0qy/lSrL2F0qpOG5keA93pQ2FC+TK0wNdwMB5oO/u5fO BD6APpoQGC8u0d2+LjvvTk4SA+KLy8TqcCrcAp2pRDA7ca9u2KPwK0AprF4/hAOO/x9z q4+QNnbyy8uZk0BXItQYfhBDmg9yY2mO/QoiM= DomainKey-Signature: a=rsa-sha1; c=nofws; d=gmail.com; s=gamma; h=from:to:cc:date:message-id:subject; b=gzwJGUSN/ty4/VPfPIsyvgmJvOG64zcCDB/LSW3GSbL5GHc01x4Lh8A8k1Wk/OJqv5 8TqMffySf5uTeSRwotFSfaPSbCt5QiKlfmHDc6PJ/hAOKsw6CRo8NlnBeF6uUlzSVt3/ EsPx0gmmB6LYp/FJ1FCSFzJ4BJ4E8Y3GoNYi8= Received: by 10.90.45.11 with SMTP id s11mr4365072ags.72.1254312121429; Wed, 30 Sep 2009 05:02:01 -0700 (PDT) Received: from rxone.opensource.se (210-225-125-011.jp.fiberphone.net [210.225.125.11]) by mx.google.com with ESMTPS id 1sm3536508agb.48.2009.09.30.05.01.57 (version=TLSv1/SSLv3 cipher=RC4-MD5); Wed, 30 Sep 2009 05:02:00 -0700 (PDT) From: Magnus Damm To: linux-sh@vger.kernel.org Cc: Magnus Damm , lethal@linux-sh.org, shimoda.yoshihiro@renesas.com, linux-usb@vger.kernel.org, gregkh@suse.de Date: Wed, 30 Sep 2009 20:57:24 +0900 Message-Id: <20090930115724.5579.76782.sendpatchset@rxone.opensource.se> Subject: [PATCH] usb: r8a66597-udc unaligned fifo fix Sender: linux-sh-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-sh@vger.kernel.org --- 0001/drivers/usb/gadget/r8a66597-udc.h +++ work/drivers/usb/gadget/r8a66597-udc.h 2009-09-30 17:00:36.000000000 +0900 @@ -131,31 +131,48 @@ static inline u16 r8a66597_read(struct r } static inline void r8a66597_read_fifo(struct r8a66597 *r8a66597, - unsigned long offset, u16 *buf, + unsigned long offset, + unsigned char *buf, int len) { + unsigned long fifoaddr = r8a66597->reg + offset; + unsigned int data; + int i; + if (r8a66597->pdata->on_chip) { - unsigned long fifoaddr = r8a66597->reg + offset; - unsigned long count; - union { - unsigned long dword; - unsigned char byte[4]; - } data; - unsigned char *pb; - int i; - - count = len / 4; - insl(fifoaddr, buf, count); - - if (len & 0x00000003) { - data.dword = inl(fifoaddr); - pb = (unsigned char *)buf + count * 4; - for (i = 0; i < (len & 0x00000003); i++) - pb[i] = data.byte[i]; + /* 32-bit accesses for on_chip controllers */ + + /* aligned buf case */ + if (len >= 4 && !((unsigned long)buf & 0x03)) { + insl(fifoaddr, buf, len / 4); + buf += len & ~0x03; + len &= 0x03; + } + + /* unaligned buf case */ + for (i = 0; i < len; i++) { + if (!(i & 0x03)) + data = inl(fifoaddr); + + buf[i] = (data >> ((i & 0x03) * 8)) & 0xff; } } else { - len = (len + 1) / 2; - insw(r8a66597->reg + offset, buf, len); + /* 16-bit accesses for external controllers */ + + /* aligned buf case */ + if (len >= 2 && !((unsigned long)buf & 0x01)) { + insw(fifoaddr, buf, len / 2); + buf += len & ~0x01; + len &= 0x01; + } + + /* unaligned buf case */ + for (i = 0; i < len; i++) { + if (!(i & 0x01)) + data = inw(fifoaddr); + + buf[i] = (data >> ((i & 0x01) * 8)) & 0xff; + } } } @@ -166,38 +183,40 @@ static inline void r8a66597_write(struct } static inline void r8a66597_write_fifo(struct r8a66597 *r8a66597, - unsigned long offset, u16 *buf, + unsigned long offset, + unsigned char *buf, int len) { unsigned long fifoaddr = r8a66597->reg + offset; + int adj = 0; + int i; if (r8a66597->pdata->on_chip) { - unsigned long count; - unsigned char *pb; - int i; - - count = len / 4; - outsl(fifoaddr, buf, count); - - if (len & 0x00000003) { - pb = (unsigned char *)buf + count * 4; - for (i = 0; i < (len & 0x00000003); i++) { - if (r8a66597_read(r8a66597, CFIFOSEL) & BIGEND) - outb(pb[i], fifoaddr + i); - else - outb(pb[i], fifoaddr + 3 - i); - } + /* 32-bit access only if buf is 32-bit aligned */ + if (len >= 4 && !((unsigned long)buf & 0x03)) { + outsl(fifoaddr, buf, len / 4); + buf += len & ~0x03; + len &= 0x03; } } else { - int odd = len & 0x0001; - - len = len / 2; - outsw(fifoaddr, buf, len); - if (unlikely(odd)) { - buf = &buf[len]; - outb((unsigned char)*buf, fifoaddr); + /* 16-bit access only if buf is 16-bit aligned */ + if (len >= 2 && !((unsigned long)buf & 0x01)) { + outsw(fifoaddr, buf, len / 2); + buf += len & ~0x01; + len &= 0x01; } } + + /* adjust fifo address in the little endian case */ + if (!(r8a66597_read(r8a66597, CFIFOSEL) & BIGEND)) { + if (r8a66597->pdata->on_chip) + adj = 0x03; /* 32-bit wide */ + else + adj = 0x01; /* 16-bit wide */ + } + + for (i = 0; i < len; i++) + outb(buf[i], fifoaddr + adj - (i & adj)); } static inline void r8a66597_mdfy(struct r8a66597 *r8a66597,