Date: Sun, 5 Jul 2009 10:39:18 +0200 From: Hans Petter Selasky <hselasky@c2i.net> To: freebsd-current@freebsd.org Cc: Patrick Lamaiziere <patfbsd@davenulle.org> Subject: Re: ulpt problem (USB_ERR_IOERROR) Message-ID: <200907051039.19584.hselasky@c2i.net> In-Reply-To: <20090704164341.0acd0271@baby-jane.lamaiziere.net> References: <20090703172600.1971111e@baby-jane.lamaiziere.net> <200907040945.41153.hselasky@c2i.net> <20090704164341.0acd0271@baby-jane.lamaiziere.net>
next in thread | previous in thread | raw e-mail | index | archive | help
--Boundary-00=_3aGUKFo9aO8ZqtK
Content-Type: text/plain;
charset="iso-8859-1"
Content-Transfer-Encoding: quoted-printable
Content-Disposition: inline
On Saturday 04 July 2009 16:43:41 Patrick Lamaiziere wrote:
> Le Sat, 4 Jul 2009 09:45:40 +0200,
>
> Hans Petter Selasky <hselasky@c2i.net> a =E9crit :
> > > ulpt_write_callback:220: state=3D0x1 actlen=3D2889
> > > ulpt_write_callback:220: state=3D0x1 actlen=3D3023
> >
> > These two lines are interesting. Are these printed when doing the
> > same job?
>
> Yes.
>
Can you try the attached patch for 8-current. Please provide ulpt debug pri=
nts=20
in either failing or succeeding case.
cd /sys/dev/usb
cat ulpt.diff | patch
Build a new kernel and modules.
=2D-HPS
--Boundary-00=_3aGUKFo9aO8ZqtK
Content-Type: text/x-patch;
charset="iso-8859-1";
name="ulpt.diff"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
filename="ulpt.diff"
diff -u ./serial/ulpt.c ./serial/ulpt.c
--- ./serial/ulpt.c 2009-06-24 12:59:19.000000000 +0200
+++ ./serial/ulpt.c 2009-07-05 10:19:31.000000000 +0200
@@ -110,6 +110,7 @@
struct ulpt_softc {
struct usb_fifo_sc sc_fifo;
struct usb_fifo_sc sc_fifo_noreset;
+ struct usb_fifo_sc sc_fifo_raw;
struct mtx sc_mtx;
struct usb_callout sc_watchdog;
@@ -147,6 +148,7 @@
static usb_fifo_ioctl_t ulpt_ioctl;
static usb_fifo_open_t ulpt_open;
static usb_fifo_open_t unlpt_open;
+static usb_fifo_open_t urlpt_open;
static struct usb_fifo_methods ulpt_fifo_methods = {
.f_close = &ulpt_close,
@@ -170,6 +172,17 @@
.basename[0] = "unlpt",
};
+static struct usb_fifo_methods urlpt_fifo_methods = {
+ .f_close = &ulpt_close,
+ .f_ioctl = &ulpt_ioctl,
+ .f_open = &urlpt_open,
+ .f_start_read = &ulpt_start_read,
+ .f_start_write = &ulpt_start_write,
+ .f_stop_read = &ulpt_stop_read,
+ .f_stop_write = &ulpt_stop_write,
+ .basename[0] = "urlpt",
+};
+
static void
ulpt_reset(struct ulpt_softc *sc)
{
@@ -419,6 +432,28 @@
}
static int
+urlpt_open(struct usb_fifo *fifo, int fflags)
+{
+ struct ulpt_softc *sc = usb_fifo_softc(fifo);
+
+ /* we assume that open is a serial process */
+
+ if (sc->sc_fflags == 0) {
+
+ /* reset USB paralell port */
+
+ ulpt_reset(sc);
+
+ /* set raw write mode */
+
+ if (fflags & FWRITE) {
+ usb_fifo_set_write_defrag(fifo, 0);
+ }
+ }
+ return (unlpt_open(fifo, fflags));
+}
+
+static int
ulpt_open(struct usb_fifo *fifo, int fflags)
{
struct ulpt_softc *sc = usb_fifo_softc(fifo);
@@ -426,7 +461,16 @@
/* we assume that open is a serial process */
if (sc->sc_fflags == 0) {
+
+ /* reset USB paralell port */
+
ulpt_reset(sc);
+
+ /* set defrag write mode */
+
+ if (fflags & FWRITE) {
+ usb_fifo_set_write_defrag(fifo, 1);
+ }
}
return (unlpt_open(fifo, fflags));
}
@@ -633,6 +677,13 @@
if (error) {
goto detach;
}
+ error = usb_fifo_attach(uaa->device, sc, &sc->sc_mtx,
+ &urlpt_fifo_methods, &sc->sc_fifo_raw,
+ unit, 0 - 1, uaa->info.bIfaceIndex,
+ UID_ROOT, GID_OPERATOR, 0644);
+ if (error) {
+ goto detach;
+ }
/* start reading of status */
mtx_lock(&sc->sc_mtx);
@@ -654,6 +705,7 @@
usb_fifo_detach(&sc->sc_fifo);
usb_fifo_detach(&sc->sc_fifo_noreset);
+ usb_fifo_detach(&sc->sc_fifo_raw);
mtx_lock(&sc->sc_mtx);
usb_callout_stop(&sc->sc_watchdog);
diff -u ./usb_busdma.c ./usb_busdma.c
--- ./usb_busdma.c 2009-06-23 04:19:59.000000000 +0200
+++ ./usb_busdma.c 2009-06-29 13:10:45.000000000 +0200
@@ -359,7 +359,8 @@
if (bus_dma_tag_create
( /* parent */ udt->tag_parent->tag,
/* alignment */ align,
- /* boundary */ USB_PAGE_SIZE,
+ /* boundary */ (align == 1) ?
+ USB_PAGE_SIZE : 0,
/* lowaddr */ (2ULL << (udt->tag_parent->dma_bits - 1)) - 1,
/* highaddr */ BUS_SPACE_MAXADDR,
/* filter */ NULL,
diff -u ./usb_dev.c ./usb_dev.c
--- ./usb_dev.c 2009-06-24 12:59:19.000000000 +0200
+++ ./usb_dev.c 2009-07-05 10:05:59.000000000 +0200
@@ -740,6 +740,8 @@
break;
}
}
+ /* reset have fragment flag */
+ f->flag_have_fragment = 0;
}
/*------------------------------------------------------------------------*
@@ -783,6 +785,16 @@
/* set flushing flag */
f->flag_flushing = 1;
+ /* get the last packet in */
+ if (f->flag_have_fragment) {
+ struct usb_mbuf *m;
+ f->flag_have_fragment = 0;
+ USB_IF_DEQUEUE(&f->free_q, m);
+ if (m) {
+ USB_IF_ENQUEUE(&f->used_q, m);
+ }
+ }
+
/* start write transfer, if not already started */
(f->methods->f_start_write) (f);
@@ -1303,6 +1315,7 @@
struct usb_cdev_privdata* cpd;
struct usb_fifo *f;
struct usb_mbuf *m;
+ uint8_t *pdata;
int fflags;
int resid;
int io_len;
@@ -1373,33 +1386,59 @@
}
tr_data = 1;
- USB_MBUF_RESET(m);
-
- io_len = MIN(m->cur_data_len, uio->uio_resid);
-
- m->cur_data_len = io_len;
+ if (f->flag_have_fragment == 0) {
+ USB_MBUF_RESET(m);
+ io_len = m->cur_data_len;
+ pdata = m->cur_data_ptr;
+ if (io_len > uio->uio_resid)
+ io_len = uio->uio_resid;
+ m->cur_data_len = io_len;
+ } else {
+ io_len = m->max_data_len - m->cur_data_len;
+ pdata = m->cur_data_ptr + io_len;
+ if (io_len > uio->uio_resid)
+ io_len = uio->uio_resid;
+ m->cur_data_len += io_len;
+ }
DPRINTFN(2, "transfer %d bytes to %p\n",
- io_len, m->cur_data_ptr);
+ io_len, pdata);
- err = usb_fifo_uiomove(f,
- m->cur_data_ptr, io_len, uio);
+ err = usb_fifo_uiomove(f, pdata, io_len, uio);
if (err) {
+ f->flag_have_fragment = 0;
USB_IF_ENQUEUE(&f->free_q, m);
break;
}
- if (f->methods->f_filter_write) {
+
+ /* check if the buffer is ready to be transmitted */
+
+ if ((f->flag_write_defrag == 0) ||
+ (m->cur_data_len == m->max_data_len)) {
+ f->flag_have_fragment = 0;
+
/*
- * Sometimes it is convenient to process data at the
- * expense of a userland process instead of a kernel
- * process.
+ * Check for write filter:
+ *
+ * Sometimes it is convenient to process data
+ * at the expense of a userland process
+ * instead of a kernel process.
*/
- (f->methods->f_filter_write) (f, m);
- }
- USB_IF_ENQUEUE(&f->used_q, m);
+ if (f->methods->f_filter_write) {
+ (f->methods->f_filter_write) (f, m);
+ }
- (f->methods->f_start_write) (f);
+ /* Put USB mbuf in the used queue */
+ USB_IF_ENQUEUE(&f->used_q, m);
+
+ /* Start writing data, if not already started */
+ (f->methods->f_start_write) (f);
+ } else {
+ /* Wait for more data or close */
+ f->flag_have_fragment = 1;
+ USB_IF_PREPEND(&f->free_q, m);
+ }
} while (uio->uio_resid > 0);
done:
@@ -2220,6 +2259,18 @@
f->flag_short = onoff;
}
+void
+usb_fifo_set_write_defrag(struct usb_fifo *f, uint8_t onoff)
+{
+ if (f == NULL)
+ return;
+
+ /* defrag written data */
+ f->flag_write_defrag = onoff;
+ /* reset defrag state */
+ f->flag_have_fragment = 0;
+}
+
void *
usb_fifo_softc(struct usb_fifo *f)
{
diff -u ./usb_dev.h ./usb_dev.h
--- ./usb_dev.h 2009-06-24 12:59:19.000000000 +0200
+++ ./usb_dev.h 2009-07-05 10:36:50.000000000 +0200
@@ -130,6 +130,8 @@
uint8_t flag_short; /* set if short_ok or force_short
* transfer flags should be set */
uint8_t flag_stall; /* set if clear stall should be run */
+ uint8_t flag_write_defrag; /* set to defrag written data */
+ uint8_t flag_have_fragment; /* set if defragging */
uint8_t iface_index; /* set to the interface we belong to */
uint8_t fifo_index; /* set to the FIFO index in "struct
* usb_device" */
@@ -144,11 +146,9 @@
int usb_fifo_wait(struct usb_fifo *fifo);
void usb_fifo_signal(struct usb_fifo *fifo);
uint8_t usb_fifo_opened(struct usb_fifo *fifo);
-void usb_fifo_free(struct usb_fifo *f);
struct usb_symlink *usb_alloc_symlink(const char *target);
void usb_free_symlink(struct usb_symlink *ps);
int usb_read_symlink(uint8_t *user_ptr, uint32_t startentry,
uint32_t user_len);
-void usb_fifo_set_close_zlp(struct usb_fifo *, uint8_t);
#endif /* _USB_DEV_H_ */
diff -u ./usbdi.h ./usbdi.h
--- ./usbdi.h 2009-06-28 08:48:04.000000000 +0200
+++ ./usbdi.h 2009-07-05 10:36:50.000000000 +0200
@@ -531,5 +531,8 @@
void usb_fifo_wakeup(struct usb_fifo *f);
void usb_fifo_get_data_error(struct usb_fifo *fifo);
void *usb_fifo_softc(struct usb_fifo *fifo);
+void usb_fifo_set_close_zlp(struct usb_fifo *, uint8_t);
+void usb_fifo_set_write_defrag(struct usb_fifo *, uint8_t);
+void usb_fifo_free(struct usb_fifo *f);
#endif /* _KERNEL */
#endif /* _USB_USBDI_H_ */
--Boundary-00=_3aGUKFo9aO8ZqtK--
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200907051039.19584.hselasky>
