aboutsummaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/block/ub.c4
-rw-r--r--drivers/char/agp/agp.h2
-rw-r--r--drivers/char/agp/ali-agp.c4
-rw-r--r--drivers/char/agp/amd-k7-agp.c6
-rw-r--r--drivers/char/agp/amd64-agp.c4
-rw-r--r--drivers/char/agp/ati-agp.c6
-rw-r--r--drivers/char/agp/backend.c6
-rw-r--r--drivers/char/agp/efficeon-agp.c2
-rw-r--r--drivers/char/agp/generic.c36
-rw-r--r--drivers/char/agp/hp-agp.c4
-rw-r--r--drivers/char/agp/i460-agp.c4
-rw-r--r--drivers/char/agp/intel-agp.c21
-rw-r--r--drivers/char/agp/sgi-agp.c12
-rw-r--r--drivers/char/agp/sworks-agp.c8
-rw-r--r--drivers/char/agp/uninorth-agp.c2
-rw-r--r--drivers/char/mxser.c38
-rw-r--r--drivers/input/keyboard/atkbd.c2
-rw-r--r--drivers/md/dm-mpath.c3
-rw-r--r--drivers/net/tg3.c39
-rw-r--r--drivers/pci/hotplug/cpci_hotplug_core.c2
-rw-r--r--drivers/pci/hotplug/cpci_hotplug_pci.c5
-rw-r--r--drivers/pci/pci.ids1
-rw-r--r--drivers/pci/quirks.c35
-rw-r--r--drivers/scsi/libata-core.c4
-rw-r--r--drivers/scsi/sata_sil.c8
-rw-r--r--drivers/serial/sa1100.c2
-rw-r--r--drivers/usb/serial/ftdi_sio.c118
27 files changed, 234 insertions, 144 deletions
diff --git a/drivers/block/ub.c b/drivers/block/ub.c
index adc4dcc306f..19c5e59bcfa 100644
--- a/drivers/block/ub.c
+++ b/drivers/block/ub.c
@@ -51,7 +51,7 @@
* This many LUNs per USB device.
* Every one of them takes a host, see UB_MAX_HOSTS.
*/
-#define UB_MAX_LUNS 4
+#define UB_MAX_LUNS 9
/*
*/
@@ -2100,7 +2100,7 @@ static int ub_probe(struct usb_interface *intf,
nluns = rc;
break;
}
- mdelay(100);
+ msleep(100);
}
for (i = 0; i < nluns; i++) {
diff --git a/drivers/char/agp/agp.h b/drivers/char/agp/agp.h
index ad9c11391d8..c1fe013c64f 100644
--- a/drivers/char/agp/agp.h
+++ b/drivers/char/agp/agp.h
@@ -278,6 +278,8 @@ void agp3_generic_cleanup(void);
#define AGP_GENERIC_SIZES_ENTRIES 11
extern struct aper_size_info_16 agp3_generic_sizes[];
+#define virt_to_gart(x) (phys_to_gart(virt_to_phys(x)))
+#define gart_to_virt(x) (phys_to_virt(gart_to_phys(x)))
extern int agp_off;
extern int agp_try_unsupported_boot;
diff --git a/drivers/char/agp/ali-agp.c b/drivers/char/agp/ali-agp.c
index 0212febda65..9c9c9c2247c 100644
--- a/drivers/char/agp/ali-agp.c
+++ b/drivers/char/agp/ali-agp.c
@@ -150,7 +150,7 @@ static void *m1541_alloc_page(struct agp_bridge_data *bridge)
pci_read_config_dword(agp_bridge->dev, ALI_CACHE_FLUSH_CTRL, &temp);
pci_write_config_dword(agp_bridge->dev, ALI_CACHE_FLUSH_CTRL,
(((temp & ALI_CACHE_FLUSH_ADDR_MASK) |
- virt_to_phys(addr)) | ALI_CACHE_FLUSH_EN ));
+ virt_to_gart(addr)) | ALI_CACHE_FLUSH_EN ));
return addr;
}
@@ -174,7 +174,7 @@ static void m1541_destroy_page(void * addr)
pci_read_config_dword(agp_bridge->dev, ALI_CACHE_FLUSH_CTRL, &temp);
pci_write_config_dword(agp_bridge->dev, ALI_CACHE_FLUSH_CTRL,
(((temp & ALI_CACHE_FLUSH_ADDR_MASK) |
- virt_to_phys(addr)) | ALI_CACHE_FLUSH_EN));
+ virt_to_gart(addr)) | ALI_CACHE_FLUSH_EN));
agp_generic_destroy_page(addr);
}
diff --git a/drivers/char/agp/amd-k7-agp.c b/drivers/char/agp/amd-k7-agp.c
index e62a3c2c44a..3a41672e4d6 100644
--- a/drivers/char/agp/amd-k7-agp.c
+++ b/drivers/char/agp/amd-k7-agp.c
@@ -43,7 +43,7 @@ static int amd_create_page_map(struct amd_page_map *page_map)
SetPageReserved(virt_to_page(page_map->real));
global_cache_flush();
- page_map->remapped = ioremap_nocache(virt_to_phys(page_map->real),
+ page_map->remapped = ioremap_nocache(virt_to_gart(page_map->real),
PAGE_SIZE);
if (page_map->remapped == NULL) {
ClearPageReserved(virt_to_page(page_map->real));
@@ -154,7 +154,7 @@ static int amd_create_gatt_table(struct agp_bridge_data *bridge)
agp_bridge->gatt_table_real = (u32 *)page_dir.real;
agp_bridge->gatt_table = (u32 __iomem *)page_dir.remapped;
- agp_bridge->gatt_bus_addr = virt_to_phys(page_dir.real);
+ agp_bridge->gatt_bus_addr = virt_to_gart(page_dir.real);
/* Get the address for the gart region.
* This is a bus address even on the alpha, b/c its
@@ -167,7 +167,7 @@ static int amd_create_gatt_table(struct agp_bridge_data *bridge)
/* Calculate the agp offset */
for (i = 0; i < value->num_entries / 1024; i++, addr += 0x00400000) {
- writel(virt_to_phys(amd_irongate_private.gatt_pages[i]->real) | 1,
+ writel(virt_to_gart(amd_irongate_private.gatt_pages[i]->real) | 1,
page_dir.remapped+GET_PAGE_DIR_OFF(addr));
readl(page_dir.remapped+GET_PAGE_DIR_OFF(addr)); /* PCI Posting. */
}
diff --git a/drivers/char/agp/amd64-agp.c b/drivers/char/agp/amd64-agp.c
index 399c042f68f..1407945a589 100644
--- a/drivers/char/agp/amd64-agp.c
+++ b/drivers/char/agp/amd64-agp.c
@@ -219,7 +219,7 @@ static struct aper_size_info_32 amd_8151_sizes[7] =
static int amd_8151_configure(void)
{
- unsigned long gatt_bus = virt_to_phys(agp_bridge->gatt_table_real);
+ unsigned long gatt_bus = virt_to_gart(agp_bridge->gatt_table_real);
/* Configure AGP regs in each x86-64 host bridge. */
for_each_nb() {
@@ -591,7 +591,7 @@ static void __devexit agp_amd64_remove(struct pci_dev *pdev)
{
struct agp_bridge_data *bridge = pci_get_drvdata(pdev);
- release_mem_region(virt_to_phys(bridge->gatt_table_real),
+ release_mem_region(virt_to_gart(bridge->gatt_table_real),
amd64_aperture_sizes[bridge->aperture_size_idx].size);
agp_remove_bridge(bridge);
agp_put_bridge(bridge);
diff --git a/drivers/char/agp/ati-agp.c b/drivers/char/agp/ati-agp.c
index a65f8827c28..e572ced9100 100644
--- a/drivers/char/agp/ati-agp.c
+++ b/drivers/char/agp/ati-agp.c
@@ -61,7 +61,7 @@ static int ati_create_page_map(ati_page_map *page_map)
SetPageReserved(virt_to_page(page_map->real));
err = map_page_into_agp(virt_to_page(page_map->real));
- page_map->remapped = ioremap_nocache(virt_to_phys(page_map->real),
+ page_map->remapped = ioremap_nocache(virt_to_gart(page_map->real),
PAGE_SIZE);
if (page_map->remapped == NULL || err) {
ClearPageReserved(virt_to_page(page_map->real));
@@ -343,7 +343,7 @@ static int ati_create_gatt_table(struct agp_bridge_data *bridge)
agp_bridge->gatt_table_real = (u32 *)page_dir.real;
agp_bridge->gatt_table = (u32 __iomem *) page_dir.remapped;
- agp_bridge->gatt_bus_addr = virt_to_bus(page_dir.real);
+ agp_bridge->gatt_bus_addr = virt_to_gart(page_dir.real);
/* Write out the size register */
current_size = A_SIZE_LVL2(agp_bridge->current_size);
@@ -373,7 +373,7 @@ static int ati_create_gatt_table(struct agp_bridge_data *bridge)
/* Calculate the agp offset */
for(i = 0; i < value->num_entries / 1024; i++, addr += 0x00400000) {
- writel(virt_to_bus(ati_generic_private.gatt_pages[i]->real) | 1,
+ writel(virt_to_gart(ati_generic_private.gatt_pages[i]->real) | 1,
page_dir.remapped+GET_PAGE_DIR_OFF(addr));
readl(page_dir.remapped+GET_PAGE_DIR_OFF(addr)); /* PCI Posting. */
}
diff --git a/drivers/char/agp/backend.c b/drivers/char/agp/backend.c
index 2f3dfb63bdc..4d4e602fdc7 100644
--- a/drivers/char/agp/backend.c
+++ b/drivers/char/agp/backend.c
@@ -148,7 +148,7 @@ static int agp_backend_initialize(struct agp_bridge_data *bridge)
return -ENOMEM;
}
- bridge->scratch_page_real = virt_to_phys(addr);
+ bridge->scratch_page_real = virt_to_gart(addr);
bridge->scratch_page =
bridge->driver->mask_memory(bridge, bridge->scratch_page_real, 0);
}
@@ -189,7 +189,7 @@ static int agp_backend_initialize(struct agp_bridge_data *bridge)
err_out:
if (bridge->driver->needs_scratch_page)
bridge->driver->agp_destroy_page(
- phys_to_virt(bridge->scratch_page_real));
+ gart_to_virt(bridge->scratch_page_real));
if (got_gatt)
bridge->driver->free_gatt_table(bridge);
if (got_keylist) {
@@ -214,7 +214,7 @@ static void agp_backend_cleanup(struct agp_bridge_data *bridge)
if (bridge->driver->agp_destroy_page &&
bridge->driver->needs_scratch_page)
bridge->driver->agp_destroy_page(
- phys_to_virt(bridge->scratch_page_real));
+ gart_to_virt(bridge->scratch_page_real));
}
/* When we remove the global variable agp_bridge from all drivers
diff --git a/drivers/char/agp/efficeon-agp.c b/drivers/char/agp/efficeon-agp.c
index 1383c3165ea..ac19fdcd21c 100644
--- a/drivers/char/agp/efficeon-agp.c
+++ b/drivers/char/agp/efficeon-agp.c
@@ -219,7 +219,7 @@ static int efficeon_create_gatt_table(struct agp_bridge_data *bridge)
efficeon_private.l1_table[index] = page;
- value = __pa(page) | pati | present | index;
+ value = virt_to_gart(page) | pati | present | index;
pci_write_config_dword(agp_bridge->dev,
EFFICEON_ATTPAGE, value);
diff --git a/drivers/char/agp/generic.c b/drivers/char/agp/generic.c
index c321a924e38..f0079e991bd 100644
--- a/drivers/char/agp/generic.c
+++ b/drivers/char/agp/generic.c
@@ -153,7 +153,7 @@ void agp_free_memory(struct agp_memory *curr)
}
if (curr->page_count != 0) {
for (i = 0; i < curr->page_count; i++) {
- curr->bridge->driver->agp_destroy_page(phys_to_virt(curr->memory[i]));
+ curr->bridge->driver->agp_destroy_page(gart_to_virt(curr->memory[i]));
}
}
agp_free_key(curr->key);
@@ -209,7 +209,7 @@ struct agp_memory *agp_allocate_memory(struct agp_bridge_data *bridge,
agp_free_memory(new);
return NULL;
}
- new->memory[i] = virt_to_phys(addr);
+ new->memory[i] = virt_to_gart(addr);
new->page_count++;
}
new->bridge = bridge;
@@ -295,19 +295,6 @@ int agp_num_entries(void)
EXPORT_SYMBOL_GPL(agp_num_entries);
-static int check_bridge_mode(struct pci_dev *dev)
-{
- u32 agp3;
- u8 cap_ptr;
-
- cap_ptr = pci_find_capability(dev, PCI_CAP_ID_AGP);
- pci_read_config_dword(dev, cap_ptr+AGPSTAT, &agp3);
- if (agp3 & AGPSTAT_MODE_3_0)
- return 1;
- return 0;
-}
-
-
/**
* agp_copy_info - copy bridge state information
*
@@ -328,7 +315,7 @@ int agp_copy_info(struct agp_bridge_data *bridge, struct agp_kern_info *info)
info->version.minor = bridge->version->minor;
info->chipset = SUPPORTED;
info->device = bridge->dev;
- if (check_bridge_mode(bridge->dev))
+ if (bridge->mode & AGPSTAT_MODE_3_0)
info->mode = bridge->mode & ~AGP3_RESERVED_MASK;
else
info->mode = bridge->mode & ~AGP2_RESERVED_MASK;
@@ -661,7 +648,7 @@ u32 agp_collect_device_status(struct agp_bridge_data *bridge, u32 requested_mode
bridge_agpstat &= ~AGPSTAT_FW;
/* Check to see if we are operating in 3.0 mode */
- if (check_bridge_mode(agp_bridge->dev))
+ if (agp_bridge->mode & AGPSTAT_MODE_3_0)
agp_v3_parse_one(&requested_mode, &bridge_agpstat, &vga_agpstat);
else
agp_v2_parse_one(&requested_mode, &bridge_agpstat, &vga_agpstat);
@@ -732,7 +719,7 @@ void agp_generic_enable(struct agp_bridge_data *bridge, u32 requested_mode)
/* Do AGP version specific frobbing. */
if (bridge->major_version >= 3) {
- if (check_bridge_mode(bridge->dev)) {
+ if (bridge->mode & AGPSTAT_MODE_3_0) {
/* If we have 3.5, we can do the isoch stuff. */
if (bridge->minor_version >= 5)
agp_3_5_enable(bridge);
@@ -806,8 +793,7 @@ int agp_generic_create_gatt_table(struct agp_bridge_data *bridge)
break;
}
- table = (char *) __get_free_pages(GFP_KERNEL,
- page_order);
+ table = alloc_gatt_pages(page_order);
if (table == NULL) {
i++;
@@ -838,7 +824,7 @@ int agp_generic_create_gatt_table(struct agp_bridge_data *bridge)
size = ((struct aper_size_info_fixed *) temp)->size;
page_order = ((struct aper_size_info_fixed *) temp)->page_order;
num_entries = ((struct aper_size_info_fixed *) temp)->num_entries;
- table = (char *) __get_free_pages(GFP_KERNEL, page_order);
+ table = alloc_gatt_pages(page_order);
}
if (table == NULL)
@@ -853,7 +839,7 @@ int agp_generic_create_gatt_table(struct agp_bridge_data *bridge)
agp_gatt_table = (void *)table;
bridge->driver->cache_flush();
- bridge->gatt_table = ioremap_nocache(virt_to_phys(table),
+ bridge->gatt_table = ioremap_nocache(virt_to_gart(table),
(PAGE_SIZE * (1 << page_order)));
bridge->driver->cache_flush();
@@ -861,11 +847,11 @@ int agp_generic_create_gatt_table(struct agp_bridge_data *bridge)
for (page = virt_to_page(table); page <= virt_to_page(table_end); page++)
ClearPageReserved(page);
- free_pages((unsigned long) table, page_order);
+ free_gatt_pages(table, page_order);
return -ENOMEM;
}
- bridge->gatt_bus_addr = virt_to_phys(bridge->gatt_table_real);
+ bridge->gatt_bus_addr = virt_to_gart(bridge->gatt_table_real);
/* AK: bogus, should encode addresses > 4GB */
for (i = 0; i < num_entries; i++) {
@@ -919,7 +905,7 @@ int agp_generic_free_gatt_table(struct agp_bridge_data *bridge)
for (page = virt_to_page(table); page <= virt_to_page(table_end); page++)
ClearPageReserved(page);
- free_pages((unsigned long) bridge->gatt_table_real, page_order);
+ free_gatt_pages(bridge->gatt_table_real, page_order);
agp_gatt_table = NULL;
bridge->gatt_table = NULL;
diff --git a/drivers/char/agp/hp-agp.c b/drivers/char/agp/hp-agp.c
index 6052bfa04c7..99762b6c19a 100644
--- a/drivers/char/agp/hp-agp.c
+++ b/drivers/char/agp/hp-agp.c
@@ -110,7 +110,7 @@ static int __init hp_zx1_ioc_shared(void)
hp->gart_size = HP_ZX1_GART_SIZE;
hp->gatt_entries = hp->gart_size / hp->io_page_size;
- hp->io_pdir = phys_to_virt(readq(hp->ioc_regs+HP_ZX1_PDIR_BASE));
+ hp->io_pdir = gart_to_virt(readq(hp->ioc_regs+HP_ZX1_PDIR_BASE));
hp->gatt = &hp->io_pdir[HP_ZX1_IOVA_TO_PDIR(hp->gart_base)];
if (hp->gatt[0] != HP_ZX1_SBA_IOMMU_COOKIE) {
@@ -248,7 +248,7 @@ hp_zx1_configure (void)
agp_bridge->mode = readl(hp->lba_regs+hp->lba_cap_offset+PCI_AGP_STATUS);
if (hp->io_pdir_owner) {
- writel(virt_to_phys(hp->io_pdir), hp->ioc_regs+HP_ZX1_PDIR_BASE);
+ writel(virt_to_gart(hp->io_pdir), hp->ioc_regs+HP_ZX1_PDIR_BASE);
readl(hp->ioc_regs+HP_ZX1_PDIR_BASE);
writel(hp->io_tlb_ps, hp->ioc_regs+HP_ZX1_TCNFG);
readl(hp->ioc_regs+HP_ZX1_TCNFG);
diff --git a/drivers/char/agp/i460-agp.c b/drivers/char/agp/i460-agp.c
index adbea896c0d..94943298c03 100644
--- a/drivers/char/agp/i460-agp.c
+++ b/drivers/char/agp/i460-agp.c
@@ -372,7 +372,7 @@ static int i460_alloc_large_page (struct lp_desc *lp)
}
memset(lp->alloced_map, 0, map_size);
- lp->paddr = virt_to_phys(lpage);
+ lp->paddr = virt_to_gart(lpage);
lp->refcount = 0;
atomic_add(I460_KPAGES_PER_IOPAGE, &agp_bridge->current_memory_agp);
return 0;
@@ -383,7 +383,7 @@ static void i460_free_large_page (struct lp_desc *lp)
kfree(lp->alloced_map);
lp->alloced_map = NULL;
- free_pages((unsigned long) phys_to_virt(lp->paddr), I460_IO_PAGE_SHIFT - PAGE_SHIFT);
+ free_pages((unsigned long) gart_to_virt(lp->paddr), I460_IO_PAGE_SHIFT - PAGE_SHIFT);
atomic_sub(I460_KPAGES_PER_IOPAGE, &agp_bridge->current_memory_agp);
}
diff --git a/drivers/char/agp/intel-agp.c b/drivers/char/agp/intel-agp.c
index 8c7d727432b..51266d6b4d7 100644
--- a/drivers/char/agp/intel-agp.c
+++ b/drivers/char/agp/intel-agp.c
@@ -286,7 +286,7 @@ static struct agp_memory *alloc_agpphysmem_i8xx(size_t pg_count, int type)
if (new == NULL)
return NULL;
- new->memory[0] = virt_to_phys(addr);
+ new->memory[0] = virt_to_gart(addr);
if (pg_count == 4) {
/* kludge to get 4 physical pages for ARGB cursor */
new->memory[1] = new->memory[0] + PAGE_SIZE;
@@ -329,10 +329,10 @@ static void intel_i810_free_by_type(struct agp_memory *curr)
agp_free_key(curr->key);
if(curr->type == AGP_PHYS_MEMORY) {
if (curr->page_count == 4)
- i8xx_destroy_pages(phys_to_virt(curr->memory[0]));
+ i8xx_destroy_pages(gart_to_virt(curr->memory[0]));
else
agp_bridge->driver->agp_destroy_page(
- phys_to_virt(curr->memory[0]));
+ gart_to_virt(curr->memory[0]));
vfree(curr->memory);
}
kfree(curr);
@@ -418,7 +418,8 @@ static void intel_i830_init_gtt_entries(void)
case I915_GMCH_GMS_STOLEN_48M:
/* Check it's really I915G */
if (agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82915G_HB ||
- agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82915GM_HB)
+ agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82915GM_HB ||
+ agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82945G_HB)
gtt_entries = MB(48) - KB(size);
else
gtt_entries = 0;
@@ -426,7 +427,8 @@ static void intel_i830_init_gtt_entries(void)
case I915_GMCH_GMS_STOLEN_64M:
/* Check it's really I915G */
if (agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82915G_HB ||
- agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82915GM_HB)
+ agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82915GM_HB ||
+ agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82945G_HB)
gtt_entries = MB(64) - KB(size);
else
gtt_entries = 0;
@@ -1662,6 +1664,14 @@ static int __devinit agp_intel_probe(struct pci_dev *pdev,
}
name = "915GM";
break;
+ case PCI_DEVICE_ID_INTEL_82945G_HB:
+ if (find_i830(PCI_DEVICE_ID_INTEL_82945G_IG)) {
+ bridge->driver = &intel_915_driver;
+ } else {
+ bridge->driver = &intel_845_driver;
+ }
+ name = "945G";
+ break;
case PCI_DEVICE_ID_INTEL_7505_0:
bridge->driver = &intel_7505_driver;
name = "E7505";
@@ -1801,6 +1811,7 @@ static struct pci_device_id agp_intel_pci_table[] = {
ID(PCI_DEVICE_ID_INTEL_7205_0),
ID(PCI_DEVICE_ID_INTEL_82915G_HB),
ID(PCI_DEVICE_ID_INTEL_82915GM_HB),
+ ID(PCI_DEVICE_ID_INTEL_82945G_HB),
{ }
};
diff --git a/drivers/char/agp/sgi-agp.c b/drivers/char/agp/sgi-agp.c
index 4b3eda26797..d3aa159c9de 100644
--- a/drivers/char/agp/sgi-agp.c
+++ b/drivers/char/agp/sgi-agp.c
@@ -133,11 +133,14 @@ static int sgi_tioca_insert_memory(struct agp_memory *mem, off_t pg_start,
off_t j;
void *temp;
struct agp_bridge_data *bridge;
+ u64 *table;
bridge = mem->bridge;
if (!bridge)
return -EINVAL;
+ table = (u64 *)bridge->gatt_table;
+
temp = bridge->current_size;
switch (bridge->driver->size_type) {
@@ -175,7 +178,7 @@ static int sgi_tioca_insert_memory(struct agp_memory *mem, off_t pg_start,
j = pg_start;
while (j < (pg_start + mem->page_count)) {
- if (*(bridge->gatt_table + j))
+ if (table[j])
return -EBUSY;
j++;
}
@@ -186,7 +189,7 @@ static int sgi_tioca_insert_memory(struct agp_memory *mem, off_t pg_start,
}
for (i = 0, j = pg_start; i < mem->page_count; i++, j++) {
- *(bridge->gatt_table + j) =
+ table[j] =
bridge->driver->mask_memory(bridge, mem->memory[i],
mem->type);
}
@@ -200,6 +203,7 @@ static int sgi_tioca_remove_memory(struct agp_memory *mem, off_t pg_start,
{
size_t i;
struct agp_bridge_data *bridge;
+ u64 *table;
bridge = mem->bridge;
if (!bridge)
@@ -209,8 +213,10 @@ static int sgi_tioca_remove_memory(struct agp_memory *mem, off_t pg_start,
return -EINVAL;
}
+ table = (u64 *)bridge->gatt_table;
+
for (i = pg_start; i < (mem->page_count + pg_start); i++) {
- *(bridge->gatt_table + i) = 0;
+ table[i] = 0;
}
bridge->driver->tlb_flush(mem);
diff --git a/drivers/char/agp/sworks-agp.c b/drivers/char/agp/sworks-agp.c
index 10c23302dd8..a9fb12c20eb 100644
--- a/drivers/char/agp/sworks-agp.c
+++ b/drivers/char/agp/sworks-agp.c
@@ -51,7 +51,7 @@ static int serverworks_create_page_map(struct serverworks_page_map *page_map)
}
SetPageReserved(virt_to_page(page_map->real));
global_cache_flush();
- page_map->remapped = ioremap_nocache(virt_to_phys(page_map->real),
+ page_map->remapped = ioremap_nocache(virt_to_gart(page_map->real),
PAGE_SIZE);
if (page_map->remapped == NULL) {
ClearPageReserved(virt_to_page(page_map->real));
@@ -162,7 +162,7 @@ static int serverworks_create_gatt_table(struct agp_bridge_data *bridge)
/* Create a fake scratch directory */
for(i = 0; i < 1024; i++) {
writel(agp_bridge->scratch_page, serverworks_private.scratch_dir.remapped+i);
- writel(virt_to_phys(serverworks_private.scratch_dir.real) | 1, page_dir.remapped+i);
+ writel(virt_to_gart(serverworks_private.scratch_dir.real) | 1, page_dir.remapped+i);
}
retval = serverworks_create_gatt_pages(value->num_entries / 1024);
@@ -174,7 +174,7 @@ static int serverworks_create_gatt_table(struct agp_bridge_data *bridge)
agp_bridge->gatt_table_real = (u32 *)page_dir.real;
agp_bridge->gatt_table = (u32 __iomem *)page_dir.remapped;
- agp_bridge->gatt_bus_addr = virt_to_phys(page_dir.real);
+ agp_bridge->gatt_bus_addr = virt_to_gart(page_dir.real);
/* Get the address for the gart region.
* This is a bus address even on the alpha, b/c its
@@ -187,7 +187,7 @@ static int serverworks_create_gatt_table(struct agp_bridge_data *bridge)
/* Calculate the agp offset */
for(i = 0; i < value->num_entries / 1024; i++)
- writel(virt_to_phys(serverworks_private.gatt_pages[i]->real)|1, page_dir.remapped+i);
+ writel(virt_to_gart(serverworks_private.gatt_pages[i]->real)|1, page_dir.remapped+i);
return 0;
}
diff --git a/drivers/char/agp/uninorth-agp.c b/drivers/char/agp/uninorth-agp.c
index a673971f2a9..c8255312b8c 100644
--- a/drivers/char/agp/uninorth-agp.c
+++ b/drivers/char/agp/uninorth-agp.c
@@ -407,7 +407,7 @@ static int uninorth_create_gatt_table(struct agp_bridge_data *bridge)
bridge->gatt_table_real = (u32 *) table;
bridge->gatt_table = (u32 *)table;
- bridge->gatt_bus_addr = virt_to_phys(table);
+ bridge->gatt_bus_addr = virt_to_gart(table);
for (i = 0; i < num_entries; i++)
bridge->gatt_table[i] = 0;
diff --git a/drivers/char/mxser.c b/drivers/char/mxser.c
index 7a245068e3e..f022f094443 100644
--- a/drivers/char/mxser.c
+++ b/drivers/char/mxser.c
@@ -1995,9 +1995,6 @@ static void mxser_receive_chars(struct mxser_struct *info, int *status)
unsigned char ch, gdl;
int ignored = 0;
int cnt = 0;
- unsigned char *cp;
- char *fp;
- int count;
int recv_room;
int max = 256;
unsigned long flags;
@@ -2011,10 +2008,6 @@ static void mxser_receive_chars(struct mxser_struct *info, int *status)
//return;
}
- cp = tty->flip.char_buf;
- fp = tty->flip.flag_buf;
- count = 0;
-
// following add by Victor Yu. 09-02-2002
if (info->IsMoxaMustChipFlag != MOXA_OTHER_UART) {
@@ -2041,12 +2034,10 @@ static void mxser_receive_chars(struct mxser_struct *info, int *status)
}
while (gdl--) {
ch = inb(info->base + UART_RX);
- count++;
- *cp++ = ch;
- *fp++ = 0;
+ tty_insert_flip_char(tty, ch, 0);
cnt++;
/*
- if((count>=HI_WATER) && (info->stop_rx==0)){
+ if((cnt>=HI_WATER) && (info->stop_rx==0)){
mxser_stoprx(tty);
info->stop_rx=1;
break;
@@ -2061,7 +2052,7 @@ intr_old:
if (max-- < 0)
break;
/*
- if((count>=HI_WATER) && (info->stop_rx==0)){
+ if((cnt>=HI_WATER) && (info->stop_rx==0)){
mxser_stoprx(tty);
info->stop_rx=1;
break;
@@ -2078,36 +2069,33 @@ intr_old:
if (++ignored > 100)
break;
} else {
- count++;
+ char flag = 0;
if (*status & UART_LSR_SPECIAL) {
if (*status & UART_LSR_BI) {
- *fp++ = TTY_BREAK;
+ flag = TTY_BREAK;
/* added by casper 1/11/2000 */
info->icount.brk++;
-
/* */
if (info->flags & ASYNC_SAK)
do_SAK(tty);
} else if (*status & UART_LSR_PE) {
- *fp++ = TTY_PARITY;
+ flag = TTY_PARITY;
/* added by casper 1/11/2000 */
info->icount.parity++;
/* */
} else if (*status & UART_LSR_FE) {
- *fp++ = TTY_FRAME;
+ flag = TTY_FRAME;
/* added by casper 1/11/2000 */
info->icount.frame++;
/* */
} else if (*status & UART_LSR_OE) {
- *fp++ = TTY_OVERRUN;
+ flag = TTY_OVERRUN;
/* added by casper 1/11/2000 */
info->icount.overrun++;
/* */
- } else
- *fp++ = 0;
- } else
- *fp++ = 0;
- *cp++ = ch;
+ }
+ }
+ tty_insert_flip_char(tty, ch, flag);
cnt++;
if (cnt >= recv_room) {
if (!info->ldisc_stop_rx) {
@@ -2132,13 +2120,13 @@ intr_old:
// above add by Victor Yu. 09-02-2002
} while (*status & UART_LSR_DR);
- end_intr: // add by Victor Yu. 09-02-2002
+end_intr: // add by Victor Yu. 09-02-2002
mxvar_log.rxcnt[info->port] += cnt;
info->mon_data.rxcnt += cnt;
info->mon_data.up_rxcnt += cnt;
spin_unlock_irqrestore(&info->slock, flags);
-
+
tty_flip_buffer_push(tty);
}
diff --git a/drivers/input/keyboard/atkbd.c b/drivers/input/keyboard/atkbd.c
index af0446c6de8..48fdf1e517c 100644
--- a/drivers/input/keyboard/atkbd.c
+++ b/drivers/input/keyboard/atkbd.c
@@ -54,7 +54,7 @@ static int atkbd_softraw = 1;
module_param_named(softraw, atkbd_softraw, bool, 0);
MODULE_PARM_DESC(softraw, "Use software generated rawmode");
-static int atkbd_scroll = 1;
+static int atkbd_scroll = 0;
module_param_named(scroll, atkbd_scroll, bool, 0);
MODULE_PARM_DESC(scroll, "Enable scroll-wheel on MS Office and similar keyboards");
diff --git a/drivers/md/dm-mpath.c b/drivers/md/dm-mpath.c
index 1e97b3c12bd..0c1b8520ef8 100644
--- a/drivers/md/dm-mpath.c
+++ b/drivers/md/dm-mpath.c
@@ -985,6 +985,9 @@ static int do_end_io(struct multipath *m, struct bio *bio,
if (!error)
return 0; /* I/O complete */
+ if ((error == -EWOULDBLOCK) && bio_rw_ahead(bio))
+ return error;
+
spin_lock(&m->lock);
if (!m->nr_valid_paths) {
if (!m->queue_if_no_path || m->suspended) {
diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c
index fc9b5cd957a..a0b8848049c 100644
--- a/drivers/net/tg3.c
+++ b/drivers/net/tg3.c
@@ -7,7 +7,12 @@
* Copyright (C) 2005 Broadcom Corporation.
*
* Firmware is:
- * Copyright (C) 2000-2003 Broadcom Corporation.
+ * Derived from proprietary unpublished source code,
+ * Copyright (C) 2000-2003 Broadcom Corporation.
+ *
+ * Permission is hereby granted for the distribution of this firmware
+ * data in hexadecimal or equivalent format, provided this copyright
+ * notice is accompanying it.
*/
#include <linux/config.h>
@@ -61,8 +66,8 @@
#define DRV_MODULE_NAME "tg3"
#define PFX DRV_MODULE_NAME ": "
-#define DRV_MODULE_VERSION "3.29"
-#define DRV_MODULE_RELDATE "May 23, 2005"
+#define DRV_MODULE_VERSION "3.31"
+#define DRV_MODULE_RELDATE "June 8, 2005"
#define TG3_DEF_MAC_MODE 0
#define TG3_DEF_RX_MODE 0
@@ -8555,6 +8560,16 @@ static void __devinit tg3_get_eeprom_hw_cfg(struct tg3 *tp)
case NIC_SRAM_DATA_CFG_LED_MODE_MAC:
tp->led_ctrl = LED_CTRL_MODE_MAC;
+
+ /* Default to PHY_1_MODE if 0 (MAC_MODE) is
+ * read on some older 5700/5701 bootcode.
+ */
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) ==
+ ASIC_REV_5700 ||
+ GET_ASIC_REV(tp->pci_chip_rev_id) ==
+ ASIC_REV_5701)
+ tp->led_ctrl = LED_CTRL_MODE_PHY_1;
+
break;
case SHASTA_EXT_LED_SHARED:
@@ -9680,10 +9695,24 @@ static int __devinit tg3_test_dma(struct tg3 *tp)
}
if ((tp->dma_rwctrl & DMA_RWCTRL_WRITE_BNDRY_MASK) !=
DMA_RWCTRL_WRITE_BNDRY_16) {
+ static struct pci_device_id dma_wait_state_chipsets[] = {
+ { PCI_DEVICE(PCI_VENDOR_ID_APPLE,
+ PCI_DEVICE_ID_APPLE_UNI_N_PCI15) },
+ { },
+ };
+
/* DMA test passed without adjusting DMA boundary,
- * just restore the calculated DMA boundary
+ * now look for chipsets that are known to expose the
+ * DMA bug without failing the test.
*/
- tp->dma_rwctrl = saved_dma_rwctrl;
+ if (pci_dev_present(dma_wait_state_chipsets)) {
+ tp->dma_rwctrl &= ~DMA_RWCTRL_WRITE_BNDRY_MASK;
+ tp->dma_rwctrl |= DMA_RWCTRL_WRITE_BNDRY_16;
+ }
+ else
+ /* Safe to use the calculated DMA boundary. */
+ tp->dma_rwctrl = saved_dma_rwctrl;
+
tw32(TG3PCI_DMA_RW_CTRL, tp->dma_rwctrl);
}
diff --git a/drivers/pci/hotplug/cpci_hotplug_core.c b/drivers/pci/hotplug/cpci_hotplug_core.c
index 8132d946c38..30af105271a 100644
--- a/drivers/pci/hotplug/cpci_hotplug_core.c
+++ b/drivers/pci/hotplug/cpci_hotplug_core.c
@@ -217,6 +217,8 @@ static void release_slot(struct hotplug_slot *hotplug_slot)
kfree(slot->hotplug_slot->info);
kfree(slot->hotplug_slot->name);
kfree(slot->hotplug_slot);
+ if (slot->dev)
+ pci_dev_put(slot->dev);
kfree(slot);
}
diff --git a/drivers/pci/hotplug/cpci_hotplug_pci.c b/drivers/pci/hotplug/cpci_hotplug_pci.c
index c878028ad21..225b5e551dd 100644
--- a/drivers/pci/hotplug/cpci_hotplug_pci.c
+++ b/drivers/pci/hotplug/cpci_hotplug_pci.c
@@ -315,9 +315,12 @@ int cpci_unconfigure_slot(struct slot* slot)
PCI_DEVFN(PCI_SLOT(slot->devfn), i));
if (dev) {
pci_remove_bus_device(dev);
- slot->dev = NULL;
+ pci_dev_put(dev);
}
}
+ pci_dev_put(slot->dev);
+ slot->dev = NULL;
+
dbg("%s - exit", __FUNCTION__);
return 0;
}
diff --git a/drivers/pci/pci.ids b/drivers/pci/pci.ids
index 93481b41b61..1d2ef1e2ffc 100644
--- a/drivers/pci/pci.ids
+++ b/drivers/pci/pci.ids
@@ -7173,6 +7173,7 @@
080f Sentry5 DDR/SDR RAM Controller
0811 Sentry5 External Interface Core
0816 BCM3302 Sentry5 MIPS32 CPU
+ 1600 NetXtreme BCM5752 Gigabit Ethernet PCI Express
1644 NetXtreme BCM5700 Gigabit Ethernet
1014 0277 Broadcom Vigil B5700 1000Base-T
1028 00d1 Broadcom BCM5700
diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c
index 637e9493034..2194669300b 100644
--- a/drivers/pci/quirks.c
+++ b/drivers/pci/quirks.c
@@ -460,17 +460,6 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8131_APIC,
/*
- * Via 686A/B: The PCI_INTERRUPT_LINE register for the on-chip
- * devices, USB0/1, AC97, MC97, and ACPI, has an unusual feature:
- * when written, it makes an internal connection to the PIC.
- * For these devices, this register is defined to be 4 bits wide.
- * Normally this is fine. However for IO-APIC motherboards, or
- * non-x86 architectures (yes Via exists on PPC among other places),
- * we must mask the PCI_INTERRUPT_LINE value versus 0xf to get
- * interrupts delivered properly.
- */
-
-/*
* FIXME: it is questionable that quirk_via_acpi
* is needed. It shows up as an ISA bridge, and does not
* support the PCI_INTERRUPT_LINE register at all. Therefore
@@ -492,28 +481,30 @@ static void __devinit quirk_via_acpi(struct pci_dev *d)
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_3, quirk_via_acpi );
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686_4, quirk_via_acpi );
-static void quirk_via_irqpic(struct pci_dev *dev)
+/*
+ * Via 686A/B: The PCI_INTERRUPT_LINE register for the on-chip
+ * devices, USB0/1, AC97, MC97, and ACPI, has an unusual feature:
+ * when written, it makes an internal connection to the PIC.
+ * For these devices, this register is defined to be 4 bits wide.
+ * Normally this is fine. However for IO-APIC motherboards, or
+ * non-x86 architectures (yes Via exists on PPC among other places),
+ * we must mask the PCI_INTERRUPT_LINE value versus 0xf to get
+ * interrupts delivered properly.
+ */
+static void quirk_via_irq(struct pci_dev *dev)
{
u8 irq, new_irq;
-#ifdef CONFIG_X86_IO_APIC
- if (nr_ioapics && !skip_ioapic_setup)
- return;
-#endif
-#ifdef CONFIG_ACPI
- if (acpi_irq_model != ACPI_IRQ_MODEL_PIC)
- return;
-#endif
new_irq = dev->irq & 0xf;
pci_read_config_byte(dev, PCI_INTERRUPT_LINE, &irq);
if (new_irq != irq) {
- printk(KERN_INFO "PCI: Via PIC IRQ fixup for %s, from %d to %d\n",
+ printk(KERN_INFO "PCI: Via IRQ fixup for %s, from %d to %d\n",
pci_name(dev), irq, new_irq);
udelay(15); /* unknown if delay really needed */
pci_write_config_byte(dev, PCI_INTERRUPT_LINE, new_irq);
}
}
-DECLARE_PCI_FIXUP_ENABLE(PCI_VENDOR_ID_VIA, PCI_ANY_ID, quirk_via_irqpic);
+DECLARE_PCI_FIXUP_ENABLE(PCI_VENDOR_ID_VIA, PCI_ANY_ID, quirk_via_irq);
/*
* PIIX3 USB: We have to disable USB interrupts that are
diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c
index 21d194c6ace..9e58f134f68 100644
--- a/drivers/scsi/libata-core.c
+++ b/drivers/scsi/libata-core.c
@@ -2577,7 +2577,6 @@ static void __atapi_pio_bytes(struct ata_queued_cmd *qc, unsigned int bytes)
next_sg:
sg = &qc->sg[qc->cursg];
-next_page:
page = sg->page;
offset = sg->offset + qc->cursg_ofs;
@@ -2585,6 +2584,7 @@ next_page:
page = nth_page(page, (offset >> PAGE_SHIFT));
offset %= PAGE_SIZE;
+ /* don't overrun current sg */
count = min(sg->length - qc->cursg_ofs, bytes);
/* don't cross page boundaries */
@@ -2609,8 +2609,6 @@ next_page:
kunmap(page);
if (bytes) {
- if (qc->cursg_ofs < sg->length)
- goto next_page;
goto next_sg;
}
}
diff --git a/drivers/scsi/sata_sil.c b/drivers/scsi/sata_sil.c
index 238580d244e..49ed557a4b6 100644
--- a/drivers/scsi/sata_sil.c
+++ b/drivers/scsi/sata_sil.c
@@ -432,7 +432,13 @@ static int sil_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
writeb(cls, mmio_base + SIL_FIFO_R0);
writeb(cls, mmio_base + SIL_FIFO_W0);
writeb(cls, mmio_base + SIL_FIFO_R1);
- writeb(cls, mmio_base + SIL_FIFO_W2);
+ writeb(cls, mmio_base + SIL_FIFO_W1);
+ if (ent->driver_data == sil_3114) {
+ writeb(cls, mmio_base + SIL_FIFO_R2);
+ writeb(cls, mmio_base + SIL_FIFO_W2);
+ writeb(cls, mmio_base + SIL_FIFO_R3);
+ writeb(cls, mmio_base + SIL_FIFO_W3);
+ }
} else
printk(KERN_WARNING DRV_NAME "(%s): cache line size not set. Driver may not function\n",
pci_name(pdev));
diff --git a/drivers/serial/sa1100.c b/drivers/serial/sa1100.c
index 22565a67a57..98641c3f5ab 100644
--- a/drivers/serial/sa1100.c
+++ b/drivers/serial/sa1100.c
@@ -197,7 +197,7 @@ static void
sa1100_rx_chars(struct sa1100_port *sport, struct pt_regs *regs)
{
struct tty_struct *tty = sport->port.info->tty;
- unsigned int status, ch, flg, ignored = 0;
+ unsigned int status, ch, flg;
status = UTSR1_TO_SM(UART_GET_UTSR1(sport)) |
UTSR0_TO_SM(UART_GET_UTSR0(sport));
diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c
index 051c3a77b41..3bfcc7b9f86 100644
--- a/drivers/usb/serial/ftdi_sio.c
+++ b/drivers/usb/serial/ftdi_sio.c
@@ -264,7 +264,7 @@
/*
* Version Information
*/
-#define DRIVER_VERSION "v1.4.1"
+#define DRIVER_VERSION "v1.4.2"
#define DRIVER_AUTHOR "Greg Kroah-Hartman <greg@kroah.com>, Bill Ryder <bryder@sgi.com>, Kuba Ober <kuba@mareimbrium.org>"
#define DRIVER_DESC "USB FTDI Serial Converters Driver"
@@ -687,6 +687,8 @@ struct ftdi_private {
char prev_status, diff_status; /* Used for TIOCMIWAIT */
__u8 rx_flags; /* receive state flags (throttling) */
spinlock_t rx_lock; /* spinlock for receive state */
+ struct work_struct rx_work;
+ int rx_processed;
__u16 interface; /* FT2232C port interface (0 for FT232/245) */
@@ -717,7 +719,7 @@ static int ftdi_write_room (struct usb_serial_port *port);
static int ftdi_chars_in_buffer (struct usb_serial_port *port);
static void ftdi_write_bulk_callback (struct urb *urb, struct pt_regs *regs);
static void ftdi_read_bulk_callback (struct urb *urb, struct pt_regs *regs);
-static void ftdi_process_read (struct usb_serial_port *port);
+static void ftdi_process_read (void *param);
static void ftdi_set_termios (struct usb_serial_port *port, struct termios * old);
static int ftdi_tiocmget (struct usb_serial_port *port, struct file *file);
static int ftdi_tiocmset (struct usb_serial_port *port, struct file * file, unsigned int set, unsigned int clear);
@@ -1387,6 +1389,8 @@ static int ftdi_common_startup (struct usb_serial *serial)
port->read_urb->transfer_buffer_length = BUFSZ;
}
+ INIT_WORK(&priv->rx_work, ftdi_process_read, port);
+
/* Free port's existing write urb and transfer buffer. */
if (port->write_urb) {
usb_free_urb (port->write_urb);
@@ -1617,6 +1621,7 @@ static int ftdi_open (struct usb_serial_port *port, struct file *filp)
spin_unlock_irqrestore(&priv->rx_lock, flags);
/* Start reading from the device */
+ priv->rx_processed = 0;
usb_fill_bulk_urb(port->read_urb, dev,
usb_rcvbulkpipe(dev, port->bulk_in_endpointAddress),
port->read_urb->transfer_buffer, port->read_urb->transfer_buffer_length,
@@ -1667,6 +1672,10 @@ static void ftdi_close (struct usb_serial_port *port, struct file *filp)
err("Error from RTS LOW urb");
}
} /* Note change no line if hupcl is off */
+
+ /* cancel any scheduled reading */
+ cancel_delayed_work(&priv->rx_work);
+ flush_scheduled_work();
/* shutdown our bulk read */
if (port->read_urb)
@@ -1862,23 +1871,14 @@ static void ftdi_read_bulk_callback (struct urb *urb, struct pt_regs *regs)
return;
}
- /* If throttled, delay receive processing until unthrottled. */
- spin_lock(&priv->rx_lock);
- if (priv->rx_flags & THROTTLED) {
- dbg("Deferring read urb processing until unthrottled");
- priv->rx_flags |= ACTUALLY_THROTTLED;
- spin_unlock(&priv->rx_lock);
- return;
- }
- spin_unlock(&priv->rx_lock);
-
ftdi_process_read(port);
} /* ftdi_read_bulk_callback */
-static void ftdi_process_read (struct usb_serial_port *port)
+static void ftdi_process_read (void *param)
{ /* ftdi_process_read */
+ struct usb_serial_port *port = (struct usb_serial_port*)param;
struct urb *urb;
struct tty_struct *tty;
struct ftdi_private *priv;
@@ -1889,6 +1889,7 @@ static void ftdi_process_read (struct usb_serial_port *port)
int result;
int need_flip;
int packet_offset;
+ unsigned long flags;
dbg("%s - port %d", __FUNCTION__, port->number);
@@ -1915,12 +1916,18 @@ static void ftdi_process_read (struct usb_serial_port *port)
data = urb->transfer_buffer;
- /* The first two bytes of every read packet are status */
- if (urb->actual_length > 2) {
- usb_serial_debug_data(debug, &port->dev, __FUNCTION__, urb->actual_length, data);
+ if (priv->rx_processed) {
+ dbg("%s - already processed: %d bytes, %d remain", __FUNCTION__,
+ priv->rx_processed,
+ urb->actual_length - priv->rx_processed);
} else {
- dbg("Status only: %03oo %03oo",data[0],data[1]);
- }
+ /* The first two bytes of every read packet are status */
+ if (urb->actual_length > 2) {
+ usb_serial_debug_data(debug, &port->dev, __FUNCTION__, urb->actual_length, data);
+ } else {
+ dbg("Status only: %03oo %03oo",data[0],data[1]);
+ }
+ }
/* TO DO -- check for hung up line and handle appropriately: */
@@ -1929,8 +1936,12 @@ static void ftdi_process_read (struct usb_serial_port *port)
/* if CD is dropped and the line is not CLOCAL then we should hangup */
need_flip = 0;
- for (packet_offset=0; packet_offset < urb->actual_length; packet_offset += PKTSZ) {
+ for (packet_offset = priv->rx_processed; packet_offset < urb->actual_length; packet_offset += PKTSZ) {
+ int length;
+
/* Compare new line status to the old one, signal if different */
+ /* N.B. packet may be processed more than once, but differences
+ * are only processed once. */
if (priv != NULL) {
char new_status = data[packet_offset+0] & FTDI_STATUS_B0_MASK;
if (new_status != priv->prev_status) {
@@ -1940,6 +1951,35 @@ static void ftdi_process_read (struct usb_serial_port *port)
}
}
+ length = min(PKTSZ, urb->actual_length-packet_offset)-2;
+ if (length < 0) {
+ err("%s - bad packet length: %d", __FUNCTION__, length+2);
+ length = 0;
+ }
+
+ /* have to make sure we don't overflow the buffer
+ with tty_insert_flip_char's */
+ if (tty->flip.count+length > TTY_FLIPBUF_SIZE) {
+ tty_flip_buffer_push(tty);
+ need_flip = 0;
+
+ if (tty->flip.count != 0) {
+ /* flip didn't work, this happens when ftdi_process_read() is
+ * called from ftdi_unthrottle, because TTY_DONT_FLIP is set */
+ dbg("%s - flip buffer push failed", __FUNCTION__);
+ break;
+ }
+ }
+ if (priv->rx_flags & THROTTLED) {
+ dbg("%s - throttled", __FUNCTION__);
+ break;
+ }
+ if (tty->ldisc.receive_room(tty)-tty->flip.count < length) {
+ /* break out & wait for throttling/unthrottling to happen */
+ dbg("%s - receive room low", __FUNCTION__);
+ break;
+ }
+
/* Handle errors and break */
error_flag = TTY_NORMAL;
/* Although the device uses a bitmask and hence can have multiple */
@@ -1962,13 +2002,8 @@ static void ftdi_process_read (struct usb_serial_port *port)
error_flag = TTY_FRAME;
dbg("FRAMING error");
}
- if (urb->actual_length > packet_offset + 2) {
- for (i = 2; (i < PKTSZ) && ((i+packet_offset) < urb->actual_length); ++i) {
- /* have to make sure we don't overflow the buffer
- with tty_insert_flip_char's */
- if(tty->flip.count >= TTY_FLIPBUF_SIZE) {
- tty_flip_buffer_push(tty);
- }
+ if (length > 0) {
+ for (i = 2; i < length+2; i++) {
/* Note that the error flag is duplicated for
every character received since we don't know
which character it applied to */
@@ -2005,6 +2040,35 @@ static void ftdi_process_read (struct usb_serial_port *port)
tty_flip_buffer_push(tty);
}
+ if (packet_offset < urb->actual_length) {
+ /* not completely processed - record progress */
+ priv->rx_processed = packet_offset;
+ dbg("%s - incomplete, %d bytes processed, %d remain",
+ __FUNCTION__, packet_offset,
+ urb->actual_length - packet_offset);
+ /* check if we were throttled while processing */
+ spin_lock_irqsave(&priv->rx_lock, flags);
+ if (priv->rx_flags & THROTTLED) {
+ priv->rx_flags |= ACTUALLY_THROTTLED;
+ spin_unlock_irqrestore(&priv->rx_lock, flags);
+ dbg("%s - deferring remainder until unthrottled",
+ __FUNCTION__);
+ return;
+ }
+ spin_unlock_irqrestore(&priv->rx_lock, flags);
+ /* if the port is closed stop trying to read */
+ if (port->open_count > 0){
+ /* delay processing of remainder */
+ schedule_delayed_work(&priv->rx_work, 1);
+ } else {
+ dbg("%s - port is closed", __FUNCTION__);
+ }
+ return;
+ }
+
+ /* urb is completely processed */
+ priv->rx_processed = 0;
+
/* if the port is closed stop trying to read */
if (port->open_count > 0){
/* Continue trying to always read */
@@ -2444,7 +2508,7 @@ static void ftdi_unthrottle (struct usb_serial_port *port)
spin_unlock_irqrestore(&priv->rx_lock, flags);
if (actually_throttled)
- ftdi_process_read(port);
+ schedule_work(&priv->rx_work);
}
static int __init ftdi_init (void)