Clarification on kernel builds
by Stan Bubrouski
Hey Guys,
Quick question: Are the kernels that end up in the development tree the
same as the ones on arjan's pages? (I know arjan's are updated more
frequently, but I was wondering before I jump around between them).
-sb
20 years, 3 months
Should there be BuildRequires for perl/libtool/auto*?
by Toshio Kuratomi
Hi, I'm fighting with BuildRequires here and was wondering about the
auto* family of tools. configure checks for them at build time and
during builds of some packages. Are these tools actually needed for
the package to build (ie: should they be a BuildRequire?)
A related question: If I change something up the tool chain (A
configure.in or Makefile.am) should I do my auto*'ing inside the .spec
or do it in my work area before hand and create a patch? The latter
will generate a bigger patch, but it seems cleaner....
-Toshio
--
Toshio <toshio(a)tiki-lounge.com>
20 years, 3 months
RHL9/FC1 USB storage 3 (110872)
by Pete Zaitcev
This was prompted by an IHV who shipped a lot of USB storage
attached to SMPs and is mad as hell that it doesn't work.
Ask ootpa about the fireworks :-)
I am guilty somewhat here. When I and Arjan fixed the last hoopla
with USB CD-ROM on Bladecenters & Dells, we were so distraught
by general misdesign of the code that we didn't go far enough.
It is not in upstream, although it seems clear like day to me.
In fact, I ask you to take it regardless of Matt Dharm's approval.
-- Pete
diff -urN -X dontdiff linux-2.4.22-1.2130.nptl/drivers/usb/storage/scsiglue.c linux-2.4.22-1.2130.nptl-usbstor3/drivers/usb/storage/scsiglue.c
--- linux-2.4.22-1.2130.nptl/drivers/usb/storage/scsiglue.c 2003-06-13 07:51:37.000000000 -0700
+++ linux-2.4.22-1.2130.nptl-usbstor3/drivers/usb/storage/scsiglue.c 2003-12-16 14:04:15.000000000 -0800
@@ -213,9 +213,20 @@
static int device_reset( Scsi_Cmnd *srb )
{
struct us_data *us = (struct us_data *)srb->host->hostdata[0];
+ int rc;
US_DEBUGP("device_reset() called\n" );
- return us->transport_reset(us);
+ spin_unlock_irq(&io_request_lock);
+ down(&(us->dev_semaphore));
+ if (!us->pusb_dev) {
+ up(&(us->dev_semaphore));
+ spin_lock_irq(&io_request_lock);
+ return SUCCESS;
+ }
+ rc = us->transport_reset(us);
+ up(&(us->dev_semaphore));
+ spin_lock_irq(&io_request_lock);
+ return rc;
}
/* This resets the device port, and simulates the device
@@ -230,27 +241,32 @@
/* we use the usb_reset_device() function to handle this for us */
US_DEBUGP("bus_reset() called\n");
+ spin_unlock_irq(&io_request_lock);
+
+ down(&(us->dev_semaphore));
+
/* if the device has been removed, this worked */
if (!us->pusb_dev) {
US_DEBUGP("-- device removed already\n");
+ up(&(us->dev_semaphore));
+ spin_lock_irq(&io_request_lock);
return SUCCESS;
}
- spin_unlock_irq(&io_request_lock);
-
/* release the IRQ, if we have one */
- down(&(us->irq_urb_sem));
if (us->irq_urb) {
US_DEBUGP("-- releasing irq URB\n");
result = usb_unlink_urb(us->irq_urb);
US_DEBUGP("-- usb_unlink_urb() returned %d\n", result);
}
- up(&(us->irq_urb_sem));
/* attempt to reset the port */
if (usb_reset_device(us->pusb_dev) < 0) {
- spin_lock_irq(&io_request_lock);
- return FAILED;
+ /*
+ * Do not return errors, or else the error handler might
+ * invoke host_reset, which is not implemented.
+ */
+ goto bail_out;
}
/* FIXME: This needs to lock out driver probing while it's working
@@ -281,17 +297,18 @@
up(&intf->driver->serialize);
}
+bail_out:
/* re-allocate the IRQ URB and submit it to restore connectivity
* for CBI devices
*/
if (us->protocol == US_PR_CBI) {
- down(&(us->irq_urb_sem));
us->irq_urb->dev = us->pusb_dev;
result = usb_submit_urb(us->irq_urb);
US_DEBUGP("usb_submit_urb() returns %d\n", result);
- up(&(us->irq_urb_sem));
}
-
+
+ up(&(us->dev_semaphore));
+
spin_lock_irq(&io_request_lock);
US_DEBUGP("bus_reset() complete\n");
diff -urN -X dontdiff linux-2.4.22-1.2130.nptl/drivers/usb/storage/usb.c linux-2.4.22-1.2130.nptl-usbstor3/drivers/usb/storage/usb.c
--- linux-2.4.22-1.2130.nptl/drivers/usb/storage/usb.c 2003-12-08 15:50:01.000000000 -0800
+++ linux-2.4.22-1.2130.nptl-usbstor3/drivers/usb/storage/usb.c 2003-12-16 14:01:41.000000000 -0800
@@ -513,6 +513,9 @@
* strucuture is current. This includes the ep_int field, which gives us
* the endpoint for the interrupt.
* Returns non-zero on failure, zero on success
+ *
+ * ss->dev_semaphore is expected taken, except for a newly minted,
+ * unregistered device.
*/
static int usb_stor_allocate_irq(struct us_data *ss)
{
@@ -522,13 +525,9 @@
US_DEBUGP("Allocating IRQ for CBI transport\n");
- /* lock access to the data structure */
- down(&(ss->irq_urb_sem));
-
/* allocate the URB */
ss->irq_urb = usb_alloc_urb(0);
if (!ss->irq_urb) {
- up(&(ss->irq_urb_sem));
US_DEBUGP("couldn't allocate interrupt URB");
return 1;
}
@@ -549,12 +548,9 @@
US_DEBUGP("usb_submit_urb() returns %d\n", result);
if (result) {
usb_free_urb(ss->irq_urb);
- up(&(ss->irq_urb_sem));
return 2;
}
- /* unlock the data structure and return success */
- up(&(ss->irq_urb_sem));
return 0;
}
@@ -782,7 +778,6 @@
init_completion(&(ss->notify));
init_MUTEX_LOCKED(&(ss->ip_waitq));
spin_lock_init(&(ss->queue_exclusion));
- init_MUTEX(&(ss->irq_urb_sem));
init_MUTEX(&(ss->current_urb_sem));
init_MUTEX(&(ss->dev_semaphore));
@@ -1079,7 +1074,6 @@
down(&(ss->dev_semaphore));
/* release the IRQ, if we have one */
- down(&(ss->irq_urb_sem));
if (ss->irq_urb) {
US_DEBUGP("-- releasing irq URB\n");
result = usb_unlink_urb(ss->irq_urb);
@@ -1087,7 +1081,6 @@
usb_free_urb(ss->irq_urb);
ss->irq_urb = NULL;
}
- up(&(ss->irq_urb_sem));
/* free up the main URB for this device */
US_DEBUGP("-- releasing main URB\n");
diff -urN -X dontdiff linux-2.4.22-1.2130.nptl/drivers/usb/storage/usb.h linux-2.4.22-1.2130.nptl-usbstor3/drivers/usb/storage/usb.h
--- linux-2.4.22-1.2130.nptl/drivers/usb/storage/usb.h 2003-12-08 15:50:01.000000000 -0800
+++ linux-2.4.22-1.2130.nptl-usbstor3/drivers/usb/storage/usb.h 2003-12-16 14:01:41.000000000 -0800
@@ -118,7 +118,7 @@
struct us_data *next; /* next device */
/* the device we're working with */
- struct semaphore dev_semaphore; /* protect pusb_dev */
+ struct semaphore dev_semaphore; /* protect many things */
struct usb_device *pusb_dev; /* this usb_device */
unsigned int flags; /* from filter initially */
@@ -164,7 +164,6 @@
atomic_t ip_wanted[1]; /* is an IRQ expected? */
/* interrupt communications data */
- struct semaphore irq_urb_sem; /* to protect irq_urb */
struct urb *irq_urb; /* for USB int requests */
unsigned char irqbuf[2]; /* buffer for USB IRQ */
unsigned char irqdata[2]; /* data from USB IRQ */
20 years, 3 months
FC1 USB printer (110307)
by Pete Zaitcev
This is taken by Greg and is "obviously correct", and it was on
my 2.4 TODO list forever, but the bug requestor is not helping
too much... Your call. Please let me know if you accept or reject
so that I can advance the bug state into MODIFIED or WONTFIX.
-- Pete
--- linux-2.4.23-rc1/drivers/usb/printer.c 2002-11-28 15:53:14.000000000 -0800
+++ linux-2.4.23-rc1-nip/drivers/usb/printer.c 2003-11-19 17:11:37.000000000 -0800
@@ -22,8 +22,11 @@
* v0.7 - fixed bulk-IN read and poll (David Paschal)
* v0.8 - add devfs support
* v0.9 - fix unplug-while-open paths
- * v0.10 - add proto_bias option (Pete Zaitcev)
- * v0.11 - add hpoj.sourceforge.net ioctls (David Paschal)
+ * v0.10- remove sleep_on, fix error on oom (oliver(a)neukum.org)
+ * v0.11 - add proto_bias option (Pete Zaitcev)
+ * v0.12 - add hpoj.sourceforge.net ioctls (David Paschal)
+ * v0.13 - alloc space for statusbuf (<status> not on stack);
+ * use usb_buffer_alloc() for read buf & write buf;
*/
/*
@@ -58,12 +61,12 @@
/*
* Version Information
*/
-#define DRIVER_VERSION "v0.11"
+#define DRIVER_VERSION "v0.13"
#define DRIVER_AUTHOR "Michael Gee, Pavel Machek, Vojtech Pavlik, Randy Dunlap, Pete Zaitcev, David Paschal"
#define DRIVER_DESC "USB Printer Device Class driver"
#define USBLP_BUF_SIZE 8192
-#define DEVICE_ID_SIZE 1024
+#define USBLP_DEVICE_ID_SIZE 1024
/* ioctls: */
#define LPGETSTATUS 0x060b /* same as in drivers/char/lp.c */
@@ -115,12 +118,20 @@
#define USBLP_LAST_PROTOCOL 3
#define USBLP_MAX_PROTOCOLS (USBLP_LAST_PROTOCOL+1)
+/*
+ * some arbitrary status buffer size;
+ * need a status buffer that is allocated via kmalloc(), not on stack
+ */
+#define STATUS_BUF_SIZE 8
+
struct usblp {
struct usb_device *dev; /* USB device */
devfs_handle_t devfs; /* devfs device */
struct semaphore sem; /* locks this struct, especially "dev" */
- char *buf; /* writeurb.transfer_buffer */
- struct urb readurb, writeurb; /* The urbs */
+ char *writebuf; /* write transfer_buffer */
+ char *readbuf; /* read transfer_buffer */
+ char *statusbuf; /* status transfer_buffer */
+ struct urb *readurb, *writeurb; /* The urbs */
wait_queue_head_t wait; /* Zzzzz ... */
int readcount; /* Counter for reads */
int ifnum; /* Interface number */
@@ -133,8 +144,11 @@
} protocol[USBLP_MAX_PROTOCOLS];
int current_protocol;
int minor; /* minor number of device */
+ int wcomplete; /* writing is completed */
+ int rcomplete; /* reading is completed */
unsigned int quirks; /* quirks flags */
unsigned char used; /* True if open */
+ unsigned char present; /* True if not disconnected */
unsigned char bidir; /* interface is bidirectional */
unsigned char *device_id_string; /* IEEE 1284 DEVICE ID string (ptr) */
/* first 2 bytes are (big-endian) length */
@@ -146,8 +160,11 @@
dbg("usblp=0x%p", usblp);
dbg("dev=0x%p", usblp->dev);
- dbg("devfs=0x%p", usblp->devfs);
- dbg("buf=0x%p", usblp->buf);
+ dbg("present=%d", usblp->present);
+ dbg("readbuf=0x%p", usblp->readbuf);
+ dbg("writebuf=0x%p", usblp->writebuf);
+ dbg("readurb=0x%p", usblp->readurb);
+ dbg("writeurb=0x%p", usblp->writeurb);
dbg("readcount=%d", usblp->readcount);
dbg("ifnum=%d", usblp->ifnum);
for (p = USBLP_FIRST_PROTOCOL; p <= USBLP_LAST_PROTOCOL; p++) {
@@ -157,6 +174,8 @@
}
dbg("current_protocol=%d", usblp->current_protocol);
dbg("minor=%d", usblp->minor);
+ dbg("wcomplete=%d", usblp->wcomplete);
+ dbg("rcomplete=%d", usblp->rcomplete);
dbg("quirks=%d", usblp->quirks);
dbg("used=%d", usblp->used);
dbg("bidir=%d", usblp->bidir);
@@ -239,17 +258,31 @@
* URB callback.
*/
-static void usblp_bulk(struct urb *urb)
+static void usblp_bulk_read(struct urb *urb)
{
struct usblp *usblp = urb->context;
- if (!usblp || !usblp->dev || !usblp->used)
+ if (!usblp || !usblp->dev || !usblp->used || !usblp->present)
return;
- if (urb->status)
+ if (unlikely(urb->status))
warn("usblp%d: nonzero read/write bulk status received: %d",
usblp->minor, urb->status);
+ usblp->rcomplete = 1;
+ wake_up_interruptible(&usblp->wait);
+}
+
+static void usblp_bulk_write(struct urb *urb)
+{
+ struct usblp *usblp = urb->context;
+
+ if (!usblp || !usblp->dev || !usblp->used || !usblp->present)
+ return;
+ if (unlikely(urb->status))
+ warn("usblp%d: nonzero read/write bulk status received: %d",
+ usblp->minor, urb->status);
+ usblp->wcomplete = 1;
wake_up_interruptible(&usblp->wait);
}
@@ -257,25 +290,28 @@
* Get and print printer errors.
*/
-static char *usblp_messages[] = { "ok", "out of paper", "off-line", "unknown error" };
+static char *usblp_messages[] = { "ok", "out of paper", "off-line", "on fire" };
static int usblp_check_status(struct usblp *usblp, int err)
{
unsigned char status, newerr = 0;
int error;
- error = usblp_read_status (usblp, &status);
+ error = usblp_read_status (usblp, usblp->statusbuf);
if (error < 0) {
err("usblp%d: error %d reading printer status",
usblp->minor, error);
return 0;
}
- if (~status & LP_PERRORP) {
+ status = *usblp->statusbuf;
+
+ if (~status & LP_PERRORP)
newerr = 3;
- if (status & LP_POUTPA) newerr = 1;
- if (~status & LP_PSELECD) newerr = 2;
- }
+ if (status & LP_POUTPA)
+ newerr = 1;
+ if (~status & LP_PSELECD)
+ newerr = 2;
if (newerr != err)
info("usblp%d: %s", usblp->minor, usblp_messages[newerr]);
@@ -300,7 +336,7 @@
usblp = usblp_table[minor];
retval = -ENODEV;
- if (!usblp || !usblp->dev)
+ if (!usblp || !usblp->dev || !usblp->present)
goto out;
retval = -EBUSY;
@@ -324,13 +360,14 @@
usblp->used = 1;
file->private_data = usblp;
- usblp->writeurb.transfer_buffer_length = 0;
- usblp->writeurb.status = 0;
+ usblp->writeurb->transfer_buffer_length = 0;
+ usblp->wcomplete = 1; /* we begin writeable */
+ usblp->rcomplete = 0;
if (usblp->bidir) {
usblp->readcount = 0;
- usblp->readurb.dev = usblp->dev;
- if (usb_submit_urb(&usblp->readurb) < 0) {
+ usblp->readurb->dev = usblp->dev;
+ if (usb_submit_urb(usblp->readurb) < 0) {
retval = -EIO;
usblp->used = 0;
file->private_data = NULL;
@@ -347,16 +384,20 @@
usblp_table [usblp->minor] = NULL;
info("usblp%d: removed", usblp->minor);
- kfree (usblp->writeurb.transfer_buffer);
+ kfree (usblp->writebuf);
+ kfree (usblp->readbuf);
kfree (usblp->device_id_string);
+ kfree (usblp->statusbuf);
+ usb_free_urb(usblp->writeurb);
+ usb_free_urb(usblp->readurb);
kfree (usblp);
}
static void usblp_unlink_urbs(struct usblp *usblp)
{
- usb_unlink_urb(&usblp->writeurb);
+ usb_unlink_urb(usblp->writeurb);
if (usblp->bidir)
- usb_unlink_urb(&usblp->readurb);
+ usb_unlink_urb(usblp->readurb);
}
static int usblp_release(struct inode *inode, struct file *file)
@@ -366,7 +407,7 @@
down (&usblp->sem);
lock_kernel();
usblp->used = 0;
- if (usblp->dev) {
+ if (usblp->present) {
usblp_unlink_urbs(usblp);
up(&usblp->sem);
} else /* finish cleanup from disconnect */
@@ -380,21 +421,21 @@
{
struct usblp *usblp = file->private_data;
poll_wait(file, &usblp->wait, wait);
- return ((!usblp->bidir || usblp->readurb.status == -EINPROGRESS) ? 0 : POLLIN | POLLRDNORM)
- | (usblp->writeurb.status == -EINPROGRESS ? 0 : POLLOUT | POLLWRNORM);
+ return ((!usblp->bidir || !usblp->rcomplete) ? 0 : POLLIN | POLLRDNORM)
+ | (!usblp->wcomplete ? 0 : POLLOUT | POLLWRNORM);
}
static int usblp_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
{
struct usblp *usblp = file->private_data;
int length, err, i;
- unsigned char lpstatus, newChannel;
+ unsigned char newChannel;
int status;
int twoints[2];
int retval = 0;
down (&usblp->sem);
- if (!usblp->dev) {
+ if (!usblp->present) {
retval = -ENODEV;
goto done;
}
@@ -534,18 +575,18 @@
break;
default:
- retval = -EINVAL;
+ retval = -ENOTTY;
}
else /* old-style ioctl value */
switch (cmd) {
case LPGETSTATUS:
- if (usblp_read_status(usblp, &lpstatus)) {
+ if (usblp_read_status(usblp, usblp->statusbuf)) {
err("usblp%d: failed reading printer status", usblp->minor);
retval = -EIO;
goto done;
}
- status = lpstatus;
+ status = *usblp->statusbuf;
if (copy_to_user ((int *)arg, &status, sizeof(int)))
retval = -EFAULT;
break;
@@ -561,41 +602,48 @@
static ssize_t usblp_write(struct file *file, const char *buffer, size_t count, loff_t *ppos)
{
+ DECLARE_WAITQUEUE(wait, current);
struct usblp *usblp = file->private_data;
int timeout, err = 0;
size_t writecount = 0;
while (writecount < count) {
-
- // FIXME: only use urb->status inside completion
- // callbacks; this way is racey...
- if (usblp->writeurb.status == -EINPROGRESS) {
-
+ if (!usblp->wcomplete) {
+ barrier();
if (file->f_flags & O_NONBLOCK)
return -EAGAIN;
timeout = USBLP_WRITE_TIMEOUT;
- while (timeout && usblp->writeurb.status == -EINPROGRESS) {
+ add_wait_queue(&usblp->wait, &wait);
+ while ( 1==1 ) {
- if (signal_pending(current))
+ if (signal_pending(current)) {
+ remove_wait_queue(&usblp->wait, &wait);
return writecount ? writecount : -EINTR;
-
- timeout = interruptible_sleep_on_timeout(&usblp->wait, timeout);
+ }
+ set_current_state(TASK_INTERRUPTIBLE);
+ if (timeout && !usblp->wcomplete) {
+ timeout = schedule_timeout(timeout);
+ } else {
+ set_current_state(TASK_RUNNING);
+ break;
+ }
}
+ remove_wait_queue(&usblp->wait, &wait);
}
down (&usblp->sem);
- if (!usblp->dev) {
+ if (!usblp->present) {
up (&usblp->sem);
return -ENODEV;
}
- if (usblp->writeurb.status != 0) {
+ if (usblp->writeurb->status != 0) {
if (usblp->quirks & USBLP_QUIRK_BIDIR) {
- if (usblp->writeurb.status != -EINPROGRESS)
+ if (!usblp->wcomplete)
err("usblp%d: error %d writing to printer",
- usblp->minor, usblp->writeurb.status);
- err = usblp->writeurb.status;
+ usblp->minor, usblp->writeurb->status);
+ err = usblp->writeurb->status;
} else
err = usblp_check_status(usblp, err);
up (&usblp->sem);
@@ -607,25 +655,30 @@
continue;
}
- writecount += usblp->writeurb.transfer_buffer_length;
- usblp->writeurb.transfer_buffer_length = 0;
+ writecount += usblp->writeurb->transfer_buffer_length;
+ usblp->writeurb->transfer_buffer_length = 0;
if (writecount == count) {
up (&usblp->sem);
break;
}
- usblp->writeurb.transfer_buffer_length = (count - writecount) < USBLP_BUF_SIZE ?
- (count - writecount) : USBLP_BUF_SIZE;
+ usblp->writeurb->transfer_buffer_length = (count - writecount) < USBLP_BUF_SIZE ?
+ (count - writecount) : USBLP_BUF_SIZE;
- if (copy_from_user(usblp->writeurb.transfer_buffer, buffer + writecount,
- usblp->writeurb.transfer_buffer_length)) {
+ if (copy_from_user(usblp->writeurb->transfer_buffer, buffer + writecount,
+ usblp->writeurb->transfer_buffer_length)) {
up(&usblp->sem);
return writecount ? writecount : -EFAULT;
}
- usblp->writeurb.dev = usblp->dev;
- usb_submit_urb(&usblp->writeurb);
+ usblp->writeurb->dev = usblp->dev;
+ usblp->wcomplete = 0;
+ if (usb_submit_urb(usblp->writeurb)) {
+ count = -EIO;
+ up (&usblp->sem);
+ break;
+ }
up (&usblp->sem);
}
@@ -635,63 +688,77 @@
static ssize_t usblp_read(struct file *file, char *buffer, size_t count, loff_t *ppos)
{
struct usblp *usblp = file->private_data;
+ DECLARE_WAITQUEUE(wait, current);
if (!usblp->bidir)
return -EINVAL;
down (&usblp->sem);
- if (!usblp->dev) {
+ if (!usblp->present) {
count = -ENODEV;
goto done;
}
- if (usblp->readurb.status == -EINPROGRESS) {
+ if (!usblp->rcomplete) {
+ barrier();
if (file->f_flags & O_NONBLOCK) {
count = -EAGAIN;
goto done;
}
- // FIXME: only use urb->status inside completion
- // callbacks; this way is racey...
- while (usblp->readurb.status == -EINPROGRESS) {
+ add_wait_queue(&usblp->wait, &wait);
+ while (1==1) {
if (signal_pending(current)) {
count = -EINTR;
+ remove_wait_queue(&usblp->wait, &wait);
goto done;
}
up (&usblp->sem);
- interruptible_sleep_on(&usblp->wait);
+ set_current_state(TASK_INTERRUPTIBLE);
+ if (!usblp->rcomplete) {
+ schedule();
+ } else {
+ set_current_state(TASK_RUNNING);
+ break;
+ }
down (&usblp->sem);
}
+ remove_wait_queue(&usblp->wait, &wait);
}
- if (!usblp->dev) {
+ if (!usblp->present) {
count = -ENODEV;
goto done;
}
- if (usblp->readurb.status) {
+ if (usblp->readurb->status) {
err("usblp%d: error %d reading from printer",
- usblp->minor, usblp->readurb.status);
- usblp->readurb.dev = usblp->dev;
+ usblp->minor, usblp->readurb->status);
+ usblp->readurb->dev = usblp->dev;
usblp->readcount = 0;
- usb_submit_urb(&usblp->readurb);
+ if (usb_submit_urb(usblp->readurb) < 0)
+ dbg("error submitting urb");
count = -EIO;
goto done;
}
- count = count < usblp->readurb.actual_length - usblp->readcount ?
- count : usblp->readurb.actual_length - usblp->readcount;
+ count = count < usblp->readurb->actual_length - usblp->readcount ?
+ count : usblp->readurb->actual_length - usblp->readcount;
- if (copy_to_user(buffer, usblp->readurb.transfer_buffer + usblp->readcount, count)) {
+ if (copy_to_user(buffer, usblp->readurb->transfer_buffer + usblp->readcount, count)) {
count = -EFAULT;
goto done;
}
- if ((usblp->readcount += count) == usblp->readurb.actual_length) {
+ if ((usblp->readcount += count) == usblp->readurb->actual_length) {
usblp->readcount = 0;
- usblp->readurb.dev = usblp->dev;
- usb_submit_urb(&usblp->readurb);
+ usblp->readurb->dev = usblp->dev;
+ usblp->rcomplete = 0;
+ if (usb_submit_urb(usblp->readurb)) {
+ count = -EIO;
+ goto done;
+ }
}
done:
@@ -766,19 +833,42 @@
}
}
+ usblp->writeurb = usb_alloc_urb(0);
+ if (!usblp->writeurb) {
+ err("out of memory");
+ goto abort;
+ }
+ usblp->readurb = usb_alloc_urb(0);
+ if (!usblp->readurb) {
+ err("out of memory");
+ goto abort;
+ }
+
/* Malloc device ID string buffer to the largest expected length,
* since we can re-query it on an ioctl and a dynamic string
* could change in length. */
- if (!(usblp->device_id_string = kmalloc(DEVICE_ID_SIZE, GFP_KERNEL))) {
+ if (!(usblp->device_id_string = kmalloc(USBLP_DEVICE_ID_SIZE, GFP_KERNEL))) {
err("out of memory for device_id_string");
goto abort;
}
- /* Malloc write/read buffers in one chunk. We somewhat wastefully
+ usblp->writebuf = usblp->readbuf = NULL;
+ /* Malloc write & read buffers. We somewhat wastefully
* malloc both regardless of bidirectionality, because the
* alternate setting can be changed later via an ioctl. */
- if (!(usblp->buf = kmalloc(2 * USBLP_BUF_SIZE, GFP_KERNEL))) {
- err("out of memory for buf");
+ if (!(usblp->writebuf = kmalloc(USBLP_BUF_SIZE, GFP_KERNEL))) {
+ err("out of memory for write buf");
+ goto abort;
+ }
+ if (!(usblp->readbuf = kmalloc(USBLP_BUF_SIZE, GFP_KERNEL))) {
+ err("out of memory for read buf");
+ goto abort;
+ }
+
+ /* Allocate buffer for printer status */
+ usblp->statusbuf = kmalloc(STATUS_BUF_SIZE, GFP_KERNEL);
+ if (!usblp->statusbuf) {
+ err("out of memory for statusbuf");
goto abort;
}
@@ -818,17 +908,26 @@
info("usblp%d: USB %sdirectional printer dev %d "
"if %d alt %d proto %d vid 0x%4.4X pid 0x%4.4X",
- usblp->minor, usblp->bidir ? "Bi" : "Uni", dev->devnum, ifnum,
+ usblp->minor, usblp->bidir ? "Bi" : "Uni", dev->devnum,
+ usblp->ifnum,
usblp->protocol[usblp->current_protocol].alt_setting,
usblp->current_protocol, usblp->dev->descriptor.idVendor,
usblp->dev->descriptor.idProduct);
+ usblp->present = 1;
+
return usblp;
abort:
if (usblp) {
- if (usblp->buf) kfree(usblp->buf);
- if (usblp->device_id_string) kfree(usblp->device_id_string);
+ if (usblp->writebuf)
+ kfree (usblp->writebuf);
+ if (usblp->readbuf)
+ kfree (usblp->readbuf);
+ kfree(usblp->statusbuf);
+ kfree(usblp->device_id_string);
+ usb_free_urb(usblp->writeurb);
+ usb_free_urb(usblp->readurb);
kfree(usblp);
}
return NULL;
@@ -943,19 +1042,19 @@
return r;
}
- FILL_BULK_URB(&usblp->writeurb, usblp->dev,
+ usb_fill_bulk_urb(usblp->writeurb, usblp->dev,
usb_sndbulkpipe(usblp->dev,
- usblp->protocol[protocol].epwrite->bEndpointAddress),
- usblp->buf, 0,
- usblp_bulk, usblp);
+ usblp->protocol[protocol].epwrite->bEndpointAddress),
+ usblp->writebuf, 0,
+ usblp_bulk_write, usblp);
usblp->bidir = (usblp->protocol[protocol].epread != 0);
if (usblp->bidir)
- FILL_BULK_URB(&usblp->readurb, usblp->dev,
+ usb_fill_bulk_urb(usblp->readurb, usblp->dev,
usb_rcvbulkpipe(usblp->dev,
- usblp->protocol[protocol].epread->bEndpointAddress),
- usblp->buf + USBLP_BUF_SIZE, USBLP_BUF_SIZE,
- usblp_bulk, usblp);
+ usblp->protocol[protocol].epread->bEndpointAddress),
+ usblp->readbuf, USBLP_BUF_SIZE,
+ usblp_bulk_read, usblp);
usblp->current_protocol = protocol;
dbg("usblp%d set protocol %d", usblp->minor, protocol);
@@ -969,7 +1068,7 @@
{
int err, length;
- err = usblp_get_id(usblp, 0, usblp->device_id_string, DEVICE_ID_SIZE - 1);
+ err = usblp_get_id(usblp, 0, usblp->device_id_string, USBLP_DEVICE_ID_SIZE - 1);
if (err < 0) {
dbg("usblp%d: error = %d reading IEEE-1284 Device ID string",
usblp->minor, err);
@@ -983,8 +1082,8 @@
length = (usblp->device_id_string[0] << 8) + usblp->device_id_string[1];
if (length < 2)
length = 2;
- else if (length >= DEVICE_ID_SIZE)
- length = DEVICE_ID_SIZE - 1;
+ else if (length >= USBLP_DEVICE_ID_SIZE)
+ length = USBLP_DEVICE_ID_SIZE - 1;
usblp->device_id_string[length] = '\0';
dbg("usblp%d Device ID string [len=%d]=\"%s\"",
@@ -1004,13 +1103,13 @@
down (&usblp->sem);
lock_kernel();
- usblp->dev = NULL;
+ usblp->present = 0;
usblp_unlink_urbs(usblp);
if (!usblp->used)
usblp_cleanup (usblp);
- else /* cleanup later, on close */
+ else /* cleanup later, on release */
up (&usblp->sem);
unlock_kernel();
}
20 years, 3 months
RHL9/FC1 USB serial helper (90442 et. al.)
by Pete Zaitcev
This comes from RHL9, but is applicable to Fedora.
The patch is extensive and solves actual oopses, expirienced
by many users (look at the list of dups for 90442). It did not
come out as I would envision it, but overhauling whole usbserial
with all component drivers is just no feasible at this time.
It pains to ask, but I would like you to take it.
-- Pete
diff -ur linux-2.4.20-20.7.5/drivers/usb/serial/usbserial.c linux-2.4.20-20.7.5-u1/drivers/usb/serial/usbserial.c
--- linux-2.4.20-20.7.5/drivers/usb/serial/usbserial.c 2003-11-17 22:30:34.000000000 -0500
+++ linux-2.4.20-20.7.5-u1/drivers/usb/serial/usbserial.c 2003-11-17 22:33:16.000000000 -0500
@@ -297,6 +297,7 @@
#include <linux/spinlock.h>
#include <linux/list.h>
#include <linux/smp_lock.h>
+#include <linux/spinlock.h>
#include <linux/usb.h>
#ifdef CONFIG_USB_SERIAL_DEBUG
@@ -347,10 +348,24 @@
};
#endif
+/*
+ * The post kludge structures and variables.
+ */
+#define POST_BSIZE 100 /* little below 128 in total */
+struct usb_serial_post_job {
+ struct list_head link;
+ struct usb_serial_port *port;
+ int len;
+ char buff[POST_BSIZE];
+};
+static spinlock_t post_lock = SPIN_LOCK_UNLOCKED; /* Also covers ->ref */
+static struct list_head post_list = LIST_HEAD_INIT(post_list);
+static struct tq_struct post_task;
/* local function prototypes */
static int serial_open (struct tty_struct *tty, struct file * filp);
static void serial_close (struct tty_struct *tty, struct file * filp);
+static int __serial_write (struct usb_serial_port *port, int from_user, const unsigned char *buf, int count);
static int serial_write (struct tty_struct * tty, int from_user, const unsigned char *buf, int count);
static int serial_write_room (struct tty_struct *tty);
static int serial_chars_in_buffer (struct tty_struct *tty);
@@ -448,6 +463,53 @@
return;
}
+/*
+ * The post kludge.
+ *
+ * Our component drivers are hideously buggy and written by people
+ * who have difficulty understanding the concept of spinlocks.
+ * There were so many races and lockups that Greg K-H made a watershed
+ * decision to provide what is essentially a single-threaded sandbox
+ * for component drivers, protected by a semaphore. It helped a lot, but
+ * for one little problem: when tty->low_latency is set, line disciplines
+ * can call ->write from an interrupt, where the semaphore oopses.
+ *
+ * Rather than open the whole can of worms again, we just post writes
+ * into a helper which can sleep.
+ *
+ * Kernel 2.6 has a proper fix, reportedly.
+ *
+ * XXX Nothing prevents this from looping forever.
+ */
+static void post_helper(void *arg)
+{
+ struct usb_serial_post_job *job;
+ struct usb_serial_port *port;
+ struct usb_serial *serial;
+ unsigned int flags;
+
+ spin_lock_irqsave(&post_lock, flags);
+ while (!list_empty(&post_list)) {
+ job = list_entry(post_list.next, struct usb_serial_post_job, link);
+ list_del(&job->link);
+ spin_unlock_irqrestore(&post_lock, flags);
+
+ port = job->port;
+ serial = get_usb_serial (port, __FUNCTION__);
+
+ down(&port->sem);
+ if (port->tty != NULL)
+ __serial_write(port, 0, job->buff, job->len);
+ up(&port->sem);
+
+ kfree(job);
+ spin_lock_irqsave(&post_lock, flags);
+ if (--serial->ref == 0)
+ kfree(serial);
+ }
+ spin_unlock_irqrestore(&post_lock, flags);
+}
+
#ifdef USES_EZUSB_FUNCTIONS
/* EZ-USB Control and Status Register. Bit 0 controls 8051 reset */
#define CPUCS_REG 0x7F92
@@ -576,23 +638,21 @@
/* if disconnect beat us to the punch here, there's nothing to do */
if (tty->driver_data) {
+ /* post_helper(NULL); */ /* Correct, but unimportant for echo.*/
__serial_close(port, filp);
}
up (&port->sem);
}
-static int serial_write (struct tty_struct * tty, int from_user, const unsigned char *buf, int count)
+static int __serial_write (struct usb_serial_port *port, int from_user, const unsigned char *buf, int count)
{
- struct usb_serial_port *port = (struct usb_serial_port *) tty->driver_data;
struct usb_serial *serial = get_usb_serial (port, __FUNCTION__);
int retval = -EINVAL;
if (!serial)
return -ENODEV;
- down (&port->sem);
-
dbg("%s - port %d, %d byte(s)", __FUNCTION__, port->number, count);
if (!port->open_count) {
@@ -607,10 +667,68 @@
retval = generic_write(port, from_user, buf, count);
exit:
- up (&port->sem);
return retval;
}
+static int serial_write (struct tty_struct * tty, int from_user, const unsigned char *buf, int count)
+{
+ struct usb_serial_port *port = (struct usb_serial_port *) tty->driver_data;
+ struct usb_serial *serial = get_usb_serial (port, __FUNCTION__);
+ struct usb_serial_post_job *job;
+ unsigned long flags;
+ int rc;
+
+ if (!in_interrupt()) {
+ /*
+ * Run post_list to reduce a possiblity of reordered writes.
+ * Tasks can make keventd to sleep, sometimes for a long time.
+ */
+ post_helper(NULL);
+
+ down(&port->sem);
+ rc = __serial_write(port, from_user, buf, count);
+ up(&port->sem);
+ return rc;
+ }
+
+ if (from_user) {
+ /*
+ * This is a BUG-able offense because we cannot
+ * pagefault while in_interrupt, but we want to see
+ * something in dmesg rather than just blinking LEDs.
+ */
+ err("user data in interrupt write");
+ return -EINVAL;
+ }
+
+ job = kmalloc(sizeof(struct usb_serial_post_job), GFP_ATOMIC);
+ if (job == NULL)
+ return -ENOMEM;
+
+ job->port = port;
+ if ((job->len = count) >= POST_BSIZE) {
+ static int rate = 0;
+ /*
+ * Data loss due to extreme circumstances.
+ * It's a ususal thing on serial to lose characters, isn't it?
+ * Neener, neener! Actually, it's probably an echo loop anyway.
+ * Only happens when getty starts talking to Visor.
+ */
+ if (++rate % 1000 < 5)
+ err("too much data (%d)", count);
+ job->len = POST_BSIZE;
+ }
+ memcpy(job->buff, buf, job->len);
+
+ spin_lock_irqsave(&post_lock, flags);
+ list_add_tail(&job->link, &post_list);
+ serial->ref++; /* Protect the port->sem from kfree() */
+ schedule_task(&post_task);
+ spin_unlock_irqrestore(&post_lock, flags);
+
+ return count;
+}
+
static int serial_write_room (struct tty_struct *tty)
{
struct usb_serial_port *port = (struct usb_serial_port *) tty->driver_data;
@@ -620,6 +738,9 @@
if (!serial)
return -ENODEV;
+ if (in_interrupt())
+ return POST_BSIZE;
+
down (&port->sem);
dbg("%s - port %d", __FUNCTION__, port->number);
@@ -1128,6 +1249,7 @@
int num_ports;
int max_endpoints;
const struct usb_device_id *id_pattern = NULL;
+ unsigned long flags;
/* loop through our list of known serial converters, and see if this
device matches. */
@@ -1338,11 +1460,15 @@
init_MUTEX (&port->sem);
}
+ spin_lock_irqsave(&post_lock, flags);
+ serial->ref = 1;
+ spin_unlock_irqrestore(&post_lock, flags);
+
/* if this device type has a startup function, call it */
if (type->startup) {
i = type->startup (serial);
if (i < 0)
- goto probe_error;
+ goto startup_error;
if (i > 0)
return serial;
}
@@ -1357,6 +1483,12 @@
return serial; /* success */
+startup_error:
+ spin_lock_irqsave(&post_lock, flags);
+ if (serial->ref != 1) {
+ err("bug in component startup: ref %d\n", serial->ref);
+ }
+ spin_unlock_irqrestore(&post_lock, flags);
probe_error:
for (i = 0; i < num_bulk_in; ++i) {
port = &serial->port[i];
@@ -1392,6 +1524,7 @@
{
struct usb_serial *serial = (struct usb_serial *) ptr;
struct usb_serial_port *port;
+ unsigned long flags;
int i;
dbg ("%s", __FUNCTION__);
@@ -1452,7 +1585,10 @@
return_serial (serial);
/* free up any memory that we allocated */
- kfree (serial);
+ spin_lock_irqsave(&post_lock, flags);
+ if (--serial->ref == 0)
+ kfree(serial);
+ spin_unlock_irqrestore(&post_lock, flags);
} else {
info("device disconnected");
@@ -1504,6 +1640,7 @@
for (i = 0; i < SERIAL_TTY_MINORS; ++i) {
serial_table[i] = NULL;
}
+ post_task.routine = post_helper;
/* register the tty driver */
serial_tty_driver.init_termios = tty_std_termios;
diff -ur linux-2.4.20-20.7.5/drivers/usb/serial/usb-serial.h linux-2.4.20-20.7.5-u1/drivers/usb/serial/usb-serial.h
--- linux-2.4.20-20.7.5/drivers/usb/serial/usb-serial.h 2002-11-28 18:53:15.000000000 -0500
+++ linux-2.4.20-20.7.5-u1/drivers/usb/serial/usb-serial.h 2003-11-17 22:32:55.000000000 -0500
@@ -151,6 +151,9 @@
__u16 product;
struct usb_serial_port port[MAX_NUM_PORTS];
void * private;
+#ifndef __GENKSYMS__
+ int ref;
+#endif
};
20 years, 3 months
FC1 USB serial visors (107929)
by Pete Zaitcev
This is a straightforward backport from 2.4.23. Seems like something
we better have.
-- Pete
diff -ur -X dontdiff linux-2.4.22-1.2130.nptl/drivers/usb/serial/usbserial.c linux-2.4.23/drivers/usb/serial/usbserial.c
--- linux-2.4.22-1.2130.nptl/drivers/usb/serial/usbserial.c 2003-08-25 04:44:42.000000000 -0700
+++ linux-2.4.23/drivers/usb/serial/usbserial.c 2003-11-29 18:53:05.000000000 -0800
@@ -2,8 +2,8 @@
* USB Serial Converter driver
*
* Copyright (C) 1999 - 2002 Greg Kroah-Hartman (greg(a)kroah.com)
- * Copyright (c) 2000 Peter Berger (pberger(a)brimson.com)
- * Copyright (c) 2000 Al Borchers (borchers(a)steinerpoint.com)
+ * Copyright (C) 2000 Peter Berger (pberger(a)brimson.com)
+ * Copyright (C) 2000 Al Borchers (borchers(a)steinerpoint.com)
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License version
@@ -556,7 +556,10 @@
else
generic_close(port, filp);
port->open_count = 0;
- port->tty = NULL;
+ if (port->tty) {
+ port->tty->driver_data = NULL;
+ port->tty = NULL;
+ }
}
if (port->serial->type->owner)
@@ -1401,12 +1404,9 @@
for (i = 0; i < serial->num_ports; ++i) {
port = &serial->port[i];
down (&port->sem);
- if (port->tty != NULL) {
- while (port->open_count > 0) {
+ if (port->tty != NULL)
+ while (port->open_count > 0)
__serial_close(port, NULL);
- }
- port->tty->driver_data = NULL;
- }
up (&port->sem);
}
20 years, 3 months
Re: FC2 initial schedule posted
by Pete Zaitcev
>>Finalizing the new set of leaders was taking longer than I had hoped,
>>so we just picked an ad-hoc committee of Red Hat and external people
>>and hammered out a schedule last week, and then refined it a bit
>>afterward. Here it is:
>>
>>http://fedora.redhat.com/participate/schedule/
>>
> I noticed the beautiful word *SPARC* in there.
Tangentially, what about ia64? I am asking because due to
curcomstances outside of my control I am about to receive
an Itanium workstation which will be my primary development box.
I saw in list archives that MKJ dismissed s390 already,
so that's a relief...
-- Pete
20 years, 3 months
rawhide questions
by Matthew T. O'Connor
Hello, I just installed a fresh copy of the fedora development version
onto a separate partition on my PC. I downloaded the 5MB boot.iso and
did a network install. Install went fine, but I have a few questions /
problems which might all be expected.
mouse is too fast - I have a USB Optical MS Intellimouse, works fine
under FC1 with the 2.4 kernel. When I tried out arjan's 2.6 test kernel
on FC1 I had the same problem. The mouse is very fast (sensitive), to
the point that it's barely useable. Perhaps there is a way to configure
this, but I don't know it.
no sound - since we are on 2.6, I would guess we are using ALSA, but
none of the alsa utilities were installed, I assume this just hasn't
been done yet. system-config-sound properly identifies my hardware, but
I get no sound.
system-config-users crashes: when I run it, I get this:
Traceback (most recent call last):
File "/usr/share/system-config-users/system-config-users.py", line 25,
in ?
import libuser
ImportError: No module named libuser
xmms crashes - I just get a message that there was a Segmentation fault.
Any feedback would be appreciated. If I get the mouse and the sound
worked out, I would be happy to keep using, testing and reporting
problems with the development versions of FC.
Thanks much,
Matthew
20 years, 3 months
Proposal: Discourage rpmbuild --sign
by Warren Togami
Proposal
========
rpm-4.2.2 in rawhide and all future versions should discourage the use
of rpmbuild --sign. Perhaps this can be done effectively by adding a
large and annoying warning message and 15 second delay. Or disable it
completely. I don't care how, just discouragement should be done.
Why?
By allowing rpmbuild --sign to be not annoying, then people tend to
think that it is the proper way to build and sign packages. This is
totally not the case for one key reason: Safety.
It is possible, however unlikely, that trojans hiding within SRPMS that
you build could steal your GPG keys since they are running as the same
user as the GPG signing keys. They have access to memory used by gnupg,
as well as access to the files in ~/.gnupg. The passphrases can be
stolen, or the files themselves stolen and passphrase cracked. (It is a
lot easier to crack a passphrase when you have both the private and
public key.)
When a user attempts rpmbuild --sign, the warning message should
indicate that it is bad, and to read a webpage at rpm.org for more
information. That webpage should explain in detail why it is a bad
practice, and the following proper safer procedure.
1) rpmbuild as non-root user foo.
2) Copy the packages to non-root user foobar.
3) Use rpm --addsign to sign packages as non-root user foobar.
Protection of GPG keys must be of the highest importance, and I know for
a fact that some of the popular 3rd party repositories are still using
rpmbuild --sign. The risk to the community is just too great, and the
mitigating fix for this is exceedingly simple.
Sane idea?
Warren Togami
warren(a)togami.com
20 years, 3 months