USB gecko driver patch
"Aliz 'Randomdude'" <[email protected]> Thu, 24 May 2012 12:45:08 +0100
| Newsgroups | gmane.linux.ports.game-cube.devel |
|---|---|
| Message-ID | <CAEMXWCCjpMryiTfUa6Tat6N6PusAxyxysGfkPiUy4ZhHagTwFA@mail.gmail.com> |
--===============8205201925648478414==
Content-Type: multipart/alternative; boundary=14dae9340cdda0a03d04c0c6c88f
--14dae9340cdda0a03d04c0c6c88f
Content-Type: text/plain; charset=ISO-8859-1
Hi list. I've made some enhancements to the gc-linux sd-gecko driver, and
thought I'd share. I hope this mailinglist is the right place to submit
such patches - my apologies if not!
My patch fixes the console_write function, which should return the number
of characters written (previous behaviour was to return the count of
characters to write, silently dropping if buffers were full). I've also
added a ring buffer for data transmission while I was in there. The
difference may not be noticeable if you just run a console over the Gecko,
but if you end up running PPP over it, it's the difference between 150ms
pings and 300 second pings! :)
As a caveat, I've only been able to test my updates on my homebrew gecko,
not on a 'real' one. My homebrew device is based on the available VHDL, so
it should be similar, but if anyone has a real gecko and can test, it'd be
appreciated!
Finally, this is my first kernel patch, so please be kind if I've violated
all sorts of style or safety guidelines. I've tried to make the code robust
and good against races.. hopefully I haven't missed anything!
The patch is against a mikep1 source.
-Aliz Hammond / randomdude
--- linux-2.6.32.27/drivers/serial/usbgecko.c 2012-03-16 18:28:34.393587508
+0000
+++ ./usbgecko.c 2012-05-24 17:33:16.037171945 +0100
@@ -24,6 +24,8 @@
#include <linux/tty_flip.h>
#include <linux/kthread.h>
#include <linux/delay.h>
+#include <linux/circ_buf.h>
+#define XMITSIZE 256
#include <linux/exi.h>
@@ -54,6 +56,7 @@
struct task_struct *poller;
struct mutex mutex;
int refcnt;
+ struct circ_buf xmit;
};
static struct ug_adapter ug_adapters[2];
@@ -342,6 +345,20 @@
}
schedule_timeout(1);
}
+ // Now try to transmit anything pending.
+ if (adapter) {
+ unsigned long head = ACCESS_ONCE(adapter->xmit.head);
+ unsigned long tail = adapter->xmit.tail;
+ count = CIRC_CNT(head, tail, XMITSIZE);
+ if (count > 0) {
+ if(ug_safe_putc(adapter,
+ adapter->xmit.buf[tail])) {
+ barrier();
+ adapter->xmit.tail = (tail + 1) & (XMITSIZE - 1);
+ }
+ }
+ }
+
set_task_state(current, TASK_RUNNING);
}
@@ -402,11 +419,37 @@
mutex_unlock(&adapter->mutex);
}
+static int ug_tty_putchar(struct tty_struct *tty, unsigned char ch)
+{
+ struct ug_adapter *adapter = tty->driver_data;
+ struct circ_buf *xmit = &adapter->xmit;
+ unsigned long head, tail;
+ int index;
+
+ if (!adapter)
+ return -ENODEV;
+
+ index = tty->index;
+ adapter = &ug_adapters[index];
+
+ head = xmit->head;
+ tail = ACCESS_ONCE(xmit->tail);
+
+ if( CIRC_SPACE(head, tail, XMITSIZE) == 0)
+ return 0;
+
+ xmit->buf[head] = ch;
+ barrier();
+ xmit->head = (head + 1) & (XMITSIZE - 1);
+
+ return 1;
+}
+
static int ug_tty_write(struct tty_struct *tty,
const unsigned char *buf, int count)
{
struct ug_adapter *adapter = tty->driver_data;
- char *b = (char *)buf;
+ unsigned long head, tail;
int index;
int i;
@@ -415,19 +458,42 @@
index = tty->index;
adapter = &ug_adapters[index];
- for (i = 0; i < count; i++)
- ug_safe_putc(adapter, *b++);
+
+ head = ACCESS_ONCE(adapter->xmit.head);
+ tail = adapter->xmit.tail;
+
+ // Simply pass all our data to putchar.
+ for(i=0; i<count; i++)
+ ug_tty_putchar(tty, buf[i]);
+
return count;
}
static int ug_tty_write_room(struct tty_struct *tty)
{
- return 0x123; /* whatever */
+ struct ug_adapter *adapter = tty->driver_data;
+
+ if (!adapter)
+ return 0;
+
+ unsigned long head = ACCESS_ONCE(adapter->xmit.head);
+ unsigned long tail = adapter->xmit.tail;
+
+ return CIRC_SPACE(head, tail, XMITSIZE);
}
static int ug_tty_chars_in_buffer(struct tty_struct *tty)
{
- return 0; /* unbuffered */
+ struct ug_adapter *adapter = tty->driver_data;
+ unsigned long head, tail;
+
+ if (!adapter)
+ return 0;
+
+ head = ACCESS_ONCE(adapter->xmit.head);
+ tail = adapter->xmit.tail;
+
+ return CIRC_CNT(head, tail, XMITSIZE);
}
@@ -435,6 +501,7 @@
.open = ug_tty_open,
.close = ug_tty_close,
.write = ug_tty_write,
+ .put_char = ug_tty_putchar,
.write_room = ug_tty_write_room,
.chars_in_buffer = ug_tty_chars_in_buffer,
};
@@ -507,6 +574,13 @@
adapter->poller = ERR_PTR(-EINVAL);
mutex_init(&adapter->mutex);
adapter->refcnt = 0;
+ adapter->xmit.head = adapter->xmit.tail = 0;
+ adapter->xmit.buf = kmalloc(XMITSIZE, GFP_KERNEL);
+ if(!adapter->xmit.buf)
+ {
+ drv_printk(KERN_ERR, "USB Gecko: kmalloc failed\n");
+ return 1;
+ }
adapter->exi_device = exi_device_get(exi_device);
exi_set_drvdata(exi_device, adapter);
--14dae9340cdda0a03d04c0c6c88f
Content-Type: text/html; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable
Hi list.=A0I've made some enhancements to the gc-linux sd-gecko driver,=
and thought I'd share. I hope this mailinglist is the right place to s=
ubmit such patches - my apologies if not!<div><br></div><div>My patch fixes=
the console_write function, which should return the number of characters w=
ritten (previous behaviour was to return the count of characters to write, =
silently dropping if buffers were full). I've also added a ring buffer =
for data transmission while I was in there.=A0The difference may not be=A0n=
oticeable=A0if you just run a console over the Gecko, but if you end up run=
ning PPP over it, it's the difference between 150ms pings and 300 secon=
d pings! :)</div>
<div><br></div><div>As a caveat, I've only been able to test my updates=
on my homebrew gecko, not on a 'real' one. My homebrew device is b=
ased on the available VHDL, so it should be similar, but if anyone has a re=
al gecko and can test, it'd be appreciated!</div>
<div>Finally, this is my first kernel patch, so please be kind if I've =
violated all sorts of style or safety guidelines. I've tried to make th=
e code robust and good against races.. hopefully I haven't missed anyth=
ing!</div>
<div><br></div><div>The patch is against a mikep1 source.</div><div><br></d=
iv><div>-Aliz Hammond / randomdude</div><div><br></div><div><div>--- linux-=
2.6.32.27/drivers/serial/usbgecko.c<span class=3D"Apple-tab-span" style=3D"=
white-space:pre"> </span>2012-03-16 18:28:34.393587508 +0000</div>
<div>+++ ./usbgecko.c<span class=3D"Apple-tab-span" style=3D"white-space:pr=
e"> </span>2012-05-24 17:33:16.037171945 +0100</div><div>@@ -24,6 +24,8 @@<=
/div><div>=A0#include <linux/tty_flip.h></div><div>=A0#include <li=
nux/kthread.h></div>
<div>=A0#include <linux/delay.h></div><div>+#include <linux/circ_b=
uf.h></div><div>+#define XMITSIZE 256</div><div>=A0</div><div>=A0#includ=
e <linux/exi.h></div><div>=A0</div><div>@@ -54,6 +56,7 @@</div><div>=
=A0<span class=3D"Apple-tab-span" style=3D"white-space:pre"> </span>struct =
task_struct *poller;</div>
<div>=A0<span class=3D"Apple-tab-span" style=3D"white-space:pre"> </span>st=
ruct mutex mutex;</div><div>=A0<span class=3D"Apple-tab-span" style=3D"whit=
e-space:pre"> </span>int refcnt;</div><div>+<span class=3D"Apple-tab-span" =
style=3D"white-space:pre"> </span>struct circ_buf xmit;</div>
<div>=A0};</div><div>=A0</div><div>=A0static struct ug_adapter ug_adapters[=
2];</div><div>@@ -342,6 +345,20 @@</div><div>=A0<span class=3D"Apple-tab-sp=
an" style=3D"white-space:pre"> </span>}</div><div>=A0<span class=3D"Apple=
-tab-span" style=3D"white-space:pre"> </span>schedule_timeout(1);</div>
<div>=A0<span class=3D"Apple-tab-span" style=3D"white-space:pre"> </span>}=
</div><div>+<span class=3D"Apple-tab-span" style=3D"white-space:pre"> </sp=
an>// Now try to transmit anything pending.</div><div>+<span class=3D"Apple=
-tab-span" style=3D"white-space:pre"> </span>if (adapter) {</div>
<div>+<span class=3D"Apple-tab-span" style=3D"white-space:pre"> </span>un=
signed long head =3D ACCESS_ONCE(adapter->xmit.head);</div><div>+<span c=
lass=3D"Apple-tab-span" style=3D"white-space:pre"> </span>unsigned long t=
ail =3D adapter->xmit.tail;</div>
<div>+<span class=3D"Apple-tab-span" style=3D"white-space:pre"> </span>co=
unt =3D CIRC_CNT(head, tail, XMITSIZE);</div><div>+<span class=3D"Apple-tab=
-span" style=3D"white-space:pre"> </span>if (count > 0) {</div><div>+<=
span class=3D"Apple-tab-span" style=3D"white-space:pre"> </span>if(ug_sa=
fe_putc(adapter,</div>
<div>+<span class=3D"Apple-tab-span" style=3D"white-space:pre"> </span>=
adapter->xmit.buf[tail])) {</div><div>+<span class=3D"Apple-tab-span" st=
yle=3D"white-space:pre"> </span>barrier();</div><div>+<span class=3D"Ap=
ple-tab-span" style=3D"white-space:pre"> </span>adapter->xmit.tail =
=3D (tail + 1) & (XMITSIZE - 1);</div>
<div>+<span class=3D"Apple-tab-span" style=3D"white-space:pre"> </span>}=
</div><div>+<span class=3D"Apple-tab-span" style=3D"white-space:pre"> </s=
pan>}</div><div>+<span class=3D"Apple-tab-span" style=3D"white-space:pre"> =
</span>}</div>
<div>+</div><div>=A0<span class=3D"Apple-tab-span" style=3D"white-space:pre=
"> </span>set_task_state(current, TASK_RUNNING);</div><div>=A0<span class=
=3D"Apple-tab-span" style=3D"white-space:pre"> </span>}</div><div>=A0</div>=
<div>@@ -402,11 +419,37 @@</div>
<div>=A0<span class=3D"Apple-tab-span" style=3D"white-space:pre"> </span>mu=
tex_unlock(&adapter->mutex);</div><div>=A0}</div><div>=A0</div><div>=
+static int ug_tty_putchar(struct tty_struct *tty, unsigned char ch)</div><=
div>+{</div>
<div>+<span class=3D"Apple-tab-span" style=3D"white-space:pre"> </span>stru=
ct ug_adapter *adapter =3D tty->driver_data;</div><div>+<span class=3D"A=
pple-tab-span" style=3D"white-space:pre"> </span>struct circ_buf =A0*xmit =
=3D &adapter->xmit;</div>
<div>+<span class=3D"Apple-tab-span" style=3D"white-space:pre"> </span>unsi=
gned long head, tail;</div><div>+<span class=3D"Apple-tab-span" style=3D"wh=
ite-space:pre"> </span>int index;</div><div>+</div><div>+<span class=3D"App=
le-tab-span" style=3D"white-space:pre"> </span>if (!adapter)</div>
<div>+<span class=3D"Apple-tab-span" style=3D"white-space:pre"> </span>ret=
urn -ENODEV;</div><div>+</div><div>+<span class=3D"Apple-tab-span" style=3D=
"white-space:pre"> </span>index =3D tty->index;</div><div>+<span class=
=3D"Apple-tab-span" style=3D"white-space:pre"> </span>adapter =3D &ug_a=
dapters[index];</div>
<div>+</div><div>+<span class=3D"Apple-tab-span" style=3D"white-space:pre">=
</span>head =3D xmit->head;</div><div>+<span class=3D"Apple-tab-span" s=
tyle=3D"white-space:pre"> </span>tail =3D ACCESS_ONCE(xmit->tail);</div>=
<div>+</div>
<div>+<span class=3D"Apple-tab-span" style=3D"white-space:pre"> </span>if( =
CIRC_SPACE(head, tail, XMITSIZE) =3D=3D 0)</div><div>+<span class=3D"Apple-=
tab-span" style=3D"white-space:pre"> </span>return 0;</div><div>+</div><di=
v>+<span class=3D"Apple-tab-span" style=3D"white-space:pre"> </span>xmit-&g=
t;buf[head] =3D ch;</div>
<div>+<span class=3D"Apple-tab-span" style=3D"white-space:pre"> </span>barr=
ier();</div><div>+<span class=3D"Apple-tab-span" style=3D"white-space:pre">=
</span>xmit->head =3D (head + 1) & (XMITSIZE - 1);</div><div>+</div=
><div>
+<span class=3D"Apple-tab-span" style=3D"white-space:pre"> </span>return 1;=
</div><div>+}</div><div>+</div><div>=A0static int ug_tty_write(struct tty_s=
truct *tty,</div><div>=A0<span class=3D"Apple-tab-span" style=3D"white-spac=
e:pre"> </span> const unsigned char *buf, int count)</div>
<div>=A0{</div><div>=A0<span class=3D"Apple-tab-span" style=3D"white-space:=
pre"> </span>struct ug_adapter *adapter =3D tty->driver_data;</div><div>=
-<span class=3D"Apple-tab-span" style=3D"white-space:pre"> </span>char *b =
=3D (char *)buf;</div>
<div>+<span class=3D"Apple-tab-span" style=3D"white-space:pre"> </span>unsi=
gned long head, tail;</div><div>=A0<span class=3D"Apple-tab-span" style=3D"=
white-space:pre"> </span>int index;</div><div>=A0<span class=3D"Apple-tab-s=
pan" style=3D"white-space:pre"> </span>int i;</div>
<div>=A0</div><div>@@ -415,19 +458,42 @@</div><div>=A0</div><div>=A0<span c=
lass=3D"Apple-tab-span" style=3D"white-space:pre"> </span>index =3D tty->=
;index;</div><div>=A0<span class=3D"Apple-tab-span" style=3D"white-space:pr=
e"> </span>adapter =3D &ug_adapters[index];</div>
<div>-<span class=3D"Apple-tab-span" style=3D"white-space:pre"> </span>for =
(i =3D 0; i < count; i++)</div><div>-<span class=3D"Apple-tab-span" styl=
e=3D"white-space:pre"> </span>ug_safe_putc(adapter, *b++);</div><div>+</di=
v><div>
+<span class=3D"Apple-tab-span" style=3D"white-space:pre"> </span>head =3D =
ACCESS_ONCE(adapter->xmit.head);</div><div>+<span class=3D"Apple-tab-spa=
n" style=3D"white-space:pre"> </span>tail =3D adapter->xmit.tail;</div><=
div>+</div>
<div>+<span class=3D"Apple-tab-span" style=3D"white-space:pre"> </span>// S=
imply pass all our data to putchar.</div><div>+<span class=3D"Apple-tab-spa=
n" style=3D"white-space:pre"> </span>for(i=3D0; i<count; i++)</div><div>=
+<span class=3D"Apple-tab-span" style=3D"white-space:pre"> </span>ug_tty_p=
utchar(tty, buf[i]);</div>
<div>+</div><div>=A0<span class=3D"Apple-tab-span" style=3D"white-space:pre=
"> </span>return count;</div><div>=A0}</div><div>=A0</div><div>=A0static in=
t ug_tty_write_room(struct tty_struct *tty)</div><div>=A0{</div><div>-<span=
class=3D"Apple-tab-span" style=3D"white-space:pre"> </span>return 0x123; /=
* whatever */</div>
<div>+<span class=3D"Apple-tab-span" style=3D"white-space:pre"> </span>stru=
ct ug_adapter *adapter =3D tty->driver_data;</div><div>+</div><div>+<spa=
n class=3D"Apple-tab-span" style=3D"white-space:pre"> </span>if (!adapter)<=
/div><div>
+<span class=3D"Apple-tab-span" style=3D"white-space:pre"> </span>return 0=
;</div><div>+</div><div>+<span class=3D"Apple-tab-span" style=3D"white-spac=
e:pre"> </span>unsigned long head =3D ACCESS_ONCE(adapter->xmit.head);</=
div><div>
+<span class=3D"Apple-tab-span" style=3D"white-space:pre"> </span>unsigned =
long tail =3D adapter->xmit.tail;</div><div>+</div><div>+<span class=3D"=
Apple-tab-span" style=3D"white-space:pre"> </span>return CIRC_SPACE(head, t=
ail, XMITSIZE);</div>
<div>=A0}</div><div>=A0</div><div>=A0static int ug_tty_chars_in_buffer(stru=
ct tty_struct *tty)</div><div>=A0{</div><div>-<span class=3D"Apple-tab-span=
" style=3D"white-space:pre"> </span>return 0; /* unbuffered */</div><div>+<=
span class=3D"Apple-tab-span" style=3D"white-space:pre"> </span>struct ug_a=
dapter *adapter =3D tty->driver_data;</div>
<div>+<span class=3D"Apple-tab-span" style=3D"white-space:pre"> </span>unsi=
gned long head, tail;</div><div>+</div><div>+<span class=3D"Apple-tab-span"=
style=3D"white-space:pre"> </span>if (!adapter)</div><div>+<span class=3D"=
Apple-tab-span" style=3D"white-space:pre"> </span>return 0;</div>
<div>+</div><div>+<span class=3D"Apple-tab-span" style=3D"white-space:pre">=
</span>head =3D ACCESS_ONCE(adapter->xmit.head);</div><div>+<span class=
=3D"Apple-tab-span" style=3D"white-space:pre"> </span>tail =3D adapter->=
xmit.tail;</div>
<div>+</div><div>+<span class=3D"Apple-tab-span" style=3D"white-space:pre">=
</span>return CIRC_CNT(head, tail, XMITSIZE);</div><div>=A0}</div><div>=A0=
</div><div>=A0</div><div>@@ -435,6 +501,7 @@</div><div>=A0<span class=3D"Ap=
ple-tab-span" style=3D"white-space:pre"> </span>.open =3D ug_tty_open,</div=
>
<div>=A0<span class=3D"Apple-tab-span" style=3D"white-space:pre"> </span>.c=
lose =3D ug_tty_close,</div><div>=A0<span class=3D"Apple-tab-span" style=3D=
"white-space:pre"> </span>.write =3D ug_tty_write,</div><div>+<span class=
=3D"Apple-tab-span" style=3D"white-space:pre"> </span>.put_char =3D ug_tty_=
putchar,</div>
<div>=A0<span class=3D"Apple-tab-span" style=3D"white-space:pre"> </span>.w=
rite_room =3D ug_tty_write_room,</div><div>=A0<span class=3D"Apple-tab-span=
" style=3D"white-space:pre"> </span>.chars_in_buffer =3D ug_tty_chars_in_bu=
ffer,</div><div>
=A0};</div><div>@@ -507,6 +574,13 @@</div><div>=A0<span class=3D"Apple-tab-=
span" style=3D"white-space:pre"> </span>adapter->poller =3D ERR_PTR(-EIN=
VAL);</div><div>=A0<span class=3D"Apple-tab-span" style=3D"white-space:pre"=
> </span>mutex_init(&adapter->mutex);</div>
<div>=A0<span class=3D"Apple-tab-span" style=3D"white-space:pre"> </span>ad=
apter->refcnt =3D 0;</div><div>+<span class=3D"Apple-tab-span" style=3D"=
white-space:pre"> </span>adapter->xmit.head =3D adapter->xmit.tail =
=3D 0;</div><div>
+<span class=3D"Apple-tab-span" style=3D"white-space:pre"> </span>adapter-&=
gt;xmit.buf =3D kmalloc(XMITSIZE, GFP_KERNEL);</div><div>+<span class=3D"Ap=
ple-tab-span" style=3D"white-space:pre"> </span>if(!adapter->xmit.buf)</=
div><div>
+<span class=3D"Apple-tab-span" style=3D"white-space:pre"> </span>{</div><d=
iv>+<span class=3D"Apple-tab-span" style=3D"white-space:pre"> </span>drv_p=
rintk(KERN_ERR, "USB Gecko: kmalloc failed\n");</div><div>+<span =
class=3D"Apple-tab-span" style=3D"white-space:pre"> </span>return 1;</div>
<div>+<span class=3D"Apple-tab-span" style=3D"white-space:pre"> </span>}</d=
iv><div>=A0</div><div>=A0<span class=3D"Apple-tab-span" style=3D"white-spac=
e:pre"> </span>adapter->exi_device =3D exi_device_get(exi_device);</div>=
<div>=A0<span class=3D"Apple-tab-span" style=3D"white-space:pre"> </span>ex=
i_set_drvdata(exi_device, adapter);</div>
</div><div><br></div>
--14dae9340cdda0a03d04c0c6c88f--
--===============8205201925648478414==
Content-Type: text/plain; charset="us-ascii"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
Content-Disposition: inline
------------------------------------------------------------------------------
Live Security Virtual Conference
Exclusive live event will cover all the ways today's security and
threat landscape has changed and how IT managers can respond. Discussions
will include endpoint security, mobile security and the latest in malware
threats. http://www.accelacomm.com/jaw/sfrnl04242012/114/50122263/
--===============8205201925648478414==
Content-Type: text/plain; charset="us-ascii"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
Content-Disposition: inline
_______________________________________________
gc-linux-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/gc-linux-devel
--===============8205201925648478414==--