Commit 40b1df3a authored by Linus Torvalds's avatar Linus Torvalds

v2.5.0.3 -> v2.5.0.4

- Jens Axboe: fix up bio highmem breakage, more cleanups
- Greg KH: USB update
parent 4d6c7b36
......@@ -110,6 +110,7 @@ APISOURCES := $(TOPDIR)/drivers/media/video/videodev.c \
$(TOPDIR)/fs/locks.c \
$(TOPDIR)/fs/bio.c \
$(TOPDIR)/include/asm-i386/bitops.h \
$(TOPDIR)/include/linux/usb.h \
$(TOPDIR)/kernel/pm.c \
$(TOPDIR)/kernel/ksyms.c \
$(TOPDIR)/kernel/kmod.c \
......
......@@ -205,7 +205,82 @@
<chapter id="usb">
<title>USB Devices</title>
<para>Drivers for USB devices talk to the "usbcore" APIs, and are
exposed through driver frameworks such as block, character,
or network devices.
There are two types of public "usbcore" APIs: those intended for
general driver use, and those which are only public to drivers that
are part of the core.
The drivers that are part of the core are involved in managing a USB bus.
They include the "hub" driver, which manages trees of USB devices, and
several different kinds of "host controller" driver (HCD), which control
individual busses.
</para>
<para>The device model seen by USB drivers is relatively complex.
</para>
<itemizedlist>
<listitem><para>USB supports four kinds of data transfer
(control, bulk, interrupt, and isochronous). Two transfer
types use bandwidth as it's available (control and bulk),
while the other two types of transfer (interrupt and isochronous)
are scheduled to provide guaranteed bandwidth.
</para></listitem>
<listitem><para>The device description model includes one or more
"configurations" per device, only one of which is active at a time.
</para></listitem>
<listitem><para>Configurations have one or more "interface", each
of which may have "alternate settings". Interfaces may be
standardized by USB "Class" specifications, or may be specific to
a vendor or device.</para>
<para>USB device drivers actually bind to interfaces, not devices.
Think of them as "interface drivers", though you
may not see many devices where the distinction is important.
Most USB devices are simple, with only one configuration,
one interface, and one alternate setting.
</para></listitem>
<listitem><para>Interfaces have one or more "endpoints", each of
which supports one type and direction of data transfer such as
"bulk out" or "interrupt in". The entire configuration may have
up to sixteen endpoints in each direction, allocated as needed
among all the interfaces.
</para></listitem>
<listitem><para>Data transfer on USB is packetized; each endpoint
has a maximum packet size.
Drivers must often be aware of conventions such as flagging the end
of bulk transfers using "short" (including zero length) packets.
</para></listitem>
<listitem><para>The Linux USB API supports synchronous calls for
control and bulk messaging.
It also supports asynchnous calls for all kinds of data transfer,
using request structures called "URBs" (USB Request Blocks).
</para></listitem>
</itemizedlist>
<para>Accordingly, the USB Core API exposed to device drivers
covers quite a lot of territory. You'll probably need to consult
the USB 2.0 specification, available online from www.usb.org at
no cost, as well as class or device specifications.
</para>
<sect1><title>Data Types and Macros</title>
!Iinclude/linux/usb.h
</sect1>
<sect1><title>USB Core APIs</title>
!Edrivers/usb/usb.c
</sect1>
</chapter>
<chapter id="uart16x50">
......
......@@ -58,6 +58,10 @@ where:
get enabled unless you set this parameter to 1.
Do not use this option unless it's actually necessary,
some Vaio models don't deal well with this option.
This option is available only if the kernel is
compiled without ACPI support (since it conflicts
with it and it shouldn't be required anyway if
ACPI is already enabled).
verbose: print unknown events from the sonypi device
......@@ -93,7 +97,10 @@ Bugs:
- some users reported that the laptop speed is lower (dhrystone
tested) when using the driver with the fnkeyinit parameter. I cannot
reproduce it on my laptop and not all users have this problem.
Still under investigation.
This happens because the fnkeyinit parameter enables the ACPI
mode (but without additionnal ACPI control, like processor
speed handling etc). Use ACPI instead of APM if it works on your
laptop.
- since all development was done by reverse engineering, there is
_absolutely no guarantee_ that this driver will not crash your
......
VERSION = 2
PATCHLEVEL = 5
SUBLEVEL = 1
EXTRAVERSION =-pre3
EXTRAVERSION =-pre4
KERNELRELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)
......
......@@ -98,7 +98,7 @@ inline int elv_rq_merge_ok(request_queue_t *q, struct request *rq,
{
if (bio_data_dir(bio) == rq->cmd) {
if (rq->rq_dev == bio->bi_dev && !rq->waiting
&& !rq->special && rq->inactive && rq->q == q)
&& !rq->special && rq->inactive)
return 1;
}
......
......@@ -2437,16 +2437,15 @@ static int buffer_chain_size(void)
char *base;
base = CURRENT->buffer;
size = CURRENT->current_nr_sectors << 9;
bio = CURRENT->bio;
size = 0;
if (bio){
bio = bio->bi_next;
while (bio && bio_data(bio) == base + size){
size += bio_size(bio);
bio = bio->bi_next;
}
rq_for_each_bio(bio, CURRENT) {
if (bio_data(bio) != base + size)
break;
size += bio->bi_size;
}
return size >> 9;
}
......@@ -2543,7 +2542,7 @@ static void copy_buffer(int ssize, int max_sector, int max_sector_2)
break;
}
#endif
size = bio_size(bio);
size = bio->bi_size;;
buffer = bio_data(bio);
}
#ifdef FLOPPY_SANITY_CHECK
......
......@@ -303,10 +303,7 @@ int blk_rq_map_sg(request_queue_t *q, struct request *rq, struct scatterlist *sg
BIO_BUG_ON(i > bio->bi_vcnt);
if (!cluster)
goto new_segment;
if (bvec_to_phys(bvec) == lastend) {
if (cluster && bvec_to_phys(bvec) == lastend) {
if (sg[nsegs - 1].length + nbytes > q->max_segment_size)
goto new_segment;
......@@ -1135,7 +1132,7 @@ int submit_bio(int rw, struct bio *bio)
BUG_ON(!bio->bi_end_io);
BIO_BUG_ON(bio_offset(bio) > PAGE_SIZE);
BIO_BUG_ON(!bio_size(bio));
BIO_BUG_ON(!bio->bi_size);
BIO_BUG_ON(!bio->bi_io_vec);
bio->bi_rw = rw;
......@@ -1172,11 +1169,7 @@ int submit_bh(int rw, struct buffer_head * bh)
bio = bio_alloc(GFP_NOIO, 1);
bio->bi_sector = bh->b_blocknr * (bh->b_size >> 9);
bio->bi_next = NULL;
bio->bi_dev = bh->b_dev;
bio->bi_private = bh;
bio->bi_end_io = end_bio_bh_io_sync;
bio->bi_io_vec[0].bv_page = bh->b_page;
bio->bi_io_vec[0].bv_len = bh->b_size;
bio->bi_io_vec[0].bv_offset = bh_offset(bh);
......@@ -1185,6 +1178,9 @@ int submit_bh(int rw, struct buffer_head * bh)
bio->bi_idx = 0;
bio->bi_size = bh->b_size;
bio->bi_end_io = end_bio_bh_io_sync;
bio->bi_private = bh;
return submit_bio(rw, bio);
}
......
......@@ -182,7 +182,7 @@ static int lo_send(struct loop_device *lo, struct bio *bio, int bsize, loff_t po
down(&mapping->host->i_sem);
index = pos >> PAGE_CACHE_SHIFT;
offset = pos & (PAGE_CACHE_SIZE - 1);
len = bio_size(bio);
len = bio->bi_size;
data = bio_data(bio);
while (len > 0) {
int IV = index * (PAGE_CACHE_SIZE/bsize) + offset/bsize;
......@@ -272,7 +272,7 @@ static int lo_receive(struct loop_device *lo, struct bio *bio, int bsize, loff_t
cookie.data = bio_data(bio);
cookie.bsize = bsize;
desc.written = 0;
desc.count = bio_size(bio);
desc.count = bio->bi_size;
desc.buf = (char*)&cookie;
desc.error = 0;
spin_lock_irq(&lo->lo_lock);
......@@ -470,7 +470,7 @@ static int loop_make_request(request_queue_t *q, struct bio *rbh)
IV = loop_get_iv(lo, rbh->bi_sector);
if (rw == WRITE) {
if (lo_do_transfer(lo, WRITE, bio_data(bh), bio_data(rbh),
bio_size(bh), IV))
bh->bi_size, IV))
goto err;
}
......@@ -504,7 +504,7 @@ static inline void loop_handle_bio(struct loop_device *lo, struct bio *bio)
unsigned long IV = loop_get_iv(lo, rbh->bi_sector);
ret = lo_do_transfer(lo, READ, bio_data(bio), bio_data(rbh),
bio_size(bio), IV);
bio->bi_size, IV);
bio_endio(rbh, !ret, bio_sectors(bio));
loop_put_buffer(bio);
......
......@@ -168,7 +168,7 @@ void nbd_send_req(struct socket *sock, struct request *req)
struct bio *bio = req->bio;
DEBUG("data, ");
do {
result = nbd_xmit(1, sock, bio_data(bio), bio_size(bio), bio->bi_next == NULL ? 0 : MSG_MORE);
result = nbd_xmit(1, sock, bio_data(bio), bio->bi_size, bio->bi_next == NULL ? 0 : MSG_MORE);
if (result <= 0)
FAIL("Send data failed.");
bio = bio->bi_next;
......@@ -208,7 +208,7 @@ struct request *nbd_read_stat(struct nbd_device *lo)
struct bio *bio = req->bio;
DEBUG("data, ");
do {
result = nbd_xmit(0, lo->sock, bio_data(bio), bio_size(bio), MSG_WAITALL);
result = nbd_xmit(0, lo->sock, bio_data(bio), bio->bi_size, MSG_WAITALL);
if (result <= 0)
HARDFAIL("Recv data failed.");
bio = bio->bi_next;
......
......@@ -409,13 +409,13 @@ static int initrd_release(struct inode *inode,struct file *file)
{
extern void free_initrd_mem(unsigned long, unsigned long);
spin_lock( &initrd_users_lock );
spin_lock(&initrd_users_lock);
if (!--initrd_users) {
spin_unlock( &initrd_users_lock );
spin_unlock(&initrd_users_lock);
free_initrd_mem(initrd_start, initrd_end);
initrd_start = 0;
} else {
spin_unlock( &initrd_users_lock );
spin_unlock(&initrd_users_lock);
}
blkdev_put(inode->i_bdev, BDEV_FILE);
......@@ -437,9 +437,9 @@ static int rd_open(struct inode * inode, struct file * filp)
#ifdef CONFIG_BLK_DEV_INITRD
if (unit == INITRD_MINOR) {
if (!initrd_start) return -ENODEV;
spin_lock( &initrd_users_lock );
initrd_users++;
if (!initrd_start) return -ENODEV;
spin_unlock( &initrd_users_lock );
filp->f_op = &initrd_fops;
return 0;
......
......@@ -68,8 +68,8 @@ static struct pc110pad_params current_params;
/* driver/filesystem interface management */
static wait_queue_head_t queue;
static struct fasync_struct *asyncptr;
static active_count = 0; /* number of concurrent open()s */
static spinlock_t active_lock = SPIN_LOCK_UNLOCKED;
static int active_count = 0; /* number of concurrent open()s */
static spinlock_t pc110_lock = SPIN_LOCK_UNLOCKED;
/* this lock should be held when referencing active_count */
static struct semaphore reader_lock;
......@@ -483,14 +483,13 @@ static void sample_debug(int d[3])
int b;
unsigned long flags;
save_flags(flags);
cli();
spin_lock_irqsave(&pc110_lock, flags);
read_raw_pad(&thisd, &thisdd, &thisx, &thisy);
d[0]=(thisd?0x80:0) | (thisdd?0x40:0) | bounce;
d[1]=(recent_transition?0x80:0)+transition_count;
read_button(&b);
d[2]=(synthesize_tap<<4) | (b?0x01:0);
restore_flags(flags);
spin_unlock_irqrestore(&pc110_lock, flags);
}
/**
......@@ -586,11 +585,12 @@ static int fasync_pad(int fd, struct file *filp, int on)
static int close_pad(struct inode * inode, struct file * file)
{
unsigned long flags;
fasync_pad(-1, file, 0);
spin_lock( &active_lock );
spin_lock_irqsave(&pc110_lock, flags);
if (!--active_count)
outb(0x30, current_params.io+2); /* switch off digitiser */
spin_unlock( &active_lock );
spin_unlock_irqrestore(&active_lock, flags);
return 0;
}
......@@ -610,16 +610,13 @@ static int open_pad(struct inode * inode, struct file * file)
{
unsigned long flags;
spin_lock( &active_lock );
spin_lock_irqsave(&pc110_lock, flags);
if (active_count++)
{
spin_unlock( &active_lock );
spin_unlock_irqrestore(&pc110_lock, flags);
return 0;
}
spin_unlock( &active_lock );
save_flags(flags);
cli();
outb(0x30, current_params.io+2); /* switch off digitiser */
pad_irq(0,0,0); /* read to flush any pending bytes */
pad_irq(0,0,0); /* read to flush any pending bytes */
......@@ -634,7 +631,7 @@ static int open_pad(struct inode * inode, struct file * file)
synthesize_tap=0;
del_timer(&bounce_timer);
del_timer(&tap_timer);
restore_flags(flags);
spin_unlock_irqrestore(&pc110_lock, flags);
return 0;
}
......
......@@ -406,7 +406,7 @@ int pckbd_pm_resume(struct pm_dev *dev, pm_request_t rqst, void *data)
if (rqst == PM_RESUME) {
if (queue) { /* Aux port detected */
spin_lock_irqsave( &aux_count_lock, flags);
spin_lock_irqsave(&aux_count_lock, flags);
if ( aux_count == 0) { /* Mouse not in use */
spin_lock(&kbd_controller_lock);
/*
......@@ -420,9 +420,9 @@ int pckbd_pm_resume(struct pm_dev *dev, pm_request_t rqst, void *data)
kbd_write_command(KBD_CCMD_WRITE_MODE);
kb_wait();
kbd_write_output(AUX_INTS_OFF);
spin_unlock(&kbd_controller_lock, flags);
spin_unlock(&kbd_controller_lock);
}
spin_unlock_irqrestore( &aux_count_lock,flags );
spin_unlock_irqrestore(&aux_count_lock, flags);
}
}
#endif
......@@ -433,7 +433,7 @@ int pckbd_pm_resume(struct pm_dev *dev, pm_request_t rqst, void *data)
static inline void handle_mouse_event(unsigned char scancode)
{
#ifdef CONFIG_PSMOUSE
int flags;
unsigned long flags;
static unsigned char prev_code;
if (mouse_reply_expected) {
if (scancode == AUX_ACK) {
......@@ -452,7 +452,7 @@ static inline void handle_mouse_event(unsigned char scancode)
prev_code = scancode;
add_mouse_randomness(scancode);
spin_lock_irqsave( &aux_count_lock, flags);
spin_lock_irqsave(&aux_count_lock, flags);
if ( aux_count ) {
int head = queue->head;
......@@ -464,7 +464,7 @@ static inline void handle_mouse_event(unsigned char scancode)
wake_up_interruptible(&queue->proc_list);
}
}
spin_unlock_irqrestore( &aux_count_lock, flags);
spin_unlock_irqrestore(&aux_count_lock, flags);
#endif
}
......@@ -1052,14 +1052,14 @@ static int fasync_aux(int fd, struct file *filp, int on)
static int release_aux(struct inode * inode, struct file * file)
{
int flags;
unsigned long flags;
fasync_aux(-1, file, 0);
spin_lock_irqsave( &aux_count, flags );
spin_lock_irqsave(&aux_count_lock, flags);
if ( --aux_count ) {
spin_unlock_irqrestore( &aux_count_lock );
spin_unlock_irqrestore(&aux_count_lock, flags);
return 0;
}
spin_unlock_irqrestore( &aux_count_lock, flags );
spin_unlock_irqrestore(&aux_count_lock, flags);
kbd_write_cmd(AUX_INTS_OFF); /* Disable controller ints */
kbd_write_command_w(KBD_CCMD_MOUSE_DISABLE);
aux_free_irq(AUX_DEV);
......@@ -1073,16 +1073,16 @@ static int release_aux(struct inode * inode, struct file * file)
static int open_aux(struct inode * inode, struct file * file)
{
int flags;
spin_lock_irqsave( &aux_count_lock, flags );
unsigned long flags;
spin_lock_irqsave(&aux_count_lock, flags);
if ( aux_count++ ) {
spin_unlock_irqrestore( &aux_count_lock );
spin_unlock_irqrestore(&aux_count_lock, flags);
return 0;
}
queue->head = queue->tail = 0; /* Flush input queue */
if (aux_request_irq(keyboard_interrupt, AUX_DEV)) {
aux_count--;
spin_unlock_irqrestore( &aux_count_lock, flags );
spin_unlock_irqrestore(&aux_count_lock, flags);
return -EBUSY;
}
kbd_write_command_w(KBD_CCMD_MOUSE_ENABLE); /* Enable the
......@@ -1094,7 +1094,7 @@ static int open_aux(struct inode * inode, struct file * file)
mdelay(2); /* Ensure we follow the kbc access delay rules.. */
send_data(KBD_CMD_ENABLE); /* try to workaround toshiba4030cdt problem */
spin_unlock_irqrestore( &aux_count_lock, flags );
spin_unlock_irqrestore(&aux_count_lock, flags);
return 0;
}
......
......@@ -617,8 +617,11 @@ static int __devinit sonypi_probe(struct pci_dev *pcidev) {
goto out3;
}
#if !defined(CONFIG_ACPI)
/* Enable ACPI mode to get Fn key events */
if (fnkeyinit)
outb(0xf0, 0xb2);
#endif
if (sonypi_device.model == SONYPI_DEVICE_MODEL_TYPE2)
sonypi_type2_srs();
......@@ -666,6 +669,11 @@ static void __devexit sonypi_remove(void) {
sonypi_type2_dis();
else
sonypi_type1_dis();
#if !defined(CONFIG_ACPI)
/* disable ACPI mode */
if (fnkeyinit)
outb(0xf1, 0xb2);
#endif
free_irq(sonypi_device.irq, sonypi_irq);
release_region(sonypi_device.ioport1, sonypi_device.region_size);
misc_deregister(&sonypi_misc_device);
......
......@@ -35,7 +35,7 @@
#ifdef __KERNEL__
#define SONYPI_DRIVER_MAJORVERSION 1
#define SONYPI_DRIVER_MINORVERSION 7
#define SONYPI_DRIVER_MINORVERSION 8
#include <linux/types.h>
#include <linux/pci.h>
......
......@@ -50,7 +50,7 @@
#include <linux/reboot.h>
#include <linux/init.h>
static int wdt_is_open;
static unsigned long wdt_is_open;
/*
* You must set these - there is no sane way to probe for this board.
......@@ -337,13 +337,12 @@ static int wdt_open(struct inode *inode, struct file *file)
switch(MINOR(inode->i_rdev))
{
case WATCHDOG_MINOR:
if(wdt_is_open)
if(test_and_set_bit(0, &wdt_is_open))
return -EBUSY;
/*
* Activate
*/
wdt_is_open=1;
inb_p(WDT_DC); /* Disable */
wdt_ctr_mode(0,3);
wdt_ctr_mode(1,2);
......@@ -380,7 +379,7 @@ static int wdt_release(struct inode *inode, struct file *file)
inb_p(WDT_DC); /* Disable counters */
wdt_ctr_load(2,0); /* 0 length reset pulses now */
#endif
wdt_is_open=0;
clear_bit(0, &wdt_is_open);
}
return 0;
}
......
......@@ -71,7 +71,7 @@
#define PCI_DEVICE_ID_WDG_CSM 0x22c0
#endif
static int wdt_is_open;
static unsigned long wdt_is_open;
/*
* You must set these - there is no sane way to probe for this board.
......
......@@ -1246,8 +1246,6 @@ static int lvm_map(struct bio *bh)
}
out:
if (test_bit(BIO_HASHED, &bh->bi_flags))
BUG();
bh->bi_dev = rdev_map;
bh->bi_sector = rsector_map;
up_read(&lv->lv_lock);
......
......@@ -287,8 +287,8 @@ static int i2ob_send(u32 m, struct i2ob_device *dev, struct i2ob_request *ireq,
while(bio)
{
if (bio_to_phys(bio) == last) {
size += bio_size(bio);
last += bio_size(bio);
size += bio->bi_size;
last += bio->bi_size;
if(bio->bi_next)
__raw_writel(0x14000000|(size), mptr-8);
else
......@@ -297,16 +297,16 @@ static int i2ob_send(u32 m, struct i2ob_device *dev, struct i2ob_request *ireq,
else
{
if(bio->bi_next)
__raw_writel(0x10000000|bio_size(bio), mptr);
__raw_writel(0x10000000|bio->bi_size, mptr);
else
__raw_writel(0xD0000000|bio_size(bio), mptr);
__raw_writel(0xD0000000|bio->bi_size, mptr);
__raw_writel(bio_to_phys(bio), mptr+4);
mptr += 8;
size = bio_size(bio);
last = bio_to_phys(bio) + bio_size(bio);
size = bio->bi_size;
last = bio_to_phys(bio) + bio->bi_size;
}
count -= bio_size(bio);
count -= bio->bi_size;
bio = bio->bi_next;
}
/*
......@@ -326,8 +326,8 @@ static int i2ob_send(u32 m, struct i2ob_device *dev, struct i2ob_request *ireq,
while(bio)
{
if (bio_to_phys(bio) == last) {
size += bio_size(bio);
last += bio_size(bio);
size += bio->bi_size;
last += bio->bi_size;
if(bio->bi_next)
__raw_writel(0x14000000|(size), mptr-8);
else
......@@ -336,16 +336,16 @@ static int i2ob_send(u32 m, struct i2ob_device *dev, struct i2ob_request *ireq,
else
{
if(bio->bi_next)
__raw_writel(0x14000000|bio_size(bio), mptr);
__raw_writel(0x14000000|bio->bi_size, mptr);
else
__raw_writel(0xD4000000|bio_size(bio), mptr);
__raw_writel(0xD4000000|bio->bi_size, mptr);
__raw_writel(bio_to_phys(bio), mptr+4);
mptr += 8;
size = bio_size(bio);
last = bio_to_phys(bio) + bio_size(bio);
size = bio->bi_size;
last = bio_to_phys(bio) + bio->bi_size;
}
count -= bio_size(bio);
count -= bio->bi_size;
bio = bio->bi_next;
}
......
......@@ -49,7 +49,7 @@ int aha152x_proc_info(char *buffer, char **start, off_t offset, int length, int
cmd_per_lun: 1, \
present: 0, \
unchecked_isa_dma: 0, \
use_clustering: DISABLE_CLUSTERING, \
use_clustering: DISABLE_CLUSTERING }
#endif
......
......@@ -1059,7 +1059,7 @@ int gdth_eh_host_reset(Scsi_Cmnd *scp);
cmd_per_lun: GDTH_MAXC_P_L, \
present: 0, \
unchecked_isa_dma: 1, \
use_clustering: ENABLE_CLUSTERING, \
use_clustering: ENABLE_CLUSTERING }
#elif LINUX_VERSION_CODE >= 0x02015F
int gdth_bios_param(Disk *,kdev_t,int *);
......@@ -1090,7 +1090,7 @@ int gdth_eh_host_reset(Scsi_Cmnd *scp);
cmd_per_lun: GDTH_MAXC_P_L, \
present: 0, \
unchecked_isa_dma: 1, \
use_clustering: ENABLE_CLUSTERING, \
use_clustering: ENABLE_CLUSTERING }
#elif LINUX_VERSION_CODE >= 0x010300
int gdth_bios_param(Disk *,kdev_t,int *);
......
......@@ -34,7 +34,7 @@ extern int esp_reset(Scsi_Cmnd *, unsigned int);
this_id: 7, \
sg_tablesize: SG_ALL, \
cmd_per_lun: 1, \
use_clustering: DISABLE_CLUSTERING, \
use_clustering: DISABLE_CLUSTERING }
#endif /* MAC_ESP_H */
......@@ -148,7 +148,7 @@ __inline static int __count_segments(struct request *req,
*/
bio = req->bio;
#ifdef DMA_SEGMENT_SIZE_LIMITED
if (reqsize + bio_size(bio) > PAGE_SIZE)
if (reqsize + bio->bi_size > PAGE_SIZE)
ret++;
#endif
......@@ -156,7 +156,7 @@ __inline static int __count_segments(struct request *req,
bio_for_each_segment(bvec, bio, i)
ret++;
reqsize += bio_size(bio);
reqsize += bio->bi_size;
}
if (remainder)
......@@ -201,7 +201,7 @@ recount_segments(Scsi_Cmnd * SCpnt)
}
#define MERGEABLE_BUFFERS(X,Y) \
(((((long)bio_to_phys((X))+bio_size((X)))|((long)bio_to_phys((Y)))) & \
(((((long)bio_to_phys((X))+(X)->bi_size)|((long)bio_to_phys((Y)))) & \
(DMA_CHUNK_SIZE - 1)) == 0)
#ifdef DMA_CHUNK_SIZE
......@@ -767,7 +767,7 @@ __inline static int __init_io(Scsi_Cmnd * SCpnt,
* back and allocate a really small one - enough to satisfy
* the first buffer.
*/
if (bio_to_phys(bio) + bio_size(bio) - 1 > ISA_DMA_THRESHOLD) {
if (bio_to_phys(bio) + bio->bi_size - 1 > ISA_DMA_THRESHOLD) {
buff = (char *) scsi_malloc(this_count << 9);
if (!buff) {
printk("Warning - running low on DMA memory\n");
......
......@@ -37,7 +37,7 @@ int sim710_release(struct Scsi_Host *);
this_id: 7, \
sg_tablesize: 128, \
cmd_per_lun: 1, \
use_clustering: DISABLE_CLUSTERING, \
use_clustering: DISABLE_CLUSTERING }
#ifndef HOSTS_C
......
......@@ -224,7 +224,7 @@ static int dabusb_alloc_buffers (pdabusb_t s)
err("kmalloc(sizeof(buff_t))==NULL");
goto err;
}
memset (b, sizeof (buff_t), 0);
memset (b, 0, sizeof (buff_t));
b->s = s;
b->purb = usb_alloc_urb(packets);
if (!b->purb) {
......
/*
* Belkin USB Serial Adapter Driver
*
* Copyright (C) 2000
* William Greathouse (wgreathouse@smva.com)
* Copyright (C) 2000 William Greathouse (wgreathouse@smva.com)
* Copyright (C) 2000-2001 Greg Kroah-Hartman (greg@kroah.com)
*
* This program is largely derived from work by the linux-usb group
* and associated source files. Please see the usb/serial files for
......@@ -24,6 +24,9 @@
* -- Add support for flush commands
* -- Add everything that is missing :)
*
* 27-Nov-2001 gkh
* compressed all the differnent device entries into 1.
*
* 30-May-2001 gkh
* switched from using spinlock to a semaphore, which fixes lots of problems.
*
......@@ -88,7 +91,7 @@
/*
* Version Information
*/
#define DRIVER_VERSION "v1.1"
#define DRIVER_VERSION "v1.2"
#define DRIVER_AUTHOR "William Greathouse <wgreathouse@smva.com>"
#define DRIVER_DESC "USB Belkin Serial converter driver"
......@@ -112,125 +115,12 @@ static __devinitdata struct usb_device_id id_table_combined [] = {
{ } /* Terminating entry */
};
static __devinitdata struct usb_device_id belkin_dockstation_table [] = {
{ USB_DEVICE(BELKIN_DOCKSTATION_VID, BELKIN_DOCKSTATION_PID) },
{ } /* Terminating entry */
};
static __devinitdata struct usb_device_id belkin_sa_table [] = {
{ USB_DEVICE(BELKIN_SA_VID, BELKIN_SA_PID) },
{ } /* Terminating entry */
};
static __devinitdata struct usb_device_id belkin_old_table [] = {
{ USB_DEVICE(BELKIN_OLD_VID, BELKIN_OLD_PID) },
{ } /* Terminating entry */
};
static __devinitdata struct usb_device_id peracom_table [] = {
{ USB_DEVICE(PERACOM_VID, PERACOM_PID) },
{ } /* Terminating entry */
};
static __devinitdata struct usb_device_id gocom232_table [] = {
{ USB_DEVICE(GOHUBS_VID, GOHUBS_PID) },
{ } /* Terminating entry */
};
MODULE_DEVICE_TABLE (usb, id_table_combined);
/* All of the device info needed for the Belkin dockstation serial converter */
static struct usb_serial_device_type belkin_dockstation_device = {
name: "Belkin F5U120-PC USB Serial Adapter",
id_table: belkin_dockstation_table, /* the Belkin F5U103 device */
needs_interrupt_in: MUST_HAVE, /* this device must have an interrupt in endpoint */
needs_bulk_in: MUST_HAVE, /* this device must have a bulk in endpoint */
needs_bulk_out: MUST_HAVE, /* this device must have a bulk out endpoint */
num_interrupt_in: 1,
num_bulk_in: 1,
num_bulk_out: 1,
num_ports: 1,
open: belkin_sa_open,
close: belkin_sa_close,
read_int_callback: belkin_sa_read_int_callback, /* How we get the status info */
ioctl: belkin_sa_ioctl,
set_termios: belkin_sa_set_termios,
break_ctl: belkin_sa_break_ctl,
startup: belkin_sa_startup,
shutdown: belkin_sa_shutdown,
};
/* All of the device info needed for the Belkin serial converter */
static struct usb_serial_device_type belkin_sa_device = {
name: "Belkin F5U103 USB Serial Adapter",
id_table: belkin_sa_table, /* the Belkin F5U103 device */
needs_interrupt_in: MUST_HAVE, /* this device must have an interrupt in endpoint */
needs_bulk_in: MUST_HAVE, /* this device must have a bulk in endpoint */
needs_bulk_out: MUST_HAVE, /* this device must have a bulk out endpoint */
num_interrupt_in: 1,
num_bulk_in: 1,
num_bulk_out: 1,
num_ports: 1,
open: belkin_sa_open,
close: belkin_sa_close,
read_int_callback: belkin_sa_read_int_callback, /* How we get the status info */
ioctl: belkin_sa_ioctl,
set_termios: belkin_sa_set_termios,
break_ctl: belkin_sa_break_ctl,
startup: belkin_sa_startup,
shutdown: belkin_sa_shutdown,
};
/* This driver also supports the "old" school Belkin single port adaptor */
static struct usb_serial_device_type belkin_old_device = {
name: "Belkin USB Serial Adapter",
id_table: belkin_old_table, /* the old Belkin device */
needs_interrupt_in: MUST_HAVE, /* this device must have an interrupt in endpoint */
needs_bulk_in: MUST_HAVE, /* this device must have a bulk in endpoint */
needs_bulk_out: MUST_HAVE, /* this device must have a bulk out endpoint */
num_interrupt_in: 1,
num_bulk_in: 1,
num_bulk_out: 1,
num_ports: 1,
open: belkin_sa_open,
close: belkin_sa_close,
read_int_callback: belkin_sa_read_int_callback, /* How we get the status info */
ioctl: belkin_sa_ioctl,
set_termios: belkin_sa_set_termios,
break_ctl: belkin_sa_break_ctl,
startup: belkin_sa_startup,
shutdown: belkin_sa_shutdown,
};
/* this driver also works for the Peracom single port adapter */
static struct usb_serial_device_type peracom_device = {
name: "Peracom single port USB Serial Adapter",
id_table: peracom_table, /* the Peracom device */
needs_interrupt_in: MUST_HAVE, /* this device must have an interrupt in endpoint */
needs_bulk_in: MUST_HAVE, /* this device must have a bulk in endpoint */
needs_bulk_out: MUST_HAVE, /* this device must have a bulk out endpoint */
num_interrupt_in: 1,
num_bulk_in: 1,
num_bulk_out: 1,
num_ports: 1,
open: belkin_sa_open,
close: belkin_sa_close,
read_int_callback: belkin_sa_read_int_callback, /* How we get the status info */
ioctl: belkin_sa_ioctl,
set_termios: belkin_sa_set_termios,
break_ctl: belkin_sa_break_ctl,
startup: belkin_sa_startup,
shutdown: belkin_sa_shutdown,
};
/* the GoHubs Go-COM232 device is the same as the Peracom single port adapter */
static struct usb_serial_device_type gocom232_device = {
name: "GO-COM232 USB Serial Converter",
id_table: gocom232_table, /* the GO-COM232 device */
needs_interrupt_in: MUST_HAVE, /* this device must have an interrupt in endpoint */
needs_bulk_in: MUST_HAVE, /* this device must have a bulk in endpoint */
needs_bulk_out: MUST_HAVE, /* this device must have a bulk out endpoint */
/* All of the device info needed for the serial converters */
static struct usb_serial_device_type belkin_device = {
name: "Belkin / Peracom / GoHubs USB Serial Adapter",
id_table: id_table_combined,
num_interrupt_in: 1,
num_bulk_in: 1,
num_bulk_out: 1,
......@@ -642,11 +532,7 @@ static int belkin_sa_ioctl (struct usb_serial_port *port, struct file * file, un
static int __init belkin_sa_init (void)
{
usb_serial_register (&belkin_dockstation_device);
usb_serial_register (&belkin_sa_device);
usb_serial_register (&belkin_old_device);
usb_serial_register (&peracom_device);
usb_serial_register (&gocom232_device);
usb_serial_register (&belkin_device);
info(DRIVER_DESC " " DRIVER_VERSION);
return 0;
}
......@@ -654,11 +540,7 @@ static int __init belkin_sa_init (void)
static void __exit belkin_sa_exit (void)
{
usb_serial_deregister (&belkin_dockstation_device);
usb_serial_deregister (&belkin_sa_device);
usb_serial_deregister (&belkin_old_device);
usb_serial_deregister (&peracom_device);
usb_serial_deregister (&gocom232_device);
usb_serial_deregister (&belkin_device);
}
......
......@@ -79,9 +79,6 @@ MODULE_DEVICE_TABLE (usb, id_table);
static struct usb_serial_device_type cyberjack_device = {
name: "Reiner SCT Cyberjack USB card reader",
id_table: id_table,
needs_interrupt_in: MUST_HAVE,
needs_bulk_in: MUST_HAVE,
needs_bulk_out: MUST_HAVE,
num_interrupt_in: 1,
num_bulk_in: 1,
num_bulk_out: 1,
......
......@@ -500,9 +500,6 @@ MODULE_DEVICE_TABLE (usb, id_table_combined);
static struct usb_serial_device_type digi_acceleport_2_device = {
name: "Digi USB",
id_table: id_table_2,
needs_interrupt_in: DONT_CARE,
needs_bulk_in: MUST_HAVE,
needs_bulk_out: MUST_HAVE,
num_interrupt_in: 0,
num_bulk_in: 4,
num_bulk_out: 4,
......@@ -526,9 +523,6 @@ static struct usb_serial_device_type digi_acceleport_2_device = {
static struct usb_serial_device_type digi_acceleport_4_device = {
name: "Digi USB",
id_table: id_table_4,
needs_interrupt_in: DONT_CARE,
needs_bulk_in: MUST_HAVE,
needs_bulk_out: MUST_HAVE,
num_interrupt_in: 0,
num_bulk_in: 5,
num_bulk_out: 5,
......
......@@ -116,9 +116,6 @@ MODULE_DEVICE_TABLE (usb, id_table);
static struct usb_serial_device_type empeg_device = {
name: "Empeg",
id_table: id_table,
needs_interrupt_in: MUST_HAVE_NOT, /* must not have an interrupt in endpoint */
needs_bulk_in: MUST_HAVE, /* must have a bulk in endpoint */
needs_bulk_out: MUST_HAVE, /* must have a bulk out endpoint */
num_interrupt_in: 0,
num_bulk_in: 1,
num_bulk_out: 1,
......
......@@ -176,9 +176,6 @@ static void ftdi_sio_break_ctl (struct usb_serial_port *port, int break_state )
static struct usb_serial_device_type ftdi_sio_device = {
name: "FTDI SIO",
id_table: id_table_sio,
needs_interrupt_in: MUST_HAVE_NOT,
needs_bulk_in: MUST_HAVE,
needs_bulk_out: MUST_HAVE,
num_interrupt_in: 0,
num_bulk_in: 1,
num_bulk_out: 1,
......@@ -199,9 +196,6 @@ static struct usb_serial_device_type ftdi_sio_device = {
static struct usb_serial_device_type ftdi_8U232AM_device = {
name: "FTDI 8U232AM",
id_table: id_table_8U232AM,
needs_interrupt_in: DONT_CARE,
needs_bulk_in: MUST_HAVE,
needs_bulk_out: MUST_HAVE,
num_interrupt_in: 0,
num_bulk_in: 1,
num_bulk_out: 1,
......
......@@ -74,9 +74,6 @@ MODULE_DEVICE_TABLE (usb, id_table_combined);
static struct usb_serial_device_type edgeport_1port_device = {
name: "Edgeport 1 port adapter",
id_table: edgeport_1port_id_table,
needs_interrupt_in: MUST_HAVE,
needs_bulk_in: MUST_HAVE,
needs_bulk_out: MUST_HAVE,
num_interrupt_in: 1,
num_bulk_in: 1,
num_bulk_out: 1,
......@@ -98,9 +95,6 @@ static struct usb_serial_device_type edgeport_1port_device = {
static struct usb_serial_device_type edgeport_2port_device = {
name: "Edgeport 2 port adapter",
id_table: edgeport_2port_id_table,
needs_interrupt_in: MUST_HAVE,
needs_bulk_in: MUST_HAVE,
needs_bulk_out: MUST_HAVE,
num_interrupt_in: 1,
num_bulk_in: 1,
num_bulk_out: 1,
......@@ -122,9 +116,6 @@ static struct usb_serial_device_type edgeport_2port_device = {
static struct usb_serial_device_type edgeport_4port_device = {
name: "Edgeport 4 port adapter",
id_table: edgeport_4port_id_table,
needs_interrupt_in: MUST_HAVE,
needs_bulk_in: MUST_HAVE,
needs_bulk_out: MUST_HAVE,
num_interrupt_in: 1,
num_bulk_in: 1,
num_bulk_out: 1,
......@@ -146,9 +137,6 @@ static struct usb_serial_device_type edgeport_4port_device = {
static struct usb_serial_device_type edgeport_8port_device = {
name: "Edgeport 8 port adapter",
id_table: edgeport_8port_id_table,
needs_interrupt_in: MUST_HAVE,
needs_bulk_in: MUST_HAVE,
needs_bulk_out: MUST_HAVE,
num_interrupt_in: 1,
num_bulk_in: 1,
num_bulk_out: 1,
......
......@@ -93,9 +93,6 @@ MODULE_DEVICE_TABLE (usb, id_table);
struct usb_serial_device_type ir_device = {
name: "IR Dongle",
id_table: id_table,
needs_interrupt_in: MUST_HAVE,
needs_bulk_in: MUST_HAVE,
needs_bulk_out: MUST_HAVE,
num_interrupt_in: 1,
num_bulk_in: 1,
num_bulk_out: 1,
......
......@@ -451,9 +451,6 @@ static __devinitdata struct usb_device_id keyspan_usa49w_ids[] = {
static struct usb_serial_device_type keyspan_usa18x_pre_device = {
name: "Keyspan USA18X - (without firmware)",
id_table: keyspan_usa18x_pre_ids,
needs_interrupt_in: DONT_CARE,
needs_bulk_in: DONT_CARE,
needs_bulk_out: DONT_CARE,
num_interrupt_in: NUM_DONT_CARE,
num_bulk_in: NUM_DONT_CARE,
num_bulk_out: NUM_DONT_CARE,
......@@ -464,9 +461,6 @@ static struct usb_serial_device_type keyspan_usa18x_pre_device = {
static struct usb_serial_device_type keyspan_usa19_pre_device = {
name: "Keyspan USA19 - (without firmware)",
id_table: keyspan_usa19_pre_ids,
needs_interrupt_in: DONT_CARE,
needs_bulk_in: DONT_CARE,
needs_bulk_out: DONT_CARE,
num_interrupt_in: NUM_DONT_CARE,
num_bulk_in: NUM_DONT_CARE,
num_bulk_out: NUM_DONT_CARE,
......@@ -478,9 +472,6 @@ static struct usb_serial_device_type keyspan_usa19_pre_device = {
static struct usb_serial_device_type keyspan_usa19w_pre_device = {
name: "Keyspan USA19W - (without firmware)",
id_table: keyspan_usa19w_pre_ids,
needs_interrupt_in: DONT_CARE,
needs_bulk_in: DONT_CARE,
needs_bulk_out: DONT_CARE,
num_interrupt_in: NUM_DONT_CARE,
num_bulk_in: NUM_DONT_CARE,
num_bulk_out: NUM_DONT_CARE,
......@@ -492,9 +483,6 @@ static struct usb_serial_device_type keyspan_usa19w_pre_device = {
static struct usb_serial_device_type keyspan_usa28_pre_device = {
name: "Keyspan USA28 - (without firmware)",
id_table: keyspan_usa28_pre_ids,
needs_interrupt_in: DONT_CARE,
needs_bulk_in: DONT_CARE,
needs_bulk_out: DONT_CARE,
num_interrupt_in: NUM_DONT_CARE,
num_bulk_in: NUM_DONT_CARE,
num_bulk_out: NUM_DONT_CARE,
......@@ -505,9 +493,6 @@ static struct usb_serial_device_type keyspan_usa28_pre_device = {
static struct usb_serial_device_type keyspan_usa28x_pre_device = {
name: "Keyspan USA28X - (without firmware)",
id_table: keyspan_usa28x_pre_ids,
needs_interrupt_in: DONT_CARE,
needs_bulk_in: DONT_CARE,
needs_bulk_out: DONT_CARE,
num_interrupt_in: NUM_DONT_CARE,
num_bulk_in: NUM_DONT_CARE,
num_bulk_out: NUM_DONT_CARE,
......@@ -518,9 +503,6 @@ static struct usb_serial_device_type keyspan_usa28x_pre_device = {
static struct usb_serial_device_type keyspan_usa28xa_pre_device = {
name: "Keyspan USA28XA - (without firmware)",
id_table: keyspan_usa28xa_pre_ids,
needs_interrupt_in: DONT_CARE,
needs_bulk_in: DONT_CARE,
needs_bulk_out: DONT_CARE,
num_interrupt_in: NUM_DONT_CARE,
num_bulk_in: NUM_DONT_CARE,
num_bulk_out: NUM_DONT_CARE,
......@@ -531,9 +513,6 @@ static struct usb_serial_device_type keyspan_usa28xa_pre_device = {
static struct usb_serial_device_type keyspan_usa28xb_pre_device = {
name: "Keyspan USA28XB - (without firmware)",
id_table: keyspan_usa28xb_pre_ids,
needs_interrupt_in: DONT_CARE,
needs_bulk_in: DONT_CARE,
needs_bulk_out: DONT_CARE,
num_interrupt_in: NUM_DONT_CARE,
num_bulk_in: NUM_DONT_CARE,
num_bulk_out: NUM_DONT_CARE,
......@@ -544,9 +523,6 @@ static struct usb_serial_device_type keyspan_usa28xb_pre_device = {
static struct usb_serial_device_type keyspan_usa49w_pre_device = {
name: "Keyspan USA49W - (without firmware)",
id_table: keyspan_usa49w_pre_ids,
needs_interrupt_in: DONT_CARE,
needs_bulk_in: DONT_CARE,
needs_bulk_out: DONT_CARE,
num_interrupt_in: NUM_DONT_CARE,
num_bulk_in: NUM_DONT_CARE,
num_bulk_out: NUM_DONT_CARE,
......@@ -557,9 +533,6 @@ static struct usb_serial_device_type keyspan_usa49w_pre_device = {
static struct usb_serial_device_type keyspan_usa18x_device = {
name: "Keyspan USA18X",
id_table: keyspan_usa18x_ids,
needs_interrupt_in: DONT_CARE,
needs_bulk_in: MUST_HAVE,
needs_bulk_out: MUST_HAVE,
num_interrupt_in: NUM_DONT_CARE,
num_bulk_in: 3,
num_bulk_out: 4,
......@@ -583,9 +556,6 @@ static struct usb_serial_device_type keyspan_usa18x_device = {
static struct usb_serial_device_type keyspan_usa19_device = {
name: "Keyspan USA19",
id_table: keyspan_usa19_ids,
needs_interrupt_in: DONT_CARE,
needs_bulk_in: MUST_HAVE,
needs_bulk_out: MUST_HAVE,
num_interrupt_in: NUM_DONT_CARE,
num_bulk_in: 3,
num_bulk_out: 4,
......@@ -610,9 +580,6 @@ static struct usb_serial_device_type keyspan_usa19_device = {
static struct usb_serial_device_type keyspan_usa19w_device = {
name: "Keyspan USA19W",
id_table: keyspan_usa19w_ids,
needs_interrupt_in: DONT_CARE,
needs_bulk_in: MUST_HAVE,
needs_bulk_out: MUST_HAVE,
num_interrupt_in: NUM_DONT_CARE,
num_bulk_in: 3,
num_bulk_out: 4,
......@@ -637,9 +604,6 @@ static struct usb_serial_device_type keyspan_usa19w_device = {
static struct usb_serial_device_type keyspan_usa28_device = {
name: "Keyspan USA28",
id_table: keyspan_usa28_ids,
needs_interrupt_in: DONT_CARE,
needs_bulk_in: DONT_CARE,
needs_bulk_out: DONT_CARE,
num_interrupt_in: NUM_DONT_CARE,
num_bulk_in: NUM_DONT_CARE,
num_bulk_out: NUM_DONT_CARE,
......@@ -655,9 +619,6 @@ static struct usb_serial_device_type keyspan_usa28_device = {
static struct usb_serial_device_type keyspan_usa28x_device = {
name: "Keyspan USA28X/XB",
id_table: keyspan_usa28x_ids,
needs_interrupt_in: DONT_CARE,
needs_bulk_in: DONT_CARE,
needs_bulk_out: DONT_CARE,
num_interrupt_in: NUM_DONT_CARE,
num_bulk_in: NUM_DONT_CARE,
num_bulk_out: NUM_DONT_CARE,
......@@ -682,9 +643,6 @@ static struct usb_serial_device_type keyspan_usa28x_device = {
static struct usb_serial_device_type keyspan_usa28xa_device = {
name: "Keyspan USA28XA",
id_table: keyspan_usa28xa_ids,
needs_interrupt_in: DONT_CARE,
needs_bulk_in: DONT_CARE,
needs_bulk_out: DONT_CARE,
num_interrupt_in: NUM_DONT_CARE,
num_bulk_in: NUM_DONT_CARE,
num_bulk_out: NUM_DONT_CARE,
......@@ -709,9 +667,6 @@ static struct usb_serial_device_type keyspan_usa28xa_device = {
static struct usb_serial_device_type keyspan_usa49w_device = {
name: "Keyspan USA49W",
id_table: keyspan_usa49w_ids,
needs_interrupt_in: DONT_CARE,
needs_bulk_in: MUST_HAVE,
needs_bulk_out: MUST_HAVE,
num_interrupt_in: NUM_DONT_CARE,
num_bulk_in: 5,
num_bulk_out: 5,
......
......@@ -172,10 +172,6 @@ static __devinitdata struct usb_device_id id_table_fake [] = {
#ifdef XIRCOM
static __devinitdata struct usb_device_id id_table_fake_xircom [] = {
{ USB_DEVICE(XIRCOM_VENDOR_ID, XIRCOM_FAKE_ID) },
{ }
};
static __devinitdata struct usb_device_id id_table_fake_entregra [] = {
{ USB_DEVICE(ENTREGRA_VENDOR_ID, ENTREGRA_FAKE_ID) },
{ }
};
......@@ -843,9 +839,6 @@ static void keyspan_pda_shutdown (struct usb_serial *serial)
static struct usb_serial_device_type keyspan_pda_fake_device = {
name: "Keyspan PDA - (prerenumeration)",
id_table: id_table_fake,
needs_interrupt_in: DONT_CARE,
needs_bulk_in: DONT_CARE,
needs_bulk_out: DONT_CARE,
num_interrupt_in: NUM_DONT_CARE,
num_bulk_in: NUM_DONT_CARE,
num_bulk_out: NUM_DONT_CARE,
......@@ -856,24 +849,8 @@ static struct usb_serial_device_type keyspan_pda_fake_device = {
#ifdef XIRCOM
static struct usb_serial_device_type xircom_pgs_fake_device = {
name: "Xircom PGS - (prerenumeration)",
name: "Xircom / Entregra PGS - (prerenumeration)",
id_table: id_table_fake_xircom,
needs_interrupt_in: DONT_CARE,
needs_bulk_in: DONT_CARE,
needs_bulk_out: DONT_CARE,
num_interrupt_in: NUM_DONT_CARE,
num_bulk_in: NUM_DONT_CARE,
num_bulk_out: NUM_DONT_CARE,
num_ports: 1,
startup: keyspan_pda_fake_startup,
};
static struct usb_serial_device_type entregra_pgs_fake_device = {
name: "Entregra PGS - (prerenumeration)",
id_table: id_table_fake_entregra,
needs_interrupt_in: DONT_CARE,
needs_bulk_in: DONT_CARE,
needs_bulk_out: DONT_CARE,
num_interrupt_in: NUM_DONT_CARE,
num_bulk_in: NUM_DONT_CARE,
num_bulk_out: NUM_DONT_CARE,
......@@ -885,9 +862,6 @@ static struct usb_serial_device_type entregra_pgs_fake_device = {
static struct usb_serial_device_type keyspan_pda_device = {
name: "Keyspan PDA",
id_table: id_table_std,
needs_interrupt_in: MUST_HAVE,
needs_bulk_in: DONT_CARE,
needs_bulk_out: MUST_HAVE,
num_interrupt_in: 1,
num_bulk_in: 0,
num_bulk_out: 1,
......@@ -917,7 +891,6 @@ static int __init keyspan_pda_init (void)
#endif
#ifdef XIRCOM
usb_serial_register (&xircom_pgs_fake_device);
usb_serial_register (&entregra_pgs_fake_device);
#endif
info(DRIVER_DESC " " DRIVER_VERSION);
return 0;
......@@ -931,7 +904,6 @@ static void __exit keyspan_pda_exit (void)
usb_serial_deregister (&keyspan_pda_fake_device);
#endif
#ifdef XIRCOM
usb_serial_deregister (&entregra_pgs_fake_device);
usb_serial_deregister (&xircom_pgs_fake_device);
#endif
}
......
......@@ -136,54 +136,12 @@ static __devinitdata struct usb_device_id id_table_combined [] = {
{ } /* Terminating entry */
};
static __devinitdata struct usb_device_id mct_u232_table [] = {
{ USB_DEVICE(MCT_U232_VID, MCT_U232_PID) },
{ } /* Terminating entry */
};
static __devinitdata struct usb_device_id mct_u232_sitecom_table [] = {
{ USB_DEVICE(MCT_U232_VID, MCT_U232_SITECOM_PID) },
{ } /* Terminating entry */
};
static __devinitdata struct usb_device_id mct_u232_du_h3sp_table [] = {
{ USB_DEVICE(MCT_U232_VID, MCT_U232_DU_H3SP_PID) },
{ } /* Terminating entry */
};
MODULE_DEVICE_TABLE (usb, id_table_combined);
static struct usb_serial_device_type mct_u232_device = {
name: "Magic Control Technology USB-RS232",
id_table: mct_u232_table,
needs_interrupt_in: MUST_HAVE, /* 2 interrupt-in endpoints */
needs_bulk_in: MUST_HAVE_NOT, /* no bulk-in endpoint */
needs_bulk_out: MUST_HAVE, /* 1 bulk-out endpoint */
num_interrupt_in: 2,
num_bulk_in: 0,
num_bulk_out: 1,
num_ports: 1,
open: mct_u232_open,
close: mct_u232_close,
#ifdef FIX_WRITE_RETURN_CODE_PROBLEM
write: mct_u232_write,
write_bulk_callback: mct_u232_write_bulk_callback,
#endif
read_int_callback: mct_u232_read_int_callback,
ioctl: mct_u232_ioctl,
set_termios: mct_u232_set_termios,
break_ctl: mct_u232_break_ctl,
startup: mct_u232_startup,
shutdown: mct_u232_shutdown,
};
static struct usb_serial_device_type mct_u232_sitecom_device = {
name: "MCT/Sitecom USB-RS232",
id_table: mct_u232_sitecom_table,
needs_interrupt_in: MUST_HAVE, /* 2 interrupt-in endpoints */
needs_bulk_in: MUST_HAVE_NOT, /* no bulk-in endpoint */
needs_bulk_out: MUST_HAVE, /* 1 bulk-out endpoint */
id_table: id_table_combined,
num_interrupt_in: 2,
num_bulk_in: 0,
num_bulk_out: 1,
......@@ -202,32 +160,6 @@ static struct usb_serial_device_type mct_u232_sitecom_device = {
shutdown: mct_u232_shutdown,
};
static struct usb_serial_device_type mct_u232_du_h3sp_device = {
name: "MCT/D-Link DU-H3SP USB BAY",
id_table: mct_u232_du_h3sp_table,
needs_interrupt_in: MUST_HAVE, /* 2 interrupt-in endpoints */
needs_bulk_in: MUST_HAVE_NOT, /* no bulk-in endpoint */
needs_bulk_out: MUST_HAVE, /* 1 bulk-out endpoint */
num_interrupt_in: 2,
num_bulk_in: 0,
num_bulk_out: 1,
num_ports: 1,
open: mct_u232_open,
close: mct_u232_close,
#ifdef FIX_WRITE_RETURN_CODE_PROBLEM
write: mct_u232_write,
write_bulk_callback: mct_u232_write_bulk_callback,
#endif
read_int_callback: mct_u232_read_int_callback,
ioctl: mct_u232_ioctl,
set_termios: mct_u232_set_termios,
break_ctl: mct_u232_break_ctl,
startup: mct_u232_startup,
shutdown: mct_u232_shutdown,
};
struct mct_u232_private {
unsigned long control_state; /* Modem Line Setting (TIOCM) */
......@@ -880,9 +812,7 @@ static int mct_u232_ioctl (struct usb_serial_port *port, struct file * file,
static int __init mct_u232_init (void)
{
usb_serial_register (&mct_u232_device);
usb_serial_register (&mct_u232_sitecom_device);
usb_serial_register (&mct_u232_du_h3sp_device);
info(DRIVER_VERSION ":" DRIVER_DESC);
info(DRIVER_DESC " " DRIVER_VERSION);
return 0;
}
......@@ -890,8 +820,6 @@ static int __init mct_u232_init (void)
static void __exit mct_u232_exit (void)
{
usb_serial_deregister (&mct_u232_device);
usb_serial_deregister (&mct_u232_sitecom_device);
usb_serial_deregister (&mct_u232_du_h3sp_device);
}
......
......@@ -90,9 +90,6 @@ MODULE_DEVICE_TABLE (usb, id_table);
static struct usb_serial_device_type zyxel_omninet_device = {
name: "ZyXEL - omni.net lcd plus usb",
id_table: id_table,
needs_interrupt_in: MUST_HAVE,
needs_bulk_in: MUST_HAVE,
needs_bulk_out: MUST_HAVE,
num_interrupt_in: 1,
num_bulk_in: 1,
num_bulk_out: 2,
......
......@@ -118,9 +118,6 @@ static void pl2303_shutdown (struct usb_serial *serial);
static struct usb_serial_device_type pl2303_device = {
name: "PL-2303",
id_table: id_table,
needs_interrupt_in: DONT_CARE, /* this device must have an interrupt in endpoint */
needs_bulk_in: MUST_HAVE, /* this device must have a bulk in endpoint */
needs_bulk_out: MUST_HAVE, /* this device must have a bulk out endpoint */
num_interrupt_in: NUM_DONT_CARE,
num_bulk_in: 1,
num_bulk_out: 1,
......
......@@ -108,13 +108,6 @@ struct usb_serial {
};
#define MUST_HAVE_NOT 0x01
#define MUST_HAVE 0x02
#define DONT_CARE 0x03
#define HAS 0x02
#define HAS_NOT 0x01
#define NUM_DONT_CARE (-1)
......@@ -122,9 +115,6 @@ struct usb_serial {
struct usb_serial_device_type {
char *name;
const struct usb_device_id *id_table;
char needs_interrupt_in;
char needs_bulk_in;
char needs_bulk_out;
char num_interrupt_in;
char num_bulk_in;
char num_bulk_out;
......
......@@ -339,9 +339,6 @@ static struct usb_device_id generic_device_ids[2]; /* Initially all zeroes. */
static struct usb_serial_device_type generic_device = {
name: "Generic",
id_table: generic_device_ids,
needs_interrupt_in: DONT_CARE, /* don't have to have an interrupt in endpoint */
needs_bulk_in: DONT_CARE, /* don't have to have a bulk in endpoint */
needs_bulk_out: DONT_CARE, /* don't have to have a bulk out endpoint */
num_interrupt_in: NUM_DONT_CARE,
num_bulk_in: NUM_DONT_CARE,
num_bulk_out: NUM_DONT_CARE,
......@@ -1068,9 +1065,6 @@ static void * usb_serial_probe(struct usb_device *dev, unsigned int ifnum,
int minor;
int buffer_size;
int i;
char interrupt_pipe;
char bulk_in_pipe;
char bulk_out_pipe;
int num_interrupt_in = 0;
int num_bulk_in = 0;
int num_bulk_out = 0;
......@@ -1099,8 +1093,6 @@ static void * usb_serial_probe(struct usb_device *dev, unsigned int ifnum,
}
/* descriptor matches, let's find the endpoints needed */
interrupt_pipe = bulk_in_pipe = bulk_out_pipe = HAS_NOT;
/* check out the endpoints */
iface_desc = &interface->altsetting[0];
for (i = 0; i < iface_desc->bNumEndpoints; ++i) {
......@@ -1110,7 +1102,6 @@ static void * usb_serial_probe(struct usb_device *dev, unsigned int ifnum,
((endpoint->bmAttributes & 3) == 0x02)) {
/* we found a bulk in endpoint */
dbg("found bulk in");
bulk_in_pipe = HAS;
bulk_in_endpoint[num_bulk_in] = endpoint;
++num_bulk_in;
}
......@@ -1119,7 +1110,6 @@ static void * usb_serial_probe(struct usb_device *dev, unsigned int ifnum,
((endpoint->bmAttributes & 3) == 0x02)) {
/* we found a bulk out endpoint */
dbg("found bulk out");
bulk_out_pipe = HAS;
bulk_out_endpoint[num_bulk_out] = endpoint;
++num_bulk_out;
}
......@@ -1128,7 +1118,6 @@ static void * usb_serial_probe(struct usb_device *dev, unsigned int ifnum,
((endpoint->bmAttributes & 3) == 0x03)) {
/* we found a interrupt in endpoint */
dbg("found interrupt in");
interrupt_pipe = HAS;
interrupt_in_endpoint[num_interrupt_in] = endpoint;
++num_interrupt_in;
}
......@@ -1151,7 +1140,6 @@ static void * usb_serial_probe(struct usb_device *dev, unsigned int ifnum,
((endpoint->bmAttributes & 3) == 0x03)) {
/* we found a interrupt in endpoint */
dbg("found interrupt in for Prolific device on separate interface");
interrupt_pipe = HAS;
interrupt_in_endpoint[num_interrupt_in] = endpoint;
++num_interrupt_in;
}
......@@ -1161,15 +1149,6 @@ static void * usb_serial_probe(struct usb_device *dev, unsigned int ifnum,
/* END HORRIBLE HACK FOR PL2303 */
#endif
/* verify that we found all of the endpoints that we need */
if (!((interrupt_pipe & type->needs_interrupt_in) &&
(bulk_in_pipe & type->needs_bulk_in) &&
(bulk_out_pipe & type->needs_bulk_out))) {
/* nope, they don't match what we expected */
info("descriptors matched, but endpoints did not");
return NULL;
}
/* found all that we need */
info("%s converter detected", type->name);
......
......@@ -127,7 +127,7 @@
/*
* Version Information
*/
#define DRIVER_VERSION "v1.5"
#define DRIVER_VERSION "v1.6"
#define DRIVER_AUTHOR "Greg Kroah-Hartman <greg@kroah.com>"
#define DRIVER_DESC "USB HandSpring Visor, Palm m50x, Sony Cli driver"
......@@ -147,15 +147,12 @@ static void visor_write_bulk_callback (struct urb *urb);
static void visor_read_bulk_callback (struct urb *urb);
static __devinitdata struct usb_device_id visor_id_table [] = {
{ USB_DEVICE(HANDSPRING_VENDOR_ID, HANDSPRING_VISOR_ID) },
{ } /* Terminating entry */
};
static __devinitdata struct usb_device_id palm_4_0_id_table [] = {
static __devinitdata struct usb_device_id combined_id_table [] = {
{ USB_DEVICE(PALM_VENDOR_ID, PALM_M500_ID) },
{ USB_DEVICE(PALM_VENDOR_ID, PALM_M505_ID) },
{ USB_DEVICE(PALM_VENDOR_ID, PALM_M125_ID) },
{ USB_DEVICE(HANDSPRING_VENDOR_ID, HANDSPRING_VISOR_ID) },
{ USB_DEVICE(SONY_VENDOR_ID, SONY_CLIE_4_0_ID) },
{ } /* Terminating entry */
};
......@@ -164,11 +161,6 @@ static __devinitdata struct usb_device_id clie_id_3_5_table [] = {
{ } /* Terminating entry */
};
static __devinitdata struct usb_device_id clie_id_4_0_table [] = {
{ USB_DEVICE(SONY_VENDOR_ID, SONY_CLIE_4_0_ID) },
{ } /* Terminating entry */
};
static __devinitdata struct usb_device_id id_table [] = {
{ USB_DEVICE(HANDSPRING_VENDOR_ID, HANDSPRING_VISOR_ID) },
{ USB_DEVICE(PALM_VENDOR_ID, PALM_M500_ID) },
......@@ -183,39 +175,10 @@ MODULE_DEVICE_TABLE (usb, id_table);
/* All of the device info needed for the Handspring Visor */
/* All of the device info needed for the Handspring Visor, and Palm 4.0 devices */
static struct usb_serial_device_type handspring_device = {
name: "Handspring Visor",
id_table: visor_id_table,
needs_interrupt_in: MUST_HAVE_NOT, /* this device must not have an interrupt in endpoint */
needs_bulk_in: MUST_HAVE, /* this device must have a bulk in endpoint */
needs_bulk_out: MUST_HAVE, /* this device must have a bulk out endpoint */
num_interrupt_in: 0,
num_bulk_in: 2,
num_bulk_out: 2,
num_ports: 2,
open: visor_open,
close: visor_close,
throttle: visor_throttle,
unthrottle: visor_unthrottle,
startup: visor_startup,
shutdown: visor_shutdown,
ioctl: visor_ioctl,
set_termios: visor_set_termios,
write: visor_write,
write_room: visor_write_room,
chars_in_buffer: visor_chars_in_buffer,
write_bulk_callback: visor_write_bulk_callback,
read_bulk_callback: visor_read_bulk_callback,
};
/* device info for the Palm 4.0 devices */
static struct usb_serial_device_type palm_4_0_device = {
name: "Palm 4.0",
id_table: palm_4_0_id_table,
needs_interrupt_in: MUST_HAVE_NOT, /* this device must not have an interrupt in endpoint */
needs_bulk_in: MUST_HAVE, /* this device must have a bulk in endpoint */
needs_bulk_out: MUST_HAVE, /* this device must have a bulk out endpoint */
name: "Handspring Visor / Palm 4.0 / Cli 4.0",
id_table: combined_id_table,
num_interrupt_in: 0,
num_bulk_in: 2,
num_bulk_out: 2,
......@@ -235,14 +198,10 @@ static struct usb_serial_device_type palm_4_0_device = {
read_bulk_callback: visor_read_bulk_callback,
};
/* device info for the Sony Clie OS version 3.5 */
static struct usb_serial_device_type clie_3_5_device = {
name: "Sony Cli 3.5",
id_table: clie_id_3_5_table,
needs_interrupt_in: MUST_HAVE_NOT, /* this device must not have an interrupt in endpoint */
needs_bulk_in: MUST_HAVE, /* this device must have a bulk in endpoint */
needs_bulk_out: MUST_HAVE, /* this device must have a bulk out endpoint */
num_interrupt_in: 0,
num_bulk_in: 1,
num_bulk_out: 1,
......@@ -260,31 +219,6 @@ static struct usb_serial_device_type clie_3_5_device = {
read_bulk_callback: visor_read_bulk_callback,
};
/* device info for the Sony Clie OS version 4.0 */
static struct usb_serial_device_type clie_4_0_device = {
name: "Sony Clié 4.0",
id_table: clie_id_4_0_table,
needs_interrupt_in: MUST_HAVE_NOT, /* this device must not have an interrupt in endpoint */
needs_bulk_in: MUST_HAVE, /* this device must have a bulk in endpoint */
needs_bulk_out: MUST_HAVE, /* this device must have a bulk out endpoint */
num_interrupt_in: 0,
num_bulk_in: 2,
num_bulk_out: 2,
num_ports: 2,
open: visor_open,
close: visor_close,
throttle: visor_throttle,
unthrottle: visor_unthrottle,
startup: visor_startup,
shutdown: visor_shutdown,
ioctl: visor_ioctl,
set_termios: visor_set_termios,
write: visor_write,
write_room: visor_write_room,
chars_in_buffer: visor_chars_in_buffer,
write_bulk_callback: visor_write_bulk_callback,
read_bulk_callback: visor_read_bulk_callback,
};
#define NUM_URBS 24
#define URB_TRANSFER_BUFFER_SIZE 768
......@@ -801,9 +735,7 @@ static int __init visor_init (void)
int i;
usb_serial_register (&handspring_device);
usb_serial_register (&palm_4_0_device);
usb_serial_register (&clie_3_5_device);
usb_serial_register (&clie_4_0_device);
/* create our write urb pool and transfer buffers */
spin_lock_init (&write_urb_pool_lock);
......@@ -835,9 +767,7 @@ static void __exit visor_exit (void)
unsigned long flags;
usb_serial_deregister (&handspring_device);
usb_serial_deregister (&palm_4_0_device);
usb_serial_deregister (&clie_3_5_device);
usb_serial_deregister (&clie_4_0_device);
spin_lock_irqsave (&write_urb_pool_lock, flags);
......
......@@ -88,7 +88,7 @@
/*
* Version Information
*/
#define DRIVER_VERSION "v1.1"
#define DRIVER_VERSION "v1.2"
#define DRIVER_AUTHOR "Greg Kroah-Hartman <greg@kroah.com>"
#define DRIVER_DESC "USB ConnectTech WhiteHEAT driver"
......@@ -128,28 +128,23 @@ static int whiteheat_ioctl (struct usb_serial_port *port, struct file * file,
static void whiteheat_set_termios (struct usb_serial_port *port, struct termios * old);
static void whiteheat_throttle (struct usb_serial_port *port);
static void whiteheat_unthrottle (struct usb_serial_port *port);
static int whiteheat_startup (struct usb_serial *serial);
static void whiteheat_shutdown (struct usb_serial *serial);
static int whiteheat_fake_startup (struct usb_serial *serial);
static int whiteheat_real_startup (struct usb_serial *serial);
static void whiteheat_real_shutdown (struct usb_serial *serial);
static struct usb_serial_device_type whiteheat_fake_device = {
name: "Connect Tech - WhiteHEAT - (prerenumeration)",
id_table: id_table_prerenumeration,
needs_interrupt_in: DONT_CARE, /* don't have to have an interrupt in endpoint */
needs_bulk_in: DONT_CARE, /* don't have to have a bulk in endpoint */
needs_bulk_out: DONT_CARE, /* don't have to have a bulk out endpoint */
num_interrupt_in: NUM_DONT_CARE,
num_bulk_in: NUM_DONT_CARE,
num_bulk_out: NUM_DONT_CARE,
num_ports: 1,
startup: whiteheat_startup
startup: whiteheat_fake_startup,
};
static struct usb_serial_device_type whiteheat_device = {
name: "Connect Tech - WhiteHEAT",
id_table: id_table_std,
needs_interrupt_in: DONT_CARE, /* don't have to have an interrupt in endpoint */
needs_bulk_in: DONT_CARE, /* don't have to have a bulk in endpoint */
needs_bulk_out: DONT_CARE, /* don't have to have a bulk out endpoint */
num_interrupt_in: NUM_DONT_CARE,
num_bulk_in: NUM_DONT_CARE,
num_bulk_out: NUM_DONT_CARE,
......@@ -160,7 +155,8 @@ static struct usb_serial_device_type whiteheat_device = {
unthrottle: whiteheat_unthrottle,
ioctl: whiteheat_ioctl,
set_termios: whiteheat_set_termios,
shutdown: whiteheat_shutdown,
startup: whiteheat_real_startup,
shutdown: whiteheat_real_shutdown,
};
struct whiteheat_private {
......@@ -539,7 +535,7 @@ static void whiteheat_unthrottle (struct usb_serial_port *port)
- device renumerated itself and comes up as new device id with all
firmware download completed.
*/
static int whiteheat_startup (struct usb_serial *serial)
static int whiteheat_fake_startup (struct usb_serial *serial)
{
int response;
const struct whiteheat_hex_record *record;
......@@ -598,7 +594,66 @@ static int whiteheat_startup (struct usb_serial *serial)
}
static void whiteheat_shutdown (struct usb_serial *serial)
static int whiteheat_real_startup (struct usb_serial *serial)
{
struct whiteheat_hw_info *hw_info;
int pipe;
int ret;
int alen;
__u8 command[2] = { WHITEHEAT_GET_HW_INFO, 0 };
__u8 result[sizeof(*hw_info) + 1];
pipe = usb_rcvbulkpipe (serial->dev, 7);
usb_bulk_msg (serial->dev, pipe, result, sizeof(result), &alen, 2 * HZ);
/*
* We ignore the return code. In the case where rmmod/insmod is
* performed with a WhiteHEAT connected, the above times out
* because the endpoint is already prepped, meaning the below succeeds
* regardless. All other cases the above succeeds.
*/
pipe = usb_sndbulkpipe (serial->dev, 7);
ret = usb_bulk_msg (serial->dev, pipe, command, sizeof(command), &alen, 2 * HZ);
if (ret) {
err("%s: Couldn't send command [%d]", serial->type->name, ret);
goto error_out;
} else if (alen != sizeof(command)) {
err("%s: Send command incomplete [%d]", serial->type->name, alen);
goto error_out;
}
pipe = usb_rcvbulkpipe (serial->dev, 7);
ret = usb_bulk_msg (serial->dev, pipe, result, sizeof(result), &alen, 2 * HZ);
if (ret) {
err("%s: Couldn't get results [%d]", serial->type->name, ret);
goto error_out;
} else if (alen != sizeof(result)) {
err("%s: Get results incomplete [%d]", serial->type->name, alen);
goto error_out;
} else if (result[0] != command[0]) {
err("%s: Command failed [%d]", serial->type->name, result[0]);
goto error_out;
}
hw_info = (struct whiteheat_hw_info *)&result[1];
info("%s: Driver %s: Firmware v%d.%02d", serial->type->name,
DRIVER_VERSION, hw_info->sw_major_rev, hw_info->sw_minor_rev);
return 0;
error_out:
err("%s: Unable to retrieve firmware version, try replugging\n", serial->type->name);
/*
* Return that we've claimed the interface. A failure here may be
* due to interception by the command_callback routine or other
* causes that don't mean that the firmware isn't running. This may
* change in the future. Probably should actually.
*/
return 0;
}
static void whiteheat_real_shutdown (struct usb_serial *serial)
{
struct usb_serial_port *command_port;
int i;
......@@ -660,7 +715,7 @@ static int __init whiteheat_init (void)
{
usb_serial_register (&whiteheat_fake_device);
usb_serial_register (&whiteheat_device);
info(DRIVER_VERSION ":" DRIVER_DESC);
info(DRIVER_DESC " " DRIVER_VERSION);
return 0;
}
......
This source diff could not be displayed because it is too large. You can view the blob instead.
......@@ -215,6 +215,9 @@ inline void bio_init(struct bio *bio)
atomic_set(&bio->bi_cnt, 1);
bio->bi_flags = 0;
bio->bi_rw = 0;
bio->bi_vcnt = 0;
bio->bi_idx = 0;
bio->bi_size = 0;
bio->bi_end_io = NULL;
}
......
......@@ -318,7 +318,7 @@ static int partitions_read_proc(char *page, char **start, off_t off,
static void *single_start(struct seq_file *p, loff_t *pos)
{
return (void *)(*pos == 0);
return NULL + (*pos == 0);
}
static void *single_next(struct seq_file *p, void *v, loff_t *pos)
{
......@@ -561,9 +561,7 @@ void __init proc_misc_init(void)
entry->proc_fops = &proc_kmsg_operations;
create_seq_entry("mounts", 0, &proc_mounts_operations);
create_seq_entry("cpuinfo", 0, &proc_cpuinfo_operations);
#if defined(CONFIG_ARCH_S390) || defined(CONFIG_X86) || defined(CONFIG_ARCH_MIPS)
create_seq_entry("interrupts", 0, &proc_interrupts_operations);
#endif
#ifdef CONFIG_MODULES
create_seq_entry("ksyms", 0, &proc_ksyms_operations);
#endif
......
......@@ -64,8 +64,15 @@ do { \
printk("kernel BUG at %s:%d!\n", __FILE__, __LINE__); \
__asm__ __volatile__("call_pal %0 # bugchk" : : "i" (PAL_bugchk)); \
} while (0)
#define PAGE_BUG(page) BUG()
#define BUG_ON(condition) \
do { \
if (unlikely((long)(condition)))\
BUG(); \
} while (0)
/* Pure 2^n version of get_order */
extern __inline__ int get_order(unsigned long size)
{
......
......@@ -93,10 +93,9 @@ struct bio {
#define bio_iovec_idx(bio, idx) (&((bio)->bi_io_vec[(bio)->bi_idx]))
#define bio_iovec(bio) bio_iovec_idx((bio), (bio)->bi_idx)
#define bio_page(bio) bio_iovec((bio))->bv_page
#define bio_size(bio) ((bio)->bi_size)
#define __bio_offset(bio, idx) bio_iovec_idx((bio), (idx))->bv_offset
#define bio_offset(bio) bio_iovec((bio))->bv_offset
#define bio_sectors(bio) (bio_size((bio)) >> 9)
#define bio_sectors(bio) ((bio)->bi_size >> 9)
#define bio_data(bio) (page_address(bio_page((bio))) + bio_offset((bio)))
#define bio_barrier(bio) ((bio)->bi_rw & (1 << BIO_BARRIER))
......@@ -106,13 +105,6 @@ struct bio {
#define bio_to_phys(bio) (page_to_phys(bio_page((bio))) + bio_offset((bio)))
#define bvec_to_phys(bv) (page_to_phys((bv)->bv_page) + (bv)->bv_offset)
/*
* hack to avoid doing 64-bit calculations on 32-bit archs, instead use a
* pseudo-pfn check to do segment coalescing
*/
#define bio_sec_pfn(bio) \
((((bio_page(bio) - bio_page(bio)->zone->zone_mem_map) << PAGE_SHIFT) / bio_size(bio)) + (bio_offset(bio) >> 9))
/*
* queues that have highmem support enabled may still need to revert to
* PIO transfers occasionally and thus map high pages temporarily. For
......@@ -124,12 +116,16 @@ struct bio {
#define __bio_kunmap(bio, idx) kunmap(bio_iovec_idx((bio), (idx))->bv_page)
#define bio_kunmap(bio) __bio_kunmap((bio), (bio)->bi_idx)
/*
* merge helpers etc
*/
#define __BVEC_END(bio) bio_iovec_idx((bio), (bio)->bi_idx - 1)
#define BIO_CONTIG(bio, nxt) \
(bio_to_phys((bio)) + bio_size((bio)) == bio_to_phys((nxt)))
(bvec_to_phys(__BVEC_END((bio)) + (bio)->bi_size) ==bio_to_phys((nxt)))
#define __BIO_SEG_BOUNDARY(addr1, addr2, mask) \
(((addr1) | (mask)) == (((addr2) - 1) | (mask)))
#define BIO_SEG_BOUNDARY(q, b1, b2) \
__BIO_SEG_BOUNDARY(bvec_to_phys(bio_iovec_idx((b1), (b1)->bi_cnt - 1)), bio_to_phys((b2)) + bio_size((b2)), (q)->seg_boundary_mask)
__BIO_SEG_BOUNDARY(bvec_to_phys(__BVEC_END((b1))), bio_to_phys((b2)) + (b2)->bi_size, (q)->seg_boundary_mask)
typedef int (bio_end_io_t) (struct bio *, int);
typedef void (bio_destructor_t) (struct bio *);
......
......@@ -177,14 +177,11 @@ extern inline struct request *elv_next_request(request_queue_t *q)
#ifdef CONFIG_HIGHMEM
extern void create_bounce(struct bio **bio_orig, int gfp_mask);
extern void create_bounce(unsigned long pfn, struct bio **bio_orig, int gfp_mask);
extern inline void blk_queue_bounce(request_queue_t *q, struct bio **bio)
{
struct page *page = bio_page(*bio);
if ((page - page->zone->zone_mem_map) + (page->zone->zone_start_paddr >> PAGE_SHIFT) < q->bounce_pfn)
create_bounce(bio, q->bounce_gfp);
create_bounce(q->bounce_pfn, bio, q->bounce_gfp);
}
#else /* CONFIG_HIGHMEM */
......@@ -234,7 +231,7 @@ extern void blk_attempt_remerge(request_queue_t *, struct request *);
extern int blk_init_queue(request_queue_t *, request_fn_proc *);
extern void blk_cleanup_queue(request_queue_t *);
extern void blk_queue_make_request(request_queue_t *, make_request_fn *);
extern void blk_queue_bounce_limit(request_queue_t *, unsigned long long);
extern void blk_queue_bounce_limit(request_queue_t *, u64);
extern void blk_queue_max_sectors(request_queue_t *q, unsigned short);
extern void blk_queue_max_segments(request_queue_t *q, unsigned short);
extern void blk_queue_max_segment_size(request_queue_t *q, unsigned int);
......
......@@ -13,7 +13,7 @@ extern struct page *highmem_start_page;
/* declarations for linux/mm/highmem.c */
unsigned int nr_free_highpages(void);
extern void create_bounce(struct bio **bio_orig, int gfp_mask);
extern void create_bounce(unsigned long pfn, struct bio **bio_orig, int gfp_mask);
static inline char *bh_kmap(struct buffer_head *bh)
{
......
......@@ -307,14 +307,14 @@ struct usb_device;
/*
* Device table entry for "new style" table-driven USB drivers.
* User mode code can read these tables to choose which modules to load.
* Declare the table as __devinitdata, and as a MODULE_DEVICE_TABLE.
* Declare the table as a MODULE_DEVICE_TABLE.
*
* With a device table provide bind() instead of probe(). Then the
* third bind() parameter will point to a matching entry from this
* table. (Null value reserved.)
* The third probe() parameter will point to a matching entry from this
* table. (Null value reserved.) Use the driver_data field for each
* match to hold information tied to that match: device quirks, etc.
*
* Terminate the driver's table with an all-zeroes entry.
* Init the fields you care about; zeroes are not used in comparisons.
* Use the flag values to control which fields are compared.
*/
#define USB_DEVICE_ID_MATCH_VENDOR 0x0001
#define USB_DEVICE_ID_MATCH_PRODUCT 0x0002
......@@ -345,43 +345,115 @@ struct usb_device;
#define USB_INTERFACE_INFO(cl,sc,pr) \
match_flags: USB_DEVICE_ID_MATCH_INT_INFO, bInterfaceClass: (cl), bInterfaceSubClass: (sc), bInterfaceProtocol: (pr)
struct usb_device_id {
/* This bitmask is used to determine which of the following fields
* are to be used for matching.
/**
* struct usb_device_id - identifies USB devices for probing and hotplugging
* @match_flags: Bit mask controlling of the other fields are used to match
* against new devices. Any field except for driver_info may be used,
* although some only make sense in conjunction with other fields.
* This is usually set by a USB_DEVICE_*() macro, which sets all
* other fields in this structure except for driver_info.
* @idVendor: USB vendor ID for a device; numbers are assigned
* by the USB forum to its members.
* @idProduct: Vendor-assigned product ID.
* @bcdDevice_lo: Low end of range of vendor-assigned product version numbers.
* This is also used to identify individual product versions, for
* a range consisting of a single device.
* @bcdDevice_hi: High end of version number range. The range of product
* versions is inclusive.
* @bDeviceClass: Class of device; numbers are assigned
* by the USB forum. Products may choose to implement classes,
* or be vendor-specific. Device classes specify behavior of all
* the interfaces on a devices.
* @bDeviceSubClass: Subclass of device; associated with bDeviceClass.
* @bDeviceProtocol: Protocol of device; associated with bDeviceClass.
* @bInterfaceClass: Class of interface; numbers are assigned
* by the USB forum. Products may choose to implement classes,
* or be vendor-specific. Interface classes specify behavior only
* of a given interface; other interfaces may support other classes.
* @bInterfaceSubClass: Subclass of interface; associated with bInterfaceClass.
* @bInterfaceProtocol: Protocol of interface; associated with bInterfaceClass.
* @driver_info: Holds information used by the driver. Usually it holds
* a pointer to a descriptor understood by the driver, or perhaps
* device flags.
*
* In most cases, drivers will create a table of device IDs by using
* the USB_DEVICE() macros designed for that purpose.
* They will then export it to userspace using MODULE_DEVICE_TABLE(),
* and provide it to the USB core through their usb_driver structure.
*
* See the usb_match_id() function for information about how matches are
* performed. Briefly, you will normally use one of several macros to help
* construct these entries. Each entry you provide will either identify
* one or more specific products, or will identify a class of products
* which have agreed to behave the same. You should put the more specific
* matches towards the beginning of your table, so that driver_info can
* record quirks of specific products.
*/
struct usb_device_id {
/* which fields to match against? */
__u16 match_flags;
/*
* vendor/product codes are checked, if vendor is nonzero
* Range is for device revision (bcdDevice), inclusive;
* zero values here mean range isn't considered
*/
/* Used for product specific matches; range is inclusive */
__u16 idVendor;
__u16 idProduct;
__u16 bcdDevice_lo, bcdDevice_hi;
__u16 bcdDevice_lo;
__u16 bcdDevice_hi;
/*
* if device class != 0, these can be match criteria;
* but only if this bDeviceClass value is nonzero
*/
/* Used for device class matches */
__u8 bDeviceClass;
__u8 bDeviceSubClass;
__u8 bDeviceProtocol;
/*
* if interface class != 0, these can be match criteria;
* but only if this bInterfaceClass value is nonzero
*/
/* Used for interface class matches */
__u8 bInterfaceClass;
__u8 bInterfaceSubClass;
__u8 bInterfaceProtocol;
/*
* for driver's use; not involved in driver matching.
*/
/* not matched against */
unsigned long driver_info;
};
/**
* struct usb_driver - identifies USB driver to usbcore
* @name: The driver name should be unique among USB drivers
* @probe: Called to see if the driver is willing to manage a particular
* interface on a device. The probe routine returns a handle that
* will later be provided to disconnect(), or a null pointer to
* indicate that the driver will not handle the interface.
* The handle is normally a pointer to driver-specific data.
* If the probe() routine needs to access the interface
* structure itself, use usb_ifnum_to_if() to make sure it's using
* the right one.
* @disconnect: Called when the interface is no longer accessible, usually
* because its device has been (or is being) disconnected. The
* handle passed is what was returned by probe(), or was provided
* to usb_driver_claim_interface().
* @fops: USB drivers can reuse some character device framework in
* the USB subsystem by providing a file operations vector and
* a minor number.
* @minor: Used with fops to simplify creating USB character devices.
* Such drivers have sixteen character devices, using the USB
* major number and starting with this minor number.
* @ioctl: Used for drivers that want to talk to userspace through
* the "usbfs" filesystem. This lets devices provide ways to
* expose information to user space regardless of where they
* do (or don't) show up otherwise in the filesystem.
* @id_table: USB drivers use ID table to support hotplugging.
*
* USB drivers should provide a name, probe() and disconnect() methods,
* and an id_table. Other driver fields are optional.
*
* The id_table is used in hotplugging. It holds a set of descriptors,
* and specialized data may be associated with each entry. That table
* is used by both user and kernel mode hotplugging support.
*
* The probe() and disconnect() methods are called in a context where
* they can sleep, but they should avoid abusing the privilage. Most
* work to connect to a device should be done when the device is opened,
* and undone at the last close. The disconnect code needs to address
* concurrency issues with respect to open() and close() methods, as
* well as cancel any I/O requests that are still pending.
*/
struct usb_driver {
const char *name;
......@@ -390,7 +462,10 @@ struct usb_driver {
unsigned intf, /* what interface */
const struct usb_device_id *id /* from id_table */
);
void (*disconnect)(struct usb_device *, void *);
void (*disconnect)(
struct usb_device *dev, /* the device */
void *handle /* as returned by probe() */
);
struct list_head driver_list;
......@@ -402,9 +477,7 @@ struct usb_driver {
/* ioctl -- userspace apps can talk to drivers through usbdevfs */
int (*ioctl)(struct usb_device *dev, unsigned int code, void *buf);
/* support for "new-style" USB hotplugging
* binding policy can be driven from user mode too
*/
/* support for "new-style" USB hotplugging */
const struct usb_device_id *id_table;
/* suspend before the bus suspends;
......@@ -419,6 +492,8 @@ struct usb_driver {
/*
* urb->transfer_flags:
*
* FIXME should be URB_* flags
*/
#define USB_DISABLE_SPD 0x0001
#define USB_ISO_ASAP 0x0002
......@@ -439,68 +514,237 @@ typedef struct
struct urb;
typedef void (*usb_complete_t)(struct urb *);
typedef struct urb
/**
* struct urb - USB Request Block
* @urb_list: For use by current owner of the URB.
* @next: Used primarily to link ISO requests into rings.
* @pipe: Holds endpoint number, direction, type, and max packet size.
* Create these values with the eight macros available;
* usb_{snd,rcv}TYPEpipe(dev,endpoint), where the type is "ctrl"
* (control), "bulk", "int" (interrupt), or "iso" (isochronous).
* For example usb_sndbulkpipe() or usb_rcvintpipe(). Endpoint
* numbers range from zero to fifteen. Note that "in" endpoint two
* is a different endpoint (and pipe) from "out" endpoint two.
* The current configuration controls the existence, type, and
* maximum packet size of any given endpoint.
* @dev: Identifies the USB device to perform the request.
* @status: This is read in non-iso completion functions to get the
* status of the particular request. ISO requests only use it
* to tell whether the URB was unlinked; detailed status for
* each frame is in the fields of the iso_frame-desc.
* @transfer_flags: A variety of flags may be used to affect how URB
* submission, unlinking, or operation are handled. Different
* kinds of URB can use different flags.
* @transfer_buffer: For non-iso transfers, this identifies the buffer
* to (or from) which the I/O request will be performed. This
* buffer must be suitable for DMA; allocate it with kmalloc()
* or equivalent. For transfers to "in" endpoints, contents of
* this buffer will be modified.
* @transfer_buffer_length: How big is transfer_buffer. The transfer may
* be broken up into chunks according to the current maximum packet
* size for the endpoint, which is a function of the configuration
* and is encoded in the pipe.
* @actual_length: This is read in non-iso completion functions, and
* it tells how many bytes (out of transfer_buffer_length) were
* transferred. It will normally be the same as requested, unless
* either an error was reported or a short read was performed and
* the USB_DISABLE_SPD transfer flag was used to say that such
* short reads are not errors.
* @setup_packet: Only used for control transfers, this points to eight bytes
* of setup data. Control transfers always start by sending this data
* to the device. Then transfer_buffer is read or written, if needed.
* @start_frame: Returns the initial frame for interrupt or isochronous
* transfers.
* @number_of_packets: Lists the number of ISO transfer buffers.
* @interval: Specifies the polling interval for interrupt transfers, in
* milliseconds.
* @error_count: Returns the number of ISO transfers that reported errors.
* @context: For use in completion functions. This normally points to
* request-specific driver context.
* @complete: Completion handler. This URB is passed as the parameter to the
* completion function. Except for interrupt or isochronous transfers
* that aren't being unlinked, the completion function may then do what
* it likes with the URB, including resubmitting or freeing it.
* @iso_frame_desc: Used to provide arrays of ISO transfer buffers and to
* collect the transfer status for each buffer.
*
* This structure identifies USB transfer requests. URBs may be allocated
* in any way, although usb_alloc_urb() is often convenient. Initialization
* may be done using various FILL_*_URB() macros. URBs are submitted
* using usb_submit_urb(), and pending requests may be canceled using
* usb_unlink_urb().
*
* Initialization:
*
* All URBs submitted must initialize dev, pipe, next (may be null),
* transfer_flags (may be zero), complete, timeout (may be zero).
* The USB_ASYNC_UNLINK transfer flag affects later invocations of
* the usb_unlink_urb() routine.
*
* All non-isochronous URBs must also initialize
* transfer_buffer and transfer_buffer_length. They may provide the
* USB_DISABLE_SPD transfer flag, indicating that short reads are
* not to be treated as errors.
*
* Bulk URBs may pass the USB_QUEUE_BULK transfer flag, telling the host
* controller driver never to report an error if several bulk requests get
* queued to the same endpoint. Such queueing supports more efficient use
* of bus bandwidth, minimizing delays due to interrupts and scheduling,
* if the host controller hardware is smart enough. Bulk URBs can also
* use the USB_ZERO_PACKET transfer flag, indicating that bulk OUT transfers
* should always terminate with a short packet, even if it means adding an
* extra zero length packet.
*
* Control URBs must provide a setup_packet.
*
* Interupt UBS must provide an interval, saying how often (in milliseconds)
* to poll for transfers. After the URB has been submitted, the interval
* and start_frame fields reflect how the transfer was actually scheduled.
* The polling interval may be more frequent than requested.
*
* Isochronous URBs normally use the USB_ISO_ASAP transfer flag, telling
* the host controller to schedule the transfer as soon as bandwidth
* utilization allows, and then set start_frame to reflect the actual frame
* selected during submission. Otherwise drivers must specify the start_frame
* and handle the case where the transfer can't begin then. However, drivers
* won't know how bandwidth is currently allocated, and while they can
* find the current frame using usb_get_current_frame_number () they can't
* know the range for that frame number. (Common ranges for the frame
* counter include 256, 512, and 1024 frames.)
*
* Isochronous URBs have a different data transfer model, in part because
* the quality of service is only "best effort". Callers provide specially
* allocated URBs, with number_of_packets worth of iso_frame_desc structures
* at the end. Each such packet is an individual ISO transfer. Isochronous
* URBs are normally submitted with urb->next fields set up as a ring, so
* that data (such as audio or video) streams at as constant a rate as the
* host controller scheduler can support.
*
* Completion Callbacks:
*
* The completion callback is made in_interrupt(), and one of the first
* things that a completion handler should do is check the status field.
* The status field is provided for all URBs. It is used to report
* unlinked URBs, and status for all non-ISO transfers. It should not
* be examined outside of the completion handler.
*
* The context field is normally used to link URBs back to the relevant
* driver or request state.
*
* When completion callback is invoked for non-isochronous URBs, the
* actual_length field tells how many bytes were transferred.
*
* For interrupt and isochronous URBs, the URB provided to the calllback
* function is still "owned" by the USB core subsystem unless the status
* indicates that the URB has been unlinked. Completion handlers should
* not modify such URBs until they have been unlinked.
*
* ISO transfer status is reported in the status and actual_length fields
* of the iso_frame_desc array, and the number of errors is reported in
* error_count.
*/
struct urb
{
spinlock_t lock; // lock for the URB
void *hcpriv; // private data for host controller
struct list_head urb_list; // list pointer to all active urbs
struct urb *next; // pointer to next URB
struct usb_device *dev; // pointer to associated USB device
unsigned int pipe; // pipe information
int status; // returned status
unsigned int transfer_flags; // USB_DISABLE_SPD | USB_ISO_ASAP | etc.
void *transfer_buffer; // associated data buffer
int transfer_buffer_length; // data buffer length
int actual_length; // actual data buffer length
int bandwidth; // bandwidth for this transfer request (INT or ISO)
unsigned char *setup_packet; // setup packet (control only)
//
int start_frame; // start frame (iso/irq only)
int number_of_packets; // number of packets in this request (iso)
int interval; // polling interval (irq only)
int error_count; // number of errors in this transfer (iso only)
int timeout; // timeout (in jiffies)
//
void *context; // context for completion routine
usb_complete_t complete; // pointer to completion routine
//
iso_packet_descriptor_t iso_frame_desc[0];
} urb_t, *purb_t;
#define FILL_CONTROL_URB(a,aa,b,c,d,e,f,g) \
spinlock_t lock; /* lock for the URB */
void *hcpriv; /* private data for host controller */
struct list_head urb_list; /* list pointer to all active urbs */
struct urb *next; /* (in) pointer to next URB */
struct usb_device *dev; /* (in) pointer to associated device */
unsigned int pipe; /* (in) pipe information */
int status; /* (return) non-ISO status */
unsigned int transfer_flags; /* (in) USB_DISABLE_SPD | ...*/
void *transfer_buffer; /* (in) associated data buffer */
int transfer_buffer_length; /* (in) data buffer length */
int actual_length; /* (return) actual transfer length */
int bandwidth; /* bandwidth for INT/ISO request */
unsigned char *setup_packet; /* (in) setup packet (control only) */
int start_frame; /* (modify) start frame (INT/ISO) */
int number_of_packets; /* (in) number of ISO packets */
int interval; /* (in) polling interval (INT only) */
int error_count; /* (return) number of ISO errors */
int timeout; /* (in) timeout, in jiffies */
void *context; /* (in) context for completion */
usb_complete_t complete; /* (in) completion routine */
iso_packet_descriptor_t iso_frame_desc[0]; /* (in) ISO ONLY */
};
typedef struct urb urb_t, *purb_t;
/**
* FILL_CONTROL_URB - macro to help initialize a control urb
* @URB: pointer to the urb to initialize.
* @DEV: pointer to the struct usb_device for this urb.
* @PIPE: the endpoint pipe
* @SETUP_PACKET: pointer to the setup_packet buffer
* @TRANSFER_BUFFER: pointer to the transfer buffer
* @BUFFER_LENGTH: length of the transfer buffer
* @COMPLETE: pointer to the usb_complete_t function
* @CONTEXT: what to set the urb context to.
*
* Initializes a control urb with the proper information needed to submit it to
* a device.
*/
#define FILL_CONTROL_URB(URB,DEV,PIPE,SETUP_PACKET,TRANSFER_BUFFER,BUFFER_LENGTH,COMPLETE,CONTEXT) \
do {\
spin_lock_init(&(a)->lock);\
(a)->dev=aa;\
(a)->pipe=b;\
(a)->setup_packet=c;\
(a)->transfer_buffer=d;\
(a)->transfer_buffer_length=e;\
(a)->complete=f;\
(a)->context=g;\
spin_lock_init(&(URB)->lock);\
(URB)->dev=DEV;\
(URB)->pipe=PIPE;\
(URB)->setup_packet=SETUP_PACKET;\
(URB)->transfer_buffer=TRANSFER_BUFFER;\
(URB)->transfer_buffer_length=BUFFER_LENGTH;\
(URB)->complete=COMPLETE;\
(URB)->context=CONTEXT;\
} while (0)
#define FILL_BULK_URB(a,aa,b,c,d,e,f) \
/**
* FILL_BULK_URB - macro to help initialize a bulk urb
* @URB: pointer to the urb to initialize.
* @DEV: pointer to the struct usb_device for this urb.
* @PIPE: the endpoint pipe
* @TRANSFER_BUFFER: pointer to the transfer buffer
* @BUFFER_LENGTH: length of the transfer buffer
* @COMPLETE: pointer to the usb_complete_t function
* @CONTEXT: what to set the urb context to.
*
* Initializes a bulk urb with the proper information needed to submit it to
* a device.
*/
#define FILL_BULK_URB(URB,DEV,PIPE,TRANSFER_BUFFER,BUFFER_LENGTH,COMPLETE,CONTEXT) \
do {\
spin_lock_init(&(a)->lock);\
(a)->dev=aa;\
(a)->pipe=b;\
(a)->transfer_buffer=c;\
(a)->transfer_buffer_length=d;\
(a)->complete=e;\
(a)->context=f;\
spin_lock_init(&(URB)->lock);\
(URB)->dev=DEV;\
(URB)->pipe=PIPE;\
(URB)->transfer_buffer=TRANSFER_BUFFER;\
(URB)->transfer_buffer_length=BUFFER_LENGTH;\
(URB)->complete=COMPLETE;\
(URB)->context=CONTEXT;\
} while (0)
#define FILL_INT_URB(a,aa,b,c,d,e,f,g) \
/**
* FILL_INT_URB - macro to help initialize a interrupt urb
* @URB: pointer to the urb to initialize.
* @DEV: pointer to the struct usb_device for this urb.
* @PIPE: the endpoint pipe
* @TRANSFER_BUFFER: pointer to the transfer buffer
* @BUFFER_LENGTH: length of the transfer buffer
* @COMPLETE: pointer to the usb_complete_t function
* @CONTEXT: what to set the urb context to.
* @INTERVAL: what to set the urb interval to.
*
* Initializes a interrupt urb with the proper information needed to submit it to
* a device.
*/
#define FILL_INT_URB(URB,DEV,PIPE,TRANSFER_BUFFER,BUFFER_LENGTH,COMPLETE,CONTEXT,INTERVAL) \
do {\
spin_lock_init(&(a)->lock);\
(a)->dev=aa;\
(a)->pipe=b;\
(a)->transfer_buffer=c;\
(a)->transfer_buffer_length=d;\
(a)->complete=e;\
(a)->context=f;\
(a)->interval=g;\
(a)->start_frame=-1;\
spin_lock_init(&(URB)->lock);\
(URB)->dev=DEV;\
(URB)->pipe=PIPE;\
(URB)->transfer_buffer=TRANSFER_BUFFER;\
(URB)->transfer_buffer_length=BUFFER_LENGTH;\
(URB)->complete=COMPLETE;\
(URB)->context=CONTEXT;\
(URB)->interval=INTERVAL;\
(URB)->start_frame=-1;\
} while (0)
#define FILL_CONTROL_URB_TO(a,aa,b,c,d,e,f,g,h) \
......
......@@ -207,35 +207,31 @@ static LIST_HEAD(emergency_bhs);
* queue gfp mask set, *to may or may not be a highmem page. kmap it
* always, it will do the Right Thing
*/
static inline void copy_from_high_bio(struct bio *to, struct bio *from)
static inline void copy_to_high_bio_irq(struct bio *to, struct bio *from)
{
unsigned char *vto, *vfrom;
unsigned long flags;
struct bio_vec *tovec, *fromvec;
int i;
if (unlikely(in_interrupt()))
BUG();
vto = bio_kmap(to);
vfrom = bio_kmap(from);
bio_for_each_segment(tovec, to, i) {
fromvec = &from->bi_io_vec[i];
memcpy(vto, vfrom + bio_offset(from), bio_size(to));
/*
* not bounced
*/
if (tovec->bv_page == fromvec->bv_page)
continue;
bio_kunmap(from);
bio_kunmap(to);
}
static inline void copy_to_high_bio_irq(struct bio *to, struct bio *from)
{
unsigned char *vto, *vfrom;
unsigned long flags;
vfrom = page_address(fromvec->bv_page) + fromvec->bv_offset;
__save_flags(flags);
__cli();
vto = kmap_atomic(bio_page(to), KM_BOUNCE_READ);
vfrom = kmap_atomic(bio_page(from), KM_BOUNCE_READ);
memcpy(vto + bio_offset(to), vfrom, bio_size(to));
kunmap_atomic(vfrom, KM_BOUNCE_READ);
vto = kmap_atomic(tovec->bv_page, KM_BOUNCE_READ);
memcpy(vto + tovec->bv_offset, vfrom, to->bi_size);
kunmap_atomic(vto, KM_BOUNCE_READ);
__restore_flags(flags);
}
}
static __init int init_emergency_pool(void)
......@@ -347,16 +343,65 @@ struct page *alloc_bounce_page(int gfp_mask)
goto repeat_alloc;
}
void create_bounce(struct bio **bio_orig, int gfp_mask)
void create_bounce(unsigned long pfn, struct bio **bio_orig, int gfp_mask)
{
struct page *page;
struct bio *bio;
struct bio *bio = NULL;
int i, rw = bio_data_dir(*bio_orig);
struct bio_vec *to, *from;
BUG_ON((*bio_orig)->bi_idx);
bio_for_each_segment(from, *bio_orig, i) {
page = from->bv_page;
/*
* is destination page below bounce pfn?
*/
if ((page - page->zone->zone_mem_map) + (page->zone->zone_start_paddr >> PAGE_SHIFT) < pfn)
continue;
/*
* irk, bounce it
*/
if (!bio)
bio = bio_alloc(GFP_NOHIGHIO, (*bio_orig)->bi_vcnt);
to = &bio->bi_io_vec[i];
to->bv_page = alloc_bounce_page(gfp_mask);
to->bv_len = from->bv_len;
to->bv_offset = from->bv_offset;
if (rw & WRITE) {
char *vto, *vfrom;
vto = page_address(to->bv_page) + to->bv_offset;
vfrom = kmap(from->bv_page);
memcpy(vto, vfrom + from->bv_offset, to->bv_len);
kunmap(to->bv_page);
}
}
/*
* no pages bounced
*/
if (!bio)
return;
/*
* at least one page was bounced, fill in possible non-highmem
* pages
*/
bio_for_each_segment(from, *bio_orig, i) {
to = &bio->bi_io_vec[i];
if (!to->bv_page) {
to->bv_page = from->bv_page;
to->bv_len = from->bv_len;
to->bv_offset = to->bv_offset;
}
}
bio->bi_dev = (*bio_orig)->bi_dev;
bio->bi_sector = (*bio_orig)->bi_sector;
bio->bi_rw = (*bio_orig)->bi_rw;
......@@ -370,23 +415,6 @@ void create_bounce(struct bio **bio_orig, int gfp_mask)
else
bio->bi_end_io = bounce_end_io_read;
for (i = 0; i < bio->bi_vcnt; i++) {
char *vto, *vfrom;
page = alloc_bounce_page(gfp_mask);
bio->bi_io_vec[i].bv_page = page;
bio->bi_io_vec[i].bv_len = (*bio_orig)->bi_io_vec[i].bv_len;
bio->bi_io_vec[i].bv_offset = 0;
if (rw & WRITE) {
vto = page_address(page);
vfrom = __bio_kmap(*bio_orig, i);
memcpy(vto, vfrom + __bio_offset(*bio_orig, i), bio->bi_io_vec[i].bv_len);
__bio_kunmap(bio, i);
}
}
bio->bi_private = *bio_orig;
*bio_orig = bio;
}
......@@ -47,6 +47,7 @@
#include <linux/route.h>
#include <linux/udp.h>
#include <linux/proc_fs.h>
#include <linux/major.h>
#include <net/arp.h>
#include <net/ip.h>
#include <net/ipconfig.h>
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment