Skip site navigation (1)Skip section navigation (2)
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>