From eb5dd3b25fb54eb48fd604554cefaf83ab87d539 Mon Sep 17 00:00:00 2001 From: Andrew Chew Date: Wed, 4 Jan 2006 19:13:04 -0800 Subject: [PATCH] --- yaml --- r: 17110 b: refs/heads/master c: b887030aec0971a47ca97a18e93ff446bc7d049e h: refs/heads/master v: v3 --- [refs] | 2 +- trunk/Documentation/networking/bonding.txt | 2 + trunk/MAINTAINERS | 1 + trunk/block/elevator.c | 3 +- trunk/block/ll_rw_blk.c | 131 ++++------------ trunk/block/scsi_ioctl.c | 13 +- trunk/drivers/block/cciss.c | 72 ++++----- trunk/drivers/ide/ide-cd.c | 10 ++ trunk/drivers/ide/ide-io.c | 42 +----- trunk/drivers/ide/ide-probe.c | 2 - trunk/drivers/net/3c503.c | 16 +- trunk/drivers/net/Kconfig | 4 +- trunk/drivers/net/ac3200.c | 16 +- trunk/drivers/net/bonding/bonding.h | 8 +- trunk/drivers/net/e1000/e1000_param.c | 10 +- trunk/drivers/net/e2100.c | 14 +- trunk/drivers/net/es3210.c | 14 +- trunk/drivers/net/forcedeth.c | 164 ++++++++------------- trunk/drivers/net/gianfar.h | 4 +- trunk/drivers/net/hp-plus.c | 12 +- trunk/drivers/net/hp.c | 12 +- trunk/drivers/net/ibm_emac/ibm_emac.h | 3 +- trunk/drivers/net/ibm_emac/ibm_emac_core.c | 2 +- trunk/drivers/net/lance.c | 22 +-- trunk/drivers/net/lne390.c | 14 +- trunk/drivers/net/mv643xx_eth.c | 2 +- trunk/drivers/net/ne.c | 18 +-- trunk/drivers/net/ne2.c | 16 +- trunk/drivers/net/sk98lin/skge.c | 129 +++++++--------- trunk/drivers/net/smc-ultra.c | 24 +-- trunk/drivers/net/tulip/tulip_core.c | 2 +- trunk/drivers/net/wd.c | 14 +- trunk/drivers/net/wireless/ipw2100.c | 5 +- trunk/drivers/scsi/sata_nv.c | 30 +++- trunk/drivers/scsi/scsi.c | 109 +++++++++++++- trunk/drivers/scsi/scsi_lib.c | 36 ----- trunk/drivers/scsi/scsi_priv.h | 1 - trunk/fs/bio.c | 1 - trunk/include/linux/blkdev.h | 22 +-- trunk/include/linux/elevator.h | 2 + trunk/include/linux/ide.h | 1 - trunk/include/linux/interrupt.h | 2 +- trunk/include/linux/rcupdate.h | 31 +++- trunk/kernel/rcupdate.c | 30 ---- trunk/net/ieee80211/ieee80211_crypt_wep.c | 61 +++----- trunk/net/ieee80211/ieee80211_tx.c | 2 +- trunk/net/ieee80211/ieee80211_wx.c | 2 +- trunk/net/netlink/af_netlink.c | 2 +- 48 files changed, 491 insertions(+), 644 deletions(-) diff --git a/[refs] b/[refs] index 95816ff4ad2e..3bd5d5b2c3ab 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: cf10b2853f86e714eac7117484c0d368ce710fa4 +refs/heads/master: b887030aec0971a47ca97a18e93ff446bc7d049e diff --git a/trunk/Documentation/networking/bonding.txt b/trunk/Documentation/networking/bonding.txt index 8d8b4e5ea184..b0fe41da007b 100644 --- a/trunk/Documentation/networking/bonding.txt +++ b/trunk/Documentation/networking/bonding.txt @@ -945,6 +945,7 @@ bond0 Link encap:Ethernet HWaddr 00:C0:F0:1F:37:B4 collisions:0 txqueuelen:0 eth0 Link encap:Ethernet HWaddr 00:C0:F0:1F:37:B4 + inet addr:XXX.XXX.XXX.YYY Bcast:XXX.XXX.XXX.255 Mask:255.255.252.0 UP BROADCAST RUNNING SLAVE MULTICAST MTU:1500 Metric:1 RX packets:3573025 errors:0 dropped:0 overruns:0 frame:0 TX packets:1643167 errors:1 dropped:0 overruns:1 carrier:0 @@ -952,6 +953,7 @@ eth0 Link encap:Ethernet HWaddr 00:C0:F0:1F:37:B4 Interrupt:10 Base address:0x1080 eth1 Link encap:Ethernet HWaddr 00:C0:F0:1F:37:B4 + inet addr:XXX.XXX.XXX.YYY Bcast:XXX.XXX.XXX.255 Mask:255.255.252.0 UP BROADCAST RUNNING SLAVE MULTICAST MTU:1500 Metric:1 RX packets:3651769 errors:0 dropped:0 overruns:0 frame:0 TX packets:1643480 errors:0 dropped:0 overruns:0 carrier:0 diff --git a/trunk/MAINTAINERS b/trunk/MAINTAINERS index 270e28c0506a..76dc820bc889 100644 --- a/trunk/MAINTAINERS +++ b/trunk/MAINTAINERS @@ -1697,6 +1697,7 @@ S: Maintained MARVELL MV64340 ETHERNET DRIVER P: Manish Lachwani +M: Manish_Lachwani@pmc-sierra.com L: linux-mips@linux-mips.org L: netdev@vger.kernel.org S: Supported diff --git a/trunk/block/elevator.c b/trunk/block/elevator.c index 99a4d7b2f8ad..39dcccc82ada 100644 --- a/trunk/block/elevator.c +++ b/trunk/block/elevator.c @@ -64,7 +64,7 @@ inline int elv_rq_merge_ok(struct request *rq, struct bio *bio) } EXPORT_SYMBOL(elv_rq_merge_ok); -static inline int elv_try_merge(struct request *__rq, struct bio *bio) +inline int elv_try_merge(struct request *__rq, struct bio *bio) { int ret = ELEVATOR_NO_MERGE; @@ -80,6 +80,7 @@ static inline int elv_try_merge(struct request *__rq, struct bio *bio) return ret; } +EXPORT_SYMBOL(elv_try_merge); static struct elevator_type *elevator_find(const char *name) { diff --git a/trunk/block/ll_rw_blk.c b/trunk/block/ll_rw_blk.c index 8e27d0ab0d7c..91d3b4828c49 100644 --- a/trunk/block/ll_rw_blk.c +++ b/trunk/block/ll_rw_blk.c @@ -26,8 +26,7 @@ #include #include #include -#include -#include +#include /* * for max sense size @@ -63,15 +62,13 @@ static wait_queue_head_t congestion_wqh[2] = { /* * Controlling structure to kblockd */ -static struct workqueue_struct *kblockd_workqueue; +static struct workqueue_struct *kblockd_workqueue; unsigned long blk_max_low_pfn, blk_max_pfn; EXPORT_SYMBOL(blk_max_low_pfn); EXPORT_SYMBOL(blk_max_pfn); -static DEFINE_PER_CPU(struct list_head, blk_cpu_done); - /* Amount of time in which a process may batch requests */ #define BLK_BATCH_TIME (HZ/50UL) @@ -210,13 +207,6 @@ void blk_queue_merge_bvec(request_queue_t *q, merge_bvec_fn *mbfn) EXPORT_SYMBOL(blk_queue_merge_bvec); -void blk_queue_softirq_done(request_queue_t *q, softirq_done_fn *fn) -{ - q->softirq_done_fn = fn; -} - -EXPORT_SYMBOL(blk_queue_softirq_done); - /** * blk_queue_make_request - define an alternate make_request function for a device * @q: the request queue for the device to be affected @@ -280,7 +270,6 @@ EXPORT_SYMBOL(blk_queue_make_request); static inline void rq_init(request_queue_t *q, struct request *rq) { INIT_LIST_HEAD(&rq->queuelist); - INIT_LIST_HEAD(&rq->donelist); rq->errors = 0; rq->rq_status = RQ_ACTIVE; @@ -297,7 +286,6 @@ static inline void rq_init(request_queue_t *q, struct request *rq) rq->sense = NULL; rq->end_io = NULL; rq->end_io_data = NULL; - rq->completion_data = NULL; } /** @@ -2747,6 +2735,30 @@ static inline int attempt_front_merge(request_queue_t *q, struct request *rq) return 0; } +/** + * blk_attempt_remerge - attempt to remerge active head with next request + * @q: The &request_queue_t belonging to the device + * @rq: The head request (usually) + * + * Description: + * For head-active devices, the queue can easily be unplugged so quickly + * that proper merging is not done on the front request. This may hurt + * performance greatly for some devices. The block layer cannot safely + * do merging on that first request for these queues, but the driver can + * call this function and make it happen any way. Only the driver knows + * when it is safe to do so. + **/ +void blk_attempt_remerge(request_queue_t *q, struct request *rq) +{ + unsigned long flags; + + spin_lock_irqsave(q->queue_lock, flags); + attempt_back_merge(q, rq); + spin_unlock_irqrestore(q->queue_lock, flags); +} + +EXPORT_SYMBOL(blk_attempt_remerge); + static void init_request_from_bio(struct request *req, struct bio *bio) { req->flags |= REQ_CMD; @@ -3274,87 +3286,6 @@ int end_that_request_chunk(struct request *req, int uptodate, int nr_bytes) EXPORT_SYMBOL(end_that_request_chunk); -/* - * splice the completion data to a local structure and hand off to - * process_completion_queue() to complete the requests - */ -static void blk_done_softirq(struct softirq_action *h) -{ - struct list_head *cpu_list; - LIST_HEAD(local_list); - - local_irq_disable(); - cpu_list = &__get_cpu_var(blk_cpu_done); - list_splice_init(cpu_list, &local_list); - local_irq_enable(); - - while (!list_empty(&local_list)) { - struct request *rq = list_entry(local_list.next, struct request, donelist); - - list_del_init(&rq->donelist); - rq->q->softirq_done_fn(rq); - } -} - -#ifdef CONFIG_HOTPLUG_CPU - -static int blk_cpu_notify(struct notifier_block *self, unsigned long action, - void *hcpu) -{ - /* - * If a CPU goes away, splice its entries to the current CPU - * and trigger a run of the softirq - */ - if (action == CPU_DEAD) { - int cpu = (unsigned long) hcpu; - - local_irq_disable(); - list_splice_init(&per_cpu(blk_cpu_done, cpu), - &__get_cpu_var(blk_cpu_done)); - raise_softirq_irqoff(BLOCK_SOFTIRQ); - local_irq_enable(); - } - - return NOTIFY_OK; -} - - -static struct notifier_block __devinitdata blk_cpu_notifier = { - .notifier_call = blk_cpu_notify, -}; - -#endif /* CONFIG_HOTPLUG_CPU */ - -/** - * blk_complete_request - end I/O on a request - * @req: the request being processed - * - * Description: - * Ends all I/O on a request. It does not handle partial completions, - * unless the driver actually implements this in its completionc callback - * through requeueing. Theh actual completion happens out-of-order, - * through a softirq handler. The user must have registered a completion - * callback through blk_queue_softirq_done(). - **/ - -void blk_complete_request(struct request *req) -{ - struct list_head *cpu_list; - unsigned long flags; - - BUG_ON(!req->q->softirq_done_fn); - - local_irq_save(flags); - - cpu_list = &__get_cpu_var(blk_cpu_done); - list_add_tail(&req->donelist, cpu_list); - raise_softirq_irqoff(BLOCK_SOFTIRQ); - - local_irq_restore(flags); -} - -EXPORT_SYMBOL(blk_complete_request); - /* * queue lock must be held */ @@ -3433,8 +3364,6 @@ EXPORT_SYMBOL(kblockd_flush); int __init blk_dev_init(void) { - int i; - kblockd_workqueue = create_workqueue("kblockd"); if (!kblockd_workqueue) panic("Failed to create kblockd\n"); @@ -3448,14 +3377,6 @@ int __init blk_dev_init(void) iocontext_cachep = kmem_cache_create("blkdev_ioc", sizeof(struct io_context), 0, SLAB_PANIC, NULL, NULL); - for (i = 0; i < NR_CPUS; i++) - INIT_LIST_HEAD(&per_cpu(blk_cpu_done, i)); - - open_softirq(BLOCK_SOFTIRQ, blk_done_softirq, NULL); -#ifdef CONFIG_HOTPLUG_CPU - register_cpu_notifier(&blk_cpu_notifier); -#endif - blk_max_low_pfn = max_low_pfn; blk_max_pfn = max_pfn; diff --git a/trunk/block/scsi_ioctl.c b/trunk/block/scsi_ioctl.c index 18de84c8ccd8..c2ac36dfe4f3 100644 --- a/trunk/block/scsi_ioctl.c +++ b/trunk/block/scsi_ioctl.c @@ -190,21 +190,16 @@ static int verify_command(struct file *file, unsigned char *cmd) safe_for_write(GPCMD_SET_STREAMING), }; unsigned char type = cmd_type[cmd[0]]; - int has_write_perm = 0; /* Anybody who can open the device can do a read-safe command */ if (type & CMD_READ_SAFE) return 0; - /* - * file can be NULL from ioctl_by_bdev()... - */ - if (file) - has_write_perm = file->f_mode & FMODE_WRITE; - /* Write-safe commands just require a writable open.. */ - if ((type & CMD_WRITE_SAFE) && has_write_perm) - return 0; + if (type & CMD_WRITE_SAFE) { + if (file->f_mode & FMODE_WRITE) + return 0; + } /* And root can do any command.. */ if (capable(CAP_SYS_RAWIO)) diff --git a/trunk/drivers/block/cciss.c b/trunk/drivers/block/cciss.c index e4e9f255bd1f..88452c79fb64 100644 --- a/trunk/drivers/block/cciss.c +++ b/trunk/drivers/block/cciss.c @@ -2178,48 +2178,16 @@ static inline void resend_cciss_cmd( ctlr_info_t *h, CommandList_struct *c) start_io(h); } - -static void cciss_softirq_done(struct request *rq) -{ - CommandList_struct *cmd = rq->completion_data; - ctlr_info_t *h = hba[cmd->ctlr]; - u64bit temp64; - int i, ddir; - - if (cmd->Request.Type.Direction == XFER_READ) - ddir = PCI_DMA_FROMDEVICE; - else - ddir = PCI_DMA_TODEVICE; - - /* command did not need to be retried */ - /* unmap the DMA mapping for all the scatter gather elements */ - for(i=0; iHeader.SGList; i++) { - temp64.val32.lower = cmd->SG[i].Addr.lower; - temp64.val32.upper = cmd->SG[i].Addr.upper; - pci_unmap_page(h->pdev, temp64.val, cmd->SG[i].Len, ddir); - } - - complete_buffers(rq->bio, rq->errors); - -#ifdef CCISS_DEBUG - printk("Done with %p\n", rq); -#endif /* CCISS_DEBUG */ - - spin_lock_irq(&h->lock); - end_that_request_last(rq, rq->errors); - cmd_free(h, cmd,1); - spin_unlock_irq(&h->lock); -} - /* checks the status of the job and calls complete buffers to mark all - * buffers for the completed job. Note that this function does not need - * to hold the hba/queue lock. + * buffers for the completed job. */ static inline void complete_command( ctlr_info_t *h, CommandList_struct *cmd, int timeout) { int status = 1; + int i; int retry_cmd = 0; + u64bit temp64; if (timeout) status = 0; @@ -2327,10 +2295,24 @@ static inline void complete_command( ctlr_info_t *h, CommandList_struct *cmd, resend_cciss_cmd(h,cmd); return; } + /* command did not need to be retried */ + /* unmap the DMA mapping for all the scatter gather elements */ + for(i=0; iHeader.SGList; i++) { + temp64.val32.lower = cmd->SG[i].Addr.lower; + temp64.val32.upper = cmd->SG[i].Addr.upper; + pci_unmap_page(hba[cmd->ctlr]->pdev, + temp64.val, cmd->SG[i].Len, + (cmd->Request.Type.Direction == XFER_READ) ? + PCI_DMA_FROMDEVICE : PCI_DMA_TODEVICE); + } + complete_buffers(cmd->rq->bio, status); + +#ifdef CCISS_DEBUG + printk("Done with %p\n", cmd->rq); +#endif /* CCISS_DEBUG */ - cmd->rq->completion_data = cmd; - cmd->rq->errors = status; - blk_complete_request(cmd->rq); + end_that_request_last(cmd->rq, status ? 1 : -EIO); + cmd_free(h,cmd,1); } /* @@ -3217,17 +3199,15 @@ static int __devinit cciss_init_one(struct pci_dev *pdev, drv->queue = q; q->backing_dev_info.ra_pages = READ_AHEAD; - blk_queue_bounce_limit(q, hba[i]->pdev->dma_mask); - - /* This is a hardware imposed limit. */ - blk_queue_max_hw_segments(q, MAXSGENTRIES); + blk_queue_bounce_limit(q, hba[i]->pdev->dma_mask); - /* This is a limit in the driver and could be eliminated. */ - blk_queue_max_phys_segments(q, MAXSGENTRIES); + /* This is a hardware imposed limit. */ + blk_queue_max_hw_segments(q, MAXSGENTRIES); - blk_queue_max_sectors(q, 512); + /* This is a limit in the driver and could be eliminated. */ + blk_queue_max_phys_segments(q, MAXSGENTRIES); - blk_queue_softirq_done(q, cciss_softirq_done); + blk_queue_max_sectors(q, 512); q->queuedata = hba[i]; sprintf(disk->disk_name, "cciss/c%dd%d", i, j); diff --git a/trunk/drivers/ide/ide-cd.c b/trunk/drivers/ide/ide-cd.c index e4d55ad32d2f..d31117eb95aa 100644 --- a/trunk/drivers/ide/ide-cd.c +++ b/trunk/drivers/ide/ide-cd.c @@ -1332,6 +1332,8 @@ static ide_startstop_t cdrom_start_read (ide_drive_t *drive, unsigned int block) if (cdrom_read_from_buffer(drive)) return ide_stopped; + blk_attempt_remerge(drive->queue, rq); + /* Clear the local sector buffer. */ info->nsectors_buffered = 0; @@ -1872,6 +1874,14 @@ static ide_startstop_t cdrom_start_write(ide_drive_t *drive, struct request *rq) return ide_stopped; } + /* + * for dvd-ram and such media, it's a really big deal to get + * big writes all the time. so scour the queue and attempt to + * remerge requests, often the plugging will not have had time + * to do this properly + */ + blk_attempt_remerge(drive->queue, rq); + info->nsectors_buffered = 0; /* use dma, if possible. we don't need to check more, since we diff --git a/trunk/drivers/ide/ide-io.c b/trunk/drivers/ide/ide-io.c index dea2d4dcc698..b5dc6df8e67d 100644 --- a/trunk/drivers/ide/ide-io.c +++ b/trunk/drivers/ide/ide-io.c @@ -55,22 +55,9 @@ #include #include -void ide_softirq_done(struct request *rq) -{ - request_queue_t *q = rq->q; - - add_disk_randomness(rq->rq_disk); - end_that_request_chunk(rq, rq->errors, rq->data_len); - - spin_lock_irq(q->queue_lock); - end_that_request_last(rq, rq->errors); - spin_unlock_irq(q->queue_lock); -} - int __ide_end_request(ide_drive_t *drive, struct request *rq, int uptodate, int nr_sectors) { - unsigned int nbytes; int ret = 1; BUG_ON(!(rq->flags & REQ_STARTED)); @@ -94,28 +81,17 @@ int __ide_end_request(ide_drive_t *drive, struct request *rq, int uptodate, HWGROUP(drive)->hwif->ide_dma_on(drive); } - /* - * For partial completions (or non fs/pc requests), use the regular - * direct completion path. - */ - nbytes = nr_sectors << 9; - if (rq_all_done(rq, nbytes)) { - rq->errors = uptodate; - rq->data_len = nbytes; + if (!end_that_request_first(rq, uptodate, nr_sectors)) { + add_disk_randomness(rq->rq_disk); + + if (blk_rq_tagged(rq)) + blk_queue_end_tag(drive->queue, rq); + blkdev_dequeue_request(rq); HWGROUP(drive)->rq = NULL; - blk_complete_request(rq); + end_that_request_last(rq, uptodate); ret = 0; - } else { - if (!end_that_request_first(rq, uptodate, nr_sectors)) { - add_disk_randomness(rq->rq_disk); - blkdev_dequeue_request(rq); - HWGROUP(drive)->rq = NULL; - end_that_request_last(rq, uptodate); - ret = 0; - } } - return ret; } EXPORT_SYMBOL(__ide_end_request); @@ -137,10 +113,6 @@ int ide_end_request (ide_drive_t *drive, int uptodate, int nr_sectors) unsigned long flags; int ret = 1; - /* - * room for locking improvements here, the calls below don't - * need the queue lock held at all - */ spin_lock_irqsave(&ide_lock, flags); rq = HWGROUP(drive)->rq; diff --git a/trunk/drivers/ide/ide-probe.c b/trunk/drivers/ide/ide-probe.c index 1ddaa71a8f45..02167a5b751d 100644 --- a/trunk/drivers/ide/ide-probe.c +++ b/trunk/drivers/ide/ide-probe.c @@ -1011,8 +1011,6 @@ static int ide_init_queue(ide_drive_t *drive) blk_queue_max_hw_segments(q, max_sg_entries); blk_queue_max_phys_segments(q, max_sg_entries); - blk_queue_softirq_done(q, ide_softirq_done); - /* assign drive queue */ drive->queue = q; diff --git a/trunk/drivers/net/3c503.c b/trunk/drivers/net/3c503.c index dcc98afa65d7..5c5eebdb6914 100644 --- a/trunk/drivers/net/3c503.c +++ b/trunk/drivers/net/3c503.c @@ -148,6 +148,14 @@ el2_pio_probe(struct net_device *dev) return -ENODEV; } +static void cleanup_card(struct net_device *dev) +{ + /* NB: el2_close() handles free_irq */ + release_region(dev->base_addr, EL2_IO_EXTENT); + if (ei_status.mem) + iounmap(ei_status.mem); +} + #ifndef MODULE struct net_device * __init el2_probe(int unit) { @@ -718,14 +726,6 @@ init_module(void) return -ENXIO; } -static void cleanup_card(struct net_device *dev) -{ - /* NB: el2_close() handles free_irq */ - release_region(dev->base_addr, EL2_IO_EXTENT); - if (ei_status.mem) - iounmap(ei_status.mem); -} - void cleanup_module(void) { diff --git a/trunk/drivers/net/Kconfig b/trunk/drivers/net/Kconfig index 733bc25b2bf9..1960961bf28e 100644 --- a/trunk/drivers/net/Kconfig +++ b/trunk/drivers/net/Kconfig @@ -129,7 +129,7 @@ config NET_SB1000 If you don't have this card, of course say N. -source "drivers/net/arcnet/Kconfig" + source "drivers/net/arcnet/Kconfig" source "drivers/net/phy/Kconfig" @@ -844,7 +844,7 @@ config SMC9194 config DM9000 tristate "DM9000 support" - depends on (ARM || MIPS) && NET_ETHERNET + depends on ARM && NET_ETHERNET select CRC32 select MII ---help--- diff --git a/trunk/drivers/net/ac3200.c b/trunk/drivers/net/ac3200.c index 7952dc6d77e3..8a0af5453e21 100644 --- a/trunk/drivers/net/ac3200.c +++ b/trunk/drivers/net/ac3200.c @@ -123,6 +123,14 @@ static int __init do_ac3200_probe(struct net_device *dev) return -ENODEV; } +static void cleanup_card(struct net_device *dev) +{ + /* Someday free_irq may be in ac_close_card() */ + free_irq(dev->irq, dev); + release_region(dev->base_addr, AC_IO_EXTENT); + iounmap(ei_status.mem); +} + #ifndef MODULE struct net_device * __init ac3200_probe(int unit) { @@ -398,14 +406,6 @@ init_module(void) return -ENXIO; } -static void cleanup_card(struct net_device *dev) -{ - /* Someday free_irq may be in ac_close_card() */ - free_irq(dev->irq, dev); - release_region(dev->base_addr, AC_IO_EXTENT); - iounmap(ei_status.mem); -} - void cleanup_module(void) { diff --git a/trunk/drivers/net/bonding/bonding.h b/trunk/drivers/net/bonding/bonding.h index f20bb85c1ea5..015c7f1d1bc0 100644 --- a/trunk/drivers/net/bonding/bonding.h +++ b/trunk/drivers/net/bonding/bonding.h @@ -205,7 +205,7 @@ struct bonding { * * Caller must hold bond lock for read */ -static inline struct slave *bond_get_slave_by_dev(struct bonding *bond, struct net_device *slave_dev) +extern inline struct slave *bond_get_slave_by_dev(struct bonding *bond, struct net_device *slave_dev) { struct slave *slave = NULL; int i; @@ -219,7 +219,7 @@ static inline struct slave *bond_get_slave_by_dev(struct bonding *bond, struct n return slave; } -static inline struct bonding *bond_get_bond_by_slave(struct slave *slave) +extern inline struct bonding *bond_get_bond_by_slave(struct slave *slave) { if (!slave || !slave->dev->master) { return NULL; @@ -228,13 +228,13 @@ static inline struct bonding *bond_get_bond_by_slave(struct slave *slave) return (struct bonding *)slave->dev->master->priv; } -static inline void bond_set_slave_inactive_flags(struct slave *slave) +extern inline void bond_set_slave_inactive_flags(struct slave *slave) { slave->state = BOND_STATE_BACKUP; slave->dev->flags |= IFF_NOARP; } -static inline void bond_set_slave_active_flags(struct slave *slave) +extern inline void bond_set_slave_active_flags(struct slave *slave) { slave->state = BOND_STATE_ACTIVE; slave->dev->flags &= ~IFF_NOARP; diff --git a/trunk/drivers/net/e1000/e1000_param.c b/trunk/drivers/net/e1000/e1000_param.c index ccbbe5ad8e0f..38695d5b4637 100644 --- a/trunk/drivers/net/e1000/e1000_param.c +++ b/trunk/drivers/net/e1000/e1000_param.c @@ -545,7 +545,7 @@ e1000_check_fiber_options(struct e1000_adapter *adapter) static void __devinit e1000_check_copper_options(struct e1000_adapter *adapter) { - int speed, dplx, an; + int speed, dplx; int bd = adapter->bd_number; { /* Speed */ @@ -641,12 +641,8 @@ e1000_check_copper_options(struct e1000_adapter *adapter) .p = an_list }} }; - if (num_AutoNeg > bd) { - an = AutoNeg[bd]; - e1000_validate_option(&an, &opt, adapter); - } else { - an = opt.def; - } + int an = AutoNeg[bd]; + e1000_validate_option(&an, &opt, adapter); adapter->hw.autoneg_advertised = an; } diff --git a/trunk/drivers/net/e2100.c b/trunk/drivers/net/e2100.c index e5c5cd2a2712..f5a4dd7d8564 100644 --- a/trunk/drivers/net/e2100.c +++ b/trunk/drivers/net/e2100.c @@ -140,6 +140,13 @@ static int __init do_e2100_probe(struct net_device *dev) return -ENODEV; } +static void cleanup_card(struct net_device *dev) +{ + /* NB: e21_close() handles free_irq */ + iounmap(ei_status.mem); + release_region(dev->base_addr, E21_IO_EXTENT); +} + #ifndef MODULE struct net_device * __init e2100_probe(int unit) { @@ -456,13 +463,6 @@ init_module(void) return -ENXIO; } -static void cleanup_card(struct net_device *dev) -{ - /* NB: e21_close() handles free_irq */ - iounmap(ei_status.mem); - release_region(dev->base_addr, E21_IO_EXTENT); -} - void cleanup_module(void) { diff --git a/trunk/drivers/net/es3210.c b/trunk/drivers/net/es3210.c index 6b0ab1eac3fb..50f8e23bb9e5 100644 --- a/trunk/drivers/net/es3210.c +++ b/trunk/drivers/net/es3210.c @@ -155,6 +155,13 @@ static int __init do_es_probe(struct net_device *dev) return -ENODEV; } +static void cleanup_card(struct net_device *dev) +{ + free_irq(dev->irq, dev); + release_region(dev->base_addr, ES_IO_EXTENT); + iounmap(ei_status.mem); +} + #ifndef MODULE struct net_device * __init es_probe(int unit) { @@ -449,13 +456,6 @@ init_module(void) return -ENXIO; } -static void cleanup_card(struct net_device *dev) -{ - free_irq(dev->irq, dev); - release_region(dev->base_addr, ES_IO_EXTENT); - iounmap(ei_status.mem); -} - void cleanup_module(void) { diff --git a/trunk/drivers/net/forcedeth.c b/trunk/drivers/net/forcedeth.c index 3682ec61e8a8..c39344adecce 100644 --- a/trunk/drivers/net/forcedeth.c +++ b/trunk/drivers/net/forcedeth.c @@ -101,7 +101,6 @@ * 0.46: 20 Oct 2005: Add irq optimization modes. * 0.47: 26 Oct 2005: Add phyaddr 0 in phy scan. * 0.48: 24 Dec 2005: Disable TSO, bugfix for pci_map_single - * 0.49: 10 Dec 2005: Fix tso for large buffers. * * Known bugs: * We suspect that on some hardware no TX done interrupts are generated. @@ -113,7 +112,7 @@ * DEV_NEED_TIMERIRQ will not harm you on sane hardware, only generating a few * superfluous timer interrupts from the nic. */ -#define FORCEDETH_VERSION "0.49" +#define FORCEDETH_VERSION "0.48" #define DRV_NAME "forcedeth" #include @@ -350,8 +349,6 @@ typedef union _ring_type { #define NV_TX2_VALID (1<<31) #define NV_TX2_TSO (1<<28) #define NV_TX2_TSO_SHIFT 14 -#define NV_TX2_TSO_MAX_SHIFT 14 -#define NV_TX2_TSO_MAX_SIZE (1<tx_ring.ex[i].FlagLen = 0; np->tx_skbuff[i] = NULL; - np->tx_dma[i] = 0; } } @@ -950,27 +945,30 @@ static int nv_init_ring(struct net_device *dev) return nv_alloc_rx(dev); } -static int nv_release_txskb(struct net_device *dev, unsigned int skbnr) +static void nv_release_txskb(struct net_device *dev, unsigned int skbnr) { struct fe_priv *np = netdev_priv(dev); - - dprintk(KERN_INFO "%s: nv_release_txskb for skbnr %d\n", - dev->name, skbnr); - - if (np->tx_dma[skbnr]) { - pci_unmap_page(np->pci_dev, np->tx_dma[skbnr], - np->tx_dma_len[skbnr], - PCI_DMA_TODEVICE); - np->tx_dma[skbnr] = 0; - } - - if (np->tx_skbuff[skbnr]) { - dev_kfree_skb_irq(np->tx_skbuff[skbnr]); - np->tx_skbuff[skbnr] = NULL; - return 1; - } else { - return 0; + struct sk_buff *skb = np->tx_skbuff[skbnr]; + unsigned int j, entry, fragments; + + dprintk(KERN_INFO "%s: nv_release_txskb for skbnr %d, skb %p\n", + dev->name, skbnr, np->tx_skbuff[skbnr]); + + entry = skbnr; + if ((fragments = skb_shinfo(skb)->nr_frags) != 0) { + for (j = fragments; j >= 1; j--) { + skb_frag_t *frag = &skb_shinfo(skb)->frags[j-1]; + pci_unmap_page(np->pci_dev, np->tx_dma[entry], + frag->size, + PCI_DMA_TODEVICE); + entry = (entry - 1) % TX_RING; + } } + pci_unmap_single(np->pci_dev, np->tx_dma[entry], + skb->len - skb->data_len, + PCI_DMA_TODEVICE); + dev_kfree_skb_irq(skb); + np->tx_skbuff[skbnr] = NULL; } static void nv_drain_tx(struct net_device *dev) @@ -983,8 +981,10 @@ static void nv_drain_tx(struct net_device *dev) np->tx_ring.orig[i].FlagLen = 0; else np->tx_ring.ex[i].FlagLen = 0; - if (nv_release_txskb(dev, i)) + if (np->tx_skbuff[i]) { + nv_release_txskb(dev, i); np->stats.tx_dropped++; + } } } @@ -1021,105 +1021,68 @@ static void drain_ring(struct net_device *dev) static int nv_start_xmit(struct sk_buff *skb, struct net_device *dev) { struct fe_priv *np = netdev_priv(dev); - u32 tx_flags = 0; u32 tx_flags_extra = (np->desc_ver == DESC_VER_1 ? NV_TX_LASTPACKET : NV_TX2_LASTPACKET); unsigned int fragments = skb_shinfo(skb)->nr_frags; - unsigned int nr = (np->next_tx - 1) % TX_RING; - unsigned int start_nr = np->next_tx % TX_RING; + unsigned int nr = (np->next_tx + fragments) % TX_RING; unsigned int i; - u32 offset = 0; - u32 bcnt; - u32 size = skb->len-skb->data_len; - u32 entries = (size >> NV_TX2_TSO_MAX_SHIFT) + ((size & (NV_TX2_TSO_MAX_SIZE-1)) ? 1 : 0); - - /* add fragments to entries count */ - for (i = 0; i < fragments; i++) { - entries += (skb_shinfo(skb)->frags[i].size >> NV_TX2_TSO_MAX_SHIFT) + - ((skb_shinfo(skb)->frags[i].size & (NV_TX2_TSO_MAX_SIZE-1)) ? 1 : 0); - } spin_lock_irq(&np->lock); - if ((np->next_tx - np->nic_tx + entries - 1) > TX_LIMIT_STOP) { + if ((np->next_tx - np->nic_tx + fragments) > TX_LIMIT_STOP) { spin_unlock_irq(&np->lock); netif_stop_queue(dev); return NETDEV_TX_BUSY; } - /* setup the header buffer */ - do { - bcnt = (size > NV_TX2_TSO_MAX_SIZE) ? NV_TX2_TSO_MAX_SIZE : size; - nr = (nr + 1) % TX_RING; - - np->tx_dma[nr] = pci_map_single(np->pci_dev, skb->data + offset, bcnt, - PCI_DMA_TODEVICE); - np->tx_dma_len[nr] = bcnt; - - if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2) { - np->tx_ring.orig[nr].PacketBuffer = cpu_to_le32(np->tx_dma[nr]); - np->tx_ring.orig[nr].FlagLen = cpu_to_le32((bcnt-1) | tx_flags); - } else { - np->tx_ring.ex[nr].PacketBufferHigh = cpu_to_le64(np->tx_dma[nr]) >> 32; - np->tx_ring.ex[nr].PacketBufferLow = cpu_to_le64(np->tx_dma[nr]) & 0x0FFFFFFFF; - np->tx_ring.ex[nr].FlagLen = cpu_to_le32((bcnt-1) | tx_flags); - } - tx_flags = np->tx_flags; - offset += bcnt; - size -= bcnt; - } while(size); - - /* setup the fragments */ - for (i = 0; i < fragments; i++) { - skb_frag_t *frag = &skb_shinfo(skb)->frags[i]; - u32 size = frag->size; - offset = 0; - - do { - bcnt = (size > NV_TX2_TSO_MAX_SIZE) ? NV_TX2_TSO_MAX_SIZE : size; - nr = (nr + 1) % TX_RING; - - np->tx_dma[nr] = pci_map_page(np->pci_dev, frag->page, frag->page_offset+offset, bcnt, - PCI_DMA_TODEVICE); - np->tx_dma_len[nr] = bcnt; + np->tx_skbuff[nr] = skb; + + if (fragments) { + dprintk(KERN_DEBUG "%s: nv_start_xmit: buffer contains %d fragments\n", dev->name, fragments); + /* setup descriptors in reverse order */ + for (i = fragments; i >= 1; i--) { + skb_frag_t *frag = &skb_shinfo(skb)->frags[i-1]; + np->tx_dma[nr] = pci_map_page(np->pci_dev, frag->page, frag->page_offset, frag->size, + PCI_DMA_TODEVICE); if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2) { np->tx_ring.orig[nr].PacketBuffer = cpu_to_le32(np->tx_dma[nr]); - np->tx_ring.orig[nr].FlagLen = cpu_to_le32((bcnt-1) | tx_flags); + np->tx_ring.orig[nr].FlagLen = cpu_to_le32( (frag->size-1) | np->tx_flags | tx_flags_extra); } else { np->tx_ring.ex[nr].PacketBufferHigh = cpu_to_le64(np->tx_dma[nr]) >> 32; np->tx_ring.ex[nr].PacketBufferLow = cpu_to_le64(np->tx_dma[nr]) & 0x0FFFFFFFF; - np->tx_ring.ex[nr].FlagLen = cpu_to_le32((bcnt-1) | tx_flags); + np->tx_ring.ex[nr].FlagLen = cpu_to_le32( (frag->size-1) | np->tx_flags | tx_flags_extra); } - offset += bcnt; - size -= bcnt; - } while (size); - } + + nr = (nr - 1) % TX_RING; - /* set last fragment flag */ - if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2) { - np->tx_ring.orig[nr].FlagLen |= cpu_to_le32(tx_flags_extra); - } else { - np->tx_ring.ex[nr].FlagLen |= cpu_to_le32(tx_flags_extra); + if (np->desc_ver == DESC_VER_1) + tx_flags_extra &= ~NV_TX_LASTPACKET; + else + tx_flags_extra &= ~NV_TX2_LASTPACKET; + } } - np->tx_skbuff[nr] = skb; - #ifdef NETIF_F_TSO if (skb_shinfo(skb)->tso_size) - tx_flags_extra = NV_TX2_TSO | (skb_shinfo(skb)->tso_size << NV_TX2_TSO_SHIFT); + tx_flags_extra |= NV_TX2_TSO | (skb_shinfo(skb)->tso_size << NV_TX2_TSO_SHIFT); else #endif - tx_flags_extra = (skb->ip_summed == CHECKSUM_HW ? (NV_TX2_CHECKSUM_L3|NV_TX2_CHECKSUM_L4) : 0); + tx_flags_extra |= (skb->ip_summed == CHECKSUM_HW ? (NV_TX2_CHECKSUM_L3|NV_TX2_CHECKSUM_L4) : 0); - /* set tx flags */ + np->tx_dma[nr] = pci_map_single(np->pci_dev, skb->data, skb->len-skb->data_len, + PCI_DMA_TODEVICE); + if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2) { - np->tx_ring.orig[start_nr].FlagLen |= cpu_to_le32(tx_flags | tx_flags_extra); + np->tx_ring.orig[nr].PacketBuffer = cpu_to_le32(np->tx_dma[nr]); + np->tx_ring.orig[nr].FlagLen = cpu_to_le32( (skb->len-skb->data_len-1) | np->tx_flags | tx_flags_extra); } else { - np->tx_ring.ex[start_nr].FlagLen |= cpu_to_le32(tx_flags | tx_flags_extra); + np->tx_ring.ex[nr].PacketBufferHigh = cpu_to_le64(np->tx_dma[nr]) >> 32; + np->tx_ring.ex[nr].PacketBufferLow = cpu_to_le64(np->tx_dma[nr]) & 0x0FFFFFFFF; + np->tx_ring.ex[nr].FlagLen = cpu_to_le32( (skb->len-skb->data_len-1) | np->tx_flags | tx_flags_extra); } - dprintk(KERN_DEBUG "%s: nv_start_xmit: packet %d (entries %d) queued for transmission. tx_flags_extra: %x\n", - dev->name, np->next_tx, entries, tx_flags_extra); + dprintk(KERN_DEBUG "%s: nv_start_xmit: packet packet %d queued for transmission. tx_flags_extra: %x\n", + dev->name, np->next_tx, tx_flags_extra); { int j; for (j=0; j<64; j++) { @@ -1130,7 +1093,7 @@ static int nv_start_xmit(struct sk_buff *skb, struct net_device *dev) dprintk("\n"); } - np->next_tx += entries; + np->next_tx += 1 + fragments; dev->trans_start = jiffies; spin_unlock_irq(&np->lock); @@ -1177,6 +1140,7 @@ static void nv_tx_done(struct net_device *dev) np->stats.tx_packets++; np->stats.tx_bytes += skb->len; } + nv_release_txskb(dev, i); } } else { if (Flags & NV_TX2_LASTPACKET) { @@ -1192,9 +1156,9 @@ static void nv_tx_done(struct net_device *dev) np->stats.tx_packets++; np->stats.tx_bytes += skb->len; } + nv_release_txskb(dev, i); } } - nv_release_txskb(dev, i); np->nic_tx++; } if (np->next_tx - np->nic_tx < TX_LIMIT_START) @@ -2492,7 +2456,7 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i np->txrxctl_bits |= NVREG_TXRXCTL_RXCHECK; dev->features |= NETIF_F_HW_CSUM | NETIF_F_SG; #ifdef NETIF_F_TSO - dev->features |= NETIF_F_TSO; + /* disabled dev->features |= NETIF_F_TSO; */ #endif } diff --git a/trunk/drivers/net/gianfar.h b/trunk/drivers/net/gianfar.h index cb9d66ac3ab9..94a91da84fbb 100644 --- a/trunk/drivers/net/gianfar.h +++ b/trunk/drivers/net/gianfar.h @@ -718,14 +718,14 @@ struct gfar_private { uint32_t msg_enable; }; -static inline u32 gfar_read(volatile unsigned *addr) +extern inline u32 gfar_read(volatile unsigned *addr) { u32 val; val = in_be32(addr); return val; } -static inline void gfar_write(volatile unsigned *addr, u32 val) +extern inline void gfar_write(volatile unsigned *addr, u32 val) { out_be32(addr, val); } diff --git a/trunk/drivers/net/hp-plus.c b/trunk/drivers/net/hp-plus.c index 74e167e7dea7..0abf5dd08b4c 100644 --- a/trunk/drivers/net/hp-plus.c +++ b/trunk/drivers/net/hp-plus.c @@ -138,6 +138,12 @@ static int __init do_hpp_probe(struct net_device *dev) return -ENODEV; } +static void cleanup_card(struct net_device *dev) +{ + /* NB: hpp_close() handles free_irq */ + release_region(dev->base_addr - NIC_OFFSET, HP_IO_EXTENT); +} + #ifndef MODULE struct net_device * __init hp_plus_probe(int unit) { @@ -467,12 +473,6 @@ init_module(void) return -ENXIO; } -static void cleanup_card(struct net_device *dev) -{ - /* NB: hpp_close() handles free_irq */ - release_region(dev->base_addr - NIC_OFFSET, HP_IO_EXTENT); -} - void cleanup_module(void) { diff --git a/trunk/drivers/net/hp.c b/trunk/drivers/net/hp.c index cf9fb3698a6b..59cf841b14ab 100644 --- a/trunk/drivers/net/hp.c +++ b/trunk/drivers/net/hp.c @@ -102,6 +102,12 @@ static int __init do_hp_probe(struct net_device *dev) return -ENODEV; } +static void cleanup_card(struct net_device *dev) +{ + free_irq(dev->irq, dev); + release_region(dev->base_addr - NIC_OFFSET, HP_IO_EXTENT); +} + #ifndef MODULE struct net_device * __init hp_probe(int unit) { @@ -438,12 +444,6 @@ init_module(void) return -ENXIO; } -static void cleanup_card(struct net_device *dev) -{ - free_irq(dev->irq, dev); - release_region(dev->base_addr - NIC_OFFSET, HP_IO_EXTENT); -} - void cleanup_module(void) { diff --git a/trunk/drivers/net/ibm_emac/ibm_emac.h b/trunk/drivers/net/ibm_emac/ibm_emac.h index c2dae6092c4c..644edbff4f94 100644 --- a/trunk/drivers/net/ibm_emac/ibm_emac.h +++ b/trunk/drivers/net/ibm_emac/ibm_emac.h @@ -110,7 +110,6 @@ struct emac_regs { #define EMAC_MR1_TFS_2K 0x00080000 #define EMAC_MR1_TR0_MULT 0x00008000 #define EMAC_MR1_JPSM 0x00000000 -#define EMAC_MR1_MWSW_001 0x00000000 #define EMAC_MR1_BASE(opb) (EMAC_MR1_TFS_2K | EMAC_MR1_TR0_MULT) #else #define EMAC_MR1_RFS_4K 0x00180000 @@ -131,7 +130,7 @@ struct emac_regs { (freq) <= 83 ? EMAC_MR1_OBCI_83 : \ (freq) <= 100 ? EMAC_MR1_OBCI_100 : EMAC_MR1_OBCI_100P) #define EMAC_MR1_BASE(opb) (EMAC_MR1_TFS_2K | EMAC_MR1_TR | \ - EMAC_MR1_OBCI(opb)) + EMAC_MR1_MWSW_001 | EMAC_MR1_OBCI(opb)) #endif /* EMACx_TMR0 */ diff --git a/trunk/drivers/net/ibm_emac/ibm_emac_core.c b/trunk/drivers/net/ibm_emac/ibm_emac_core.c index 591c5864ffb1..1da8a66f91e1 100644 --- a/trunk/drivers/net/ibm_emac/ibm_emac_core.c +++ b/trunk/drivers/net/ibm_emac/ibm_emac_core.c @@ -408,7 +408,7 @@ static int emac_configure(struct ocp_enet_private *dev) /* Mode register */ r = EMAC_MR1_BASE(emac_opb_mhz()) | EMAC_MR1_VLE | EMAC_MR1_IST; if (dev->phy.duplex == DUPLEX_FULL) - r |= EMAC_MR1_FDE | EMAC_MR1_MWSW_001; + r |= EMAC_MR1_FDE; dev->stop_timeout = STOP_TIMEOUT_10; switch (dev->phy.speed) { case SPEED_1000: diff --git a/trunk/drivers/net/lance.c b/trunk/drivers/net/lance.c index d1d714faa6ce..1d75ca0bb939 100644 --- a/trunk/drivers/net/lance.c +++ b/trunk/drivers/net/lance.c @@ -309,6 +309,17 @@ static void lance_tx_timeout (struct net_device *dev); +static void cleanup_card(struct net_device *dev) +{ + struct lance_private *lp = dev->priv; + if (dev->dma != 4) + free_dma(dev->dma); + release_region(dev->base_addr, LANCE_TOTAL_SIZE); + kfree(lp->tx_bounce_buffs); + kfree((void*)lp->rx_buffs); + kfree(lp); +} + #ifdef MODULE #define MAX_CARDS 8 /* Max number of interfaces (cards) per module */ @@ -356,17 +367,6 @@ int init_module(void) return -ENXIO; } -static void cleanup_card(struct net_device *dev) -{ - struct lance_private *lp = dev->priv; - if (dev->dma != 4) - free_dma(dev->dma); - release_region(dev->base_addr, LANCE_TOTAL_SIZE); - kfree(lp->tx_bounce_buffs); - kfree((void*)lp->rx_buffs); - kfree(lp); -} - void cleanup_module(void) { int this_dev; diff --git a/trunk/drivers/net/lne390.c b/trunk/drivers/net/lne390.c index 646e89fc3562..309d254842cf 100644 --- a/trunk/drivers/net/lne390.c +++ b/trunk/drivers/net/lne390.c @@ -145,6 +145,13 @@ static int __init do_lne390_probe(struct net_device *dev) return -ENODEV; } +static void cleanup_card(struct net_device *dev) +{ + free_irq(dev->irq, dev); + release_region(dev->base_addr, LNE390_IO_EXTENT); + iounmap(ei_status.mem); +} + #ifndef MODULE struct net_device * __init lne390_probe(int unit) { @@ -433,13 +440,6 @@ int init_module(void) return -ENXIO; } -static void cleanup_card(struct net_device *dev) -{ - free_irq(dev->irq, dev); - release_region(dev->base_addr, LNE390_IO_EXTENT); - iounmap(ei_status.mem); -} - void cleanup_module(void) { int this_dev; diff --git a/trunk/drivers/net/mv643xx_eth.c b/trunk/drivers/net/mv643xx_eth.c index 22c3a37bba5a..3cb9b3fe0cf1 100644 --- a/trunk/drivers/net/mv643xx_eth.c +++ b/trunk/drivers/net/mv643xx_eth.c @@ -6,7 +6,7 @@ * Copyright (C) 2002 rabeeh@galileo.co.il * * Copyright (C) 2003 PMC-Sierra, Inc., - * written by Manish Lachwani + * written by Manish Lachwani (lachwani@pmc-sierra.com) * * Copyright (C) 2003 Ralf Baechle * diff --git a/trunk/drivers/net/ne.c b/trunk/drivers/net/ne.c index 94f782d51f0f..0de8fdd2aa86 100644 --- a/trunk/drivers/net/ne.c +++ b/trunk/drivers/net/ne.c @@ -212,6 +212,15 @@ static int __init do_ne_probe(struct net_device *dev) return -ENODEV; } +static void cleanup_card(struct net_device *dev) +{ + struct pnp_dev *idev = (struct pnp_dev *)ei_status.priv; + if (idev) + pnp_device_detach(idev); + free_irq(dev->irq, dev); + release_region(dev->base_addr, NE_IO_EXTENT); +} + #ifndef MODULE struct net_device * __init ne_probe(int unit) { @@ -850,15 +859,6 @@ int init_module(void) return -ENODEV; } -static void cleanup_card(struct net_device *dev) -{ - struct pnp_dev *idev = (struct pnp_dev *)ei_status.priv; - if (idev) - pnp_device_detach(idev); - free_irq(dev->irq, dev); - release_region(dev->base_addr, NE_IO_EXTENT); -} - void cleanup_module(void) { int this_dev; diff --git a/trunk/drivers/net/ne2.c b/trunk/drivers/net/ne2.c index e6df375a1d4b..6d62ada85de6 100644 --- a/trunk/drivers/net/ne2.c +++ b/trunk/drivers/net/ne2.c @@ -278,6 +278,14 @@ static int __init do_ne2_probe(struct net_device *dev) return -ENODEV; } +static void cleanup_card(struct net_device *dev) +{ + mca_mark_as_unused(ei_status.priv); + mca_set_adapter_procfn( ei_status.priv, NULL, NULL); + free_irq(dev->irq, dev); + release_region(dev->base_addr, NE_IO_EXTENT); +} + #ifndef MODULE struct net_device * __init ne2_probe(int unit) { @@ -804,14 +812,6 @@ int init_module(void) return -ENXIO; } -static void cleanup_card(struct net_device *dev) -{ - mca_mark_as_unused(ei_status.priv); - mca_set_adapter_procfn( ei_status.priv, NULL, NULL); - free_irq(dev->irq, dev); - release_region(dev->base_addr, NE_IO_EXTENT); -} - void cleanup_module(void) { int this_dev; diff --git a/trunk/drivers/net/sk98lin/skge.c b/trunk/drivers/net/sk98lin/skge.c index 197edd74fbb5..9a76ac180b11 100644 --- a/trunk/drivers/net/sk98lin/skge.c +++ b/trunk/drivers/net/sk98lin/skge.c @@ -282,22 +282,26 @@ SK_U32 Val) /* pointer to store the read value */ * Description: * This function initialize the PCI resources and IO * - * Returns: - * 0 - indicate everything worked ok. - * != 0 - error indication + * Returns: N/A + * */ -static __devinit int SkGeInitPCI(SK_AC *pAC) +int SkGeInitPCI(SK_AC *pAC) { struct SK_NET_DEVICE *dev = pAC->dev[0]; struct pci_dev *pdev = pAC->PciDev; int retval; + if (pci_enable_device(pdev) != 0) { + return 1; + } + dev->mem_start = pci_resource_start (pdev, 0); pci_set_master(pdev); - retval = pci_request_regions(pdev, "sk98lin"); - if (retval) - goto out; + if (pci_request_regions(pdev, "sk98lin") != 0) { + retval = 2; + goto out_disable; + } #ifdef SK_BIG_ENDIAN /* @@ -316,8 +320,9 @@ static __devinit int SkGeInitPCI(SK_AC *pAC) * Remap the regs into kernel space. */ pAC->IoBase = ioremap_nocache(dev->mem_start, 0x4000); - if (!pAC->IoBase) { - retval = -EIO; + + if (!pAC->IoBase){ + retval = 3; goto out_release; } @@ -325,7 +330,8 @@ static __devinit int SkGeInitPCI(SK_AC *pAC) out_release: pci_release_regions(pdev); - out: + out_disable: + pci_disable_device(pdev); return retval; } @@ -486,7 +492,7 @@ module_param_array(AutoSizing, charp, NULL, 0); * 0, if everything is ok * !=0, on error */ -static int __devinit SkGeBoardInit(struct SK_NET_DEVICE *dev, SK_AC *pAC) +static int __init SkGeBoardInit(struct SK_NET_DEVICE *dev, SK_AC *pAC) { short i; unsigned long Flags; @@ -523,7 +529,7 @@ SK_BOOL DualNet; if (SkGeInit(pAC, pAC->IoBase, SK_INIT_DATA) != 0) { printk("HWInit (0) failed.\n"); spin_unlock_irqrestore(&pAC->SlowPathLock, Flags); - return -EIO; + return(-EAGAIN); } SkI2cInit( pAC, pAC->IoBase, SK_INIT_DATA); SkEventInit(pAC, pAC->IoBase, SK_INIT_DATA); @@ -545,7 +551,7 @@ SK_BOOL DualNet; if (SkGeInit(pAC, pAC->IoBase, SK_INIT_IO) != 0) { printk("sk98lin: HWInit (1) failed.\n"); spin_unlock_irqrestore(&pAC->SlowPathLock, Flags); - return -EIO; + return(-EAGAIN); } SkI2cInit( pAC, pAC->IoBase, SK_INIT_IO); SkEventInit(pAC, pAC->IoBase, SK_INIT_IO); @@ -577,20 +583,20 @@ SK_BOOL DualNet; } else { printk(KERN_WARNING "sk98lin: Illegal number of ports: %d\n", pAC->GIni.GIMacsFound); - return -EIO; + return -EAGAIN; } if (Ret) { printk(KERN_WARNING "sk98lin: Requested IRQ %d is busy.\n", dev->irq); - return Ret; + return -EAGAIN; } pAC->AllocFlag |= SK_ALLOC_IRQ; /* Alloc memory for this board (Mem for RxD/TxD) : */ if(!BoardAllocMem(pAC)) { printk("No memory for descriptor rings.\n"); - return -ENOMEM; + return(-EAGAIN); } BoardInitMem(pAC); @@ -606,7 +612,7 @@ SK_BOOL DualNet; DualNet)) { BoardFreeMem(pAC); printk("sk98lin: SkGeInitAssignRamToQueues failed.\n"); - return -EIO; + return(-EAGAIN); } return (0); @@ -627,7 +633,8 @@ SK_BOOL DualNet; * SK_TRUE, if all memory could be allocated * SK_FALSE, if not */ -static __devinit SK_BOOL BoardAllocMem(SK_AC *pAC) +static SK_BOOL BoardAllocMem( +SK_AC *pAC) { caddr_t pDescrMem; /* pointer to descriptor memory area */ size_t AllocLength; /* length of complete descriptor area */ @@ -720,7 +727,8 @@ size_t AllocLength; /* length of complete descriptor area */ * * Returns: N/A */ -static __devinit void BoardInitMem(SK_AC *pAC) +static void BoardInitMem( +SK_AC *pAC) /* pointer to adapter context */ { int i; /* loop counter */ int RxDescrSize; /* the size of a rx descriptor rounded up to alignment*/ @@ -4768,47 +4776,32 @@ static int __devinit skge_probe_one(struct pci_dev *pdev, struct net_device *dev = NULL; static int boards_found = 0; int error = -ENODEV; - int using_dac = 0; char DeviceStr[80]; if (pci_enable_device(pdev)) goto out; /* Configure DMA attributes. */ - if (sizeof(dma_addr_t) > sizeof(u32) && - !(error = pci_set_dma_mask(pdev, DMA_64BIT_MASK))) { - using_dac = 1; - error = pci_set_consistent_dma_mask(pdev, DMA_64BIT_MASK); - if (error < 0) { - printk(KERN_ERR "sk98lin %s unable to obtain 64 bit DMA " - "for consistent allocations\n", pci_name(pdev)); - goto out_disable_device; - } - } else { - error = pci_set_dma_mask(pdev, DMA_32BIT_MASK); - if (error) { - printk(KERN_ERR "sk98lin %s no usable DMA configuration\n", - pci_name(pdev)); - goto out_disable_device; - } - } + if (pci_set_dma_mask(pdev, DMA_64BIT_MASK) && + pci_set_dma_mask(pdev, DMA_32BIT_MASK)) + goto out_disable_device; + - error = -ENOMEM; - dev = alloc_etherdev(sizeof(DEV_NET)); - if (!dev) { - printk(KERN_ERR "sk98lin: unable to allocate etherdev " + if ((dev = alloc_etherdev(sizeof(DEV_NET))) == NULL) { + printk(KERN_ERR "Unable to allocate etherdev " "structure!\n"); goto out_disable_device; } pNet = netdev_priv(dev); - pNet->pAC = kzalloc(sizeof(SK_AC), GFP_KERNEL); + pNet->pAC = kmalloc(sizeof(SK_AC), GFP_KERNEL); if (!pNet->pAC) { - printk(KERN_ERR "sk98lin: unable to allocate adapter " + printk(KERN_ERR "Unable to allocate adapter " "structure!\n"); goto out_free_netdev; } + memset(pNet->pAC, 0, sizeof(SK_AC)); pAC = pNet->pAC; pAC->PciDev = pdev; @@ -4817,7 +4810,6 @@ static int __devinit skge_probe_one(struct pci_dev *pdev, pAC->CheckQueue = SK_FALSE; dev->irq = pdev->irq; - error = SkGeInitPCI(pAC); if (error) { printk(KERN_ERR "sk98lin: PCI setup failed: %i\n", error); @@ -4852,25 +4844,19 @@ static int __devinit skge_probe_one(struct pci_dev *pdev, #endif } - if (using_dac) - dev->features |= NETIF_F_HIGHDMA; - pAC->Index = boards_found++; - error = SkGeBoardInit(dev, pAC); - if (error) + if (SkGeBoardInit(dev, pAC)) goto out_free_netdev; /* Read Adapter name from VPD */ if (ProductStr(pAC, DeviceStr, sizeof(DeviceStr)) != 0) { - error = -EIO; printk(KERN_ERR "sk98lin: Could not read VPD data.\n"); goto out_free_resources; } /* Register net device */ - error = register_netdev(dev); - if (error) { + if (register_netdev(dev)) { printk(KERN_ERR "sk98lin: Could not register device.\n"); goto out_free_resources; } @@ -4897,17 +4883,15 @@ static int __devinit skge_probe_one(struct pci_dev *pdev, boards_found++; - pci_set_drvdata(pdev, dev); - /* More then one port found */ if ((pAC->GIni.GIMacsFound == 2 ) && (pAC->RlmtNets == 2)) { - dev = alloc_etherdev(sizeof(DEV_NET)); - if (!dev) { - printk(KERN_ERR "sk98lin: unable to allocate etherdev " + if ((dev = alloc_etherdev(sizeof(DEV_NET))) == 0) { + printk(KERN_ERR "Unable to allocate etherdev " "structure!\n"); - goto single_port; + goto out; } + pAC->dev[1] = dev; pNet = netdev_priv(dev); pNet->PortNr = 1; pNet->NetNr = 1; @@ -4936,28 +4920,20 @@ static int __devinit skge_probe_one(struct pci_dev *pdev, #endif } - if (using_dac) - dev->features |= NETIF_F_HIGHDMA; - - error = register_netdev(dev); - if (error) { - printk(KERN_ERR "sk98lin: Could not register device" - " for second port. (%d)\n", error); + if (register_netdev(dev)) { + printk(KERN_ERR "sk98lin: Could not register device for seconf port.\n"); free_netdev(dev); - goto single_port; + pAC->dev[1] = pAC->dev[0]; + } else { + memcpy(&dev->dev_addr, + &pAC->Addr.Net[1].CurrentMacAddress, 6); + memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len); + + printk("%s: %s\n", dev->name, DeviceStr); + printk(" PrefPort:B RlmtMode:Dual Check Link State\n"); } - - pAC->dev[1] = dev; - memcpy(&dev->dev_addr, - &pAC->Addr.Net[1].CurrentMacAddress, 6); - memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len); - - printk("%s: %s\n", dev->name, DeviceStr); - printk(" PrefPort:B RlmtMode:Dual Check Link State\n"); } -single_port: - /* Save the hardware revision */ pAC->HWRevision = (((pAC->GIni.GIPciHwRev >> 4) & 0x0F)*10) + (pAC->GIni.GIPciHwRev & 0x0F); @@ -4969,6 +4945,7 @@ static int __devinit skge_probe_one(struct pci_dev *pdev, memset(&pAC->PnmiBackup, 0, sizeof(SK_PNMI_STRUCT_DATA)); memcpy(&pAC->PnmiBackup, &pAC->PnmiStruct, sizeof(SK_PNMI_STRUCT_DATA)); + pci_set_drvdata(pdev, dev); return 0; out_free_resources: diff --git a/trunk/drivers/net/smc-ultra.c b/trunk/drivers/net/smc-ultra.c index 3db30cd0625e..ba8593ac3f8a 100644 --- a/trunk/drivers/net/smc-ultra.c +++ b/trunk/drivers/net/smc-ultra.c @@ -168,6 +168,18 @@ static int __init do_ultra_probe(struct net_device *dev) return -ENODEV; } +static void cleanup_card(struct net_device *dev) +{ + /* NB: ultra_close_card() does free_irq */ +#ifdef __ISAPNP__ + struct pnp_dev *idev = (struct pnp_dev *)ei_status.priv; + if (idev) + pnp_device_detach(idev); +#endif + release_region(dev->base_addr - ULTRA_NIC_OFFSET, ULTRA_IO_EXTENT); + iounmap(ei_status.mem); +} + #ifndef MODULE struct net_device * __init ultra_probe(int unit) { @@ -582,18 +594,6 @@ init_module(void) return -ENXIO; } -static void cleanup_card(struct net_device *dev) -{ - /* NB: ultra_close_card() does free_irq */ -#ifdef __ISAPNP__ - struct pnp_dev *idev = (struct pnp_dev *)ei_status.priv; - if (idev) - pnp_device_detach(idev); -#endif - release_region(dev->base_addr - ULTRA_NIC_OFFSET, ULTRA_IO_EXTENT); - iounmap(ei_status.mem); -} - void cleanup_module(void) { diff --git a/trunk/drivers/net/tulip/tulip_core.c b/trunk/drivers/net/tulip/tulip_core.c index c67c91251d04..125ed00e95a5 100644 --- a/trunk/drivers/net/tulip/tulip_core.c +++ b/trunk/drivers/net/tulip/tulip_core.c @@ -1564,7 +1564,7 @@ static int __devinit tulip_init_one (struct pci_dev *pdev, dev->dev_addr, 6); } #endif -#if defined(__i386__) || defined(__x86_64__) /* Patch up x86 BIOS bug. */ +#if defined(__i386__) /* Patch up x86 BIOS bug. */ if (last_irq) irq = last_irq; #endif diff --git a/trunk/drivers/net/wd.c b/trunk/drivers/net/wd.c index 7caa8dc88a58..b03feae459fc 100644 --- a/trunk/drivers/net/wd.c +++ b/trunk/drivers/net/wd.c @@ -127,6 +127,13 @@ static int __init do_wd_probe(struct net_device *dev) return -ENODEV; } +static void cleanup_card(struct net_device *dev) +{ + free_irq(dev->irq, dev); + release_region(dev->base_addr - WD_NIC_OFFSET, WD_IO_EXTENT); + iounmap(ei_status.mem); +} + #ifndef MODULE struct net_device * __init wd_probe(int unit) { @@ -531,13 +538,6 @@ init_module(void) return -ENXIO; } -static void cleanup_card(struct net_device *dev) -{ - free_irq(dev->irq, dev); - release_region(dev->base_addr - WD_NIC_OFFSET, WD_IO_EXTENT); - iounmap(ei_status.mem); -} - void cleanup_module(void) { diff --git a/trunk/drivers/net/wireless/ipw2100.c b/trunk/drivers/net/wireless/ipw2100.c index cf05661fb1bd..44cd3fcd1572 100644 --- a/trunk/drivers/net/wireless/ipw2100.c +++ b/trunk/drivers/net/wireless/ipw2100.c @@ -7153,7 +7153,7 @@ static int ipw2100_wx_get_range(struct net_device *dev, /* Set the Wireless Extension versions */ range->we_version_compiled = WIRELESS_EXT; - range->we_version_source = 18; + range->we_version_source = 16; // range->retry_capa; /* What retry options are supported */ // range->retry_flags; /* How to decode max/min retry limit */ @@ -7184,9 +7184,6 @@ static int ipw2100_wx_get_range(struct net_device *dev, IW_EVENT_CAPA_MASK(SIOCGIWAP)); range->event_capa[1] = IW_EVENT_CAPA_K_1; - range->enc_capa = IW_ENC_CAPA_WPA | IW_ENC_CAPA_WPA2 | - IW_ENC_CAPA_CIPHER_TKIP | IW_ENC_CAPA_CIPHER_CCMP; - IPW_DEBUG_WX("GET Range\n"); return 0; diff --git a/trunk/drivers/scsi/sata_nv.c b/trunk/drivers/scsi/sata_nv.c index c0cf52cb975a..bbbb55eeb73a 100644 --- a/trunk/drivers/scsi/sata_nv.c +++ b/trunk/drivers/scsi/sata_nv.c @@ -29,6 +29,12 @@ * NV-specific details such as register offsets, SATA phy location, * hotplug info, etc. * + * 0.10 + * - Fixed spurious interrupts issue seen with the Maxtor 6H500F0 500GB + * drive. Also made the check_hotplug() callbacks return whether there + * was a hotplug interrupt or not. This was not the source of the + * spurious interrupts, but is the right thing to do anyway. + * * 0.09 * - Fixed bug introduced by 0.08's MCP51 and MCP55 support. * @@ -124,10 +130,10 @@ static void nv_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val); static void nv_host_stop (struct ata_host_set *host_set); static void nv_enable_hotplug(struct ata_probe_ent *probe_ent); static void nv_disable_hotplug(struct ata_host_set *host_set); -static void nv_check_hotplug(struct ata_host_set *host_set); +static int nv_check_hotplug(struct ata_host_set *host_set); static void nv_enable_hotplug_ck804(struct ata_probe_ent *probe_ent); static void nv_disable_hotplug_ck804(struct ata_host_set *host_set); -static void nv_check_hotplug_ck804(struct ata_host_set *host_set); +static int nv_check_hotplug_ck804(struct ata_host_set *host_set); enum nv_host_type { @@ -176,7 +182,7 @@ struct nv_host_desc enum nv_host_type host_type; void (*enable_hotplug)(struct ata_probe_ent *probe_ent); void (*disable_hotplug)(struct ata_host_set *host_set); - void (*check_hotplug)(struct ata_host_set *host_set); + int (*check_hotplug)(struct ata_host_set *host_set); }; static struct nv_host_desc nv_device_tbl[] = { @@ -309,12 +315,16 @@ static irqreturn_t nv_interrupt (int irq, void *dev_instance, qc = ata_qc_from_tag(ap, ap->active_tag); if (qc && (!(qc->tf.ctl & ATA_NIEN))) handled += ata_host_intr(ap, qc); + else + // No request pending? Clear interrupt status + // anyway, in case there's one pending. + ap->ops->check_status(ap); } } if (host->host_desc->check_hotplug) - host->host_desc->check_hotplug(host_set); + handled += host->host_desc->check_hotplug(host_set); spin_unlock_irqrestore(&host_set->lock, flags); @@ -497,7 +507,7 @@ static void nv_disable_hotplug(struct ata_host_set *host_set) outb(intr_mask, host_set->ports[0]->ioaddr.scr_addr + NV_INT_ENABLE); } -static void nv_check_hotplug(struct ata_host_set *host_set) +static int nv_check_hotplug(struct ata_host_set *host_set) { u8 intr_status; @@ -522,7 +532,11 @@ static void nv_check_hotplug(struct ata_host_set *host_set) if (intr_status & NV_INT_STATUS_SDEV_REMOVED) printk(KERN_WARNING "nv_sata: " "Secondary device removed\n"); + + return 1; } + + return 0; } static void nv_enable_hotplug_ck804(struct ata_probe_ent *probe_ent) @@ -560,7 +574,7 @@ static void nv_disable_hotplug_ck804(struct ata_host_set *host_set) pci_write_config_byte(pdev, NV_MCP_SATA_CFG_20, regval); } -static void nv_check_hotplug_ck804(struct ata_host_set *host_set) +static int nv_check_hotplug_ck804(struct ata_host_set *host_set) { u8 intr_status; @@ -585,7 +599,11 @@ static void nv_check_hotplug_ck804(struct ata_host_set *host_set) if (intr_status & NV_INT_STATUS_SDEV_REMOVED) printk(KERN_WARNING "nv_sata: " "Secondary device removed\n"); + + return 1; } + + return 0; } static int __init nv_init(void) diff --git a/trunk/drivers/scsi/scsi.c b/trunk/drivers/scsi/scsi.c index ee5f4dfdab14..180676d7115a 100644 --- a/trunk/drivers/scsi/scsi.c +++ b/trunk/drivers/scsi/scsi.c @@ -69,6 +69,7 @@ #include "scsi_logging.h" static void scsi_done(struct scsi_cmnd *cmd); +static int scsi_retry_command(struct scsi_cmnd *cmd); /* * Definitions and constants. @@ -751,7 +752,7 @@ static void scsi_done(struct scsi_cmnd *cmd) * isn't running --- used by scsi_times_out */ void __scsi_done(struct scsi_cmnd *cmd) { - struct request *rq = cmd->request; + unsigned long flags; /* * Set the serial numbers back to zero @@ -762,14 +763,71 @@ void __scsi_done(struct scsi_cmnd *cmd) if (cmd->result) atomic_inc(&cmd->device->ioerr_cnt); - BUG_ON(!rq); - /* - * The uptodate/nbytes values don't matter, as we allow partial - * completes and thus will check this in the softirq callback + * Next, enqueue the command into the done queue. + * It is a per-CPU queue, so we just disable local interrupts + * and need no spinlock. */ - rq->completion_data = cmd; - blk_complete_request(rq); + local_irq_save(flags); + list_add_tail(&cmd->eh_entry, &__get_cpu_var(scsi_done_q)); + raise_softirq_irqoff(SCSI_SOFTIRQ); + local_irq_restore(flags); +} + +/** + * scsi_softirq - Perform post-interrupt processing of finished SCSI commands. + * + * This is the consumer of the done queue. + * + * This is called with all interrupts enabled. This should reduce + * interrupt latency, stack depth, and reentrancy of the low-level + * drivers. + */ +static void scsi_softirq(struct softirq_action *h) +{ + int disposition; + LIST_HEAD(local_q); + + local_irq_disable(); + list_splice_init(&__get_cpu_var(scsi_done_q), &local_q); + local_irq_enable(); + + while (!list_empty(&local_q)) { + struct scsi_cmnd *cmd = list_entry(local_q.next, + struct scsi_cmnd, eh_entry); + /* The longest time any command should be outstanding is the + * per command timeout multiplied by the number of retries. + * + * For a typical command, this is 2.5 minutes */ + unsigned long wait_for + = cmd->allowed * cmd->timeout_per_command; + list_del_init(&cmd->eh_entry); + + disposition = scsi_decide_disposition(cmd); + if (disposition != SUCCESS && + time_before(cmd->jiffies_at_alloc + wait_for, jiffies)) { + sdev_printk(KERN_ERR, cmd->device, + "timing out command, waited %lus\n", + wait_for/HZ); + disposition = SUCCESS; + } + + scsi_log_completion(cmd, disposition); + switch (disposition) { + case SUCCESS: + scsi_finish_command(cmd); + break; + case NEEDS_RETRY: + scsi_retry_command(cmd); + break; + case ADD_TO_MLQUEUE: + scsi_queue_insert(cmd, SCSI_MLQUEUE_DEVICE_BUSY); + break; + default: + if (!scsi_eh_scmd_add(cmd, 0)) + scsi_finish_command(cmd); + } + } } /* @@ -782,7 +840,7 @@ void __scsi_done(struct scsi_cmnd *cmd) * level drivers should not become re-entrant as a result of * this. */ -int scsi_retry_command(struct scsi_cmnd *cmd) +static int scsi_retry_command(struct scsi_cmnd *cmd) { /* * Restore the SCSI command state. @@ -1215,6 +1273,38 @@ int scsi_device_cancel(struct scsi_device *sdev, int recovery) } EXPORT_SYMBOL(scsi_device_cancel); +#ifdef CONFIG_HOTPLUG_CPU +static int scsi_cpu_notify(struct notifier_block *self, + unsigned long action, void *hcpu) +{ + int cpu = (unsigned long)hcpu; + + switch(action) { + case CPU_DEAD: + /* Drain scsi_done_q. */ + local_irq_disable(); + list_splice_init(&per_cpu(scsi_done_q, cpu), + &__get_cpu_var(scsi_done_q)); + raise_softirq_irqoff(SCSI_SOFTIRQ); + local_irq_enable(); + break; + default: + break; + } + return NOTIFY_OK; +} + +static struct notifier_block __devinitdata scsi_cpu_nb = { + .notifier_call = scsi_cpu_notify, +}; + +#define register_scsi_cpu() register_cpu_notifier(&scsi_cpu_nb) +#define unregister_scsi_cpu() unregister_cpu_notifier(&scsi_cpu_nb) +#else +#define register_scsi_cpu() +#define unregister_scsi_cpu() +#endif /* CONFIG_HOTPLUG_CPU */ + MODULE_DESCRIPTION("SCSI core"); MODULE_LICENSE("GPL"); @@ -1248,6 +1338,8 @@ static int __init init_scsi(void) INIT_LIST_HEAD(&per_cpu(scsi_done_q, i)); devfs_mk_dir("scsi"); + open_softirq(SCSI_SOFTIRQ, scsi_softirq, NULL); + register_scsi_cpu(); printk(KERN_NOTICE "SCSI subsystem initialized\n"); return 0; @@ -1275,6 +1367,7 @@ static void __exit exit_scsi(void) devfs_remove("scsi"); scsi_exit_procfs(); scsi_exit_queue(); + unregister_scsi_cpu(); } subsys_initcall(init_scsi); diff --git a/trunk/drivers/scsi/scsi_lib.c b/trunk/drivers/scsi/scsi_lib.c index 00c9bf383e23..ba93d6e66d48 100644 --- a/trunk/drivers/scsi/scsi_lib.c +++ b/trunk/drivers/scsi/scsi_lib.c @@ -1493,41 +1493,6 @@ static void scsi_kill_request(struct request *req, request_queue_t *q) __scsi_done(cmd); } -static void scsi_softirq_done(struct request *rq) -{ - struct scsi_cmnd *cmd = rq->completion_data; - unsigned long wait_for = cmd->allowed * cmd->timeout_per_command; - int disposition; - - INIT_LIST_HEAD(&cmd->eh_entry); - - disposition = scsi_decide_disposition(cmd); - if (disposition != SUCCESS && - time_before(cmd->jiffies_at_alloc + wait_for, jiffies)) { - sdev_printk(KERN_ERR, cmd->device, - "timing out command, waited %lus\n", - wait_for/HZ); - disposition = SUCCESS; - } - - scsi_log_completion(cmd, disposition); - - switch (disposition) { - case SUCCESS: - scsi_finish_command(cmd); - break; - case NEEDS_RETRY: - scsi_retry_command(cmd); - break; - case ADD_TO_MLQUEUE: - scsi_queue_insert(cmd, SCSI_MLQUEUE_DEVICE_BUSY); - break; - default: - if (!scsi_eh_scmd_add(cmd, 0)) - scsi_finish_command(cmd); - } -} - /* * Function: scsi_request_fn() * @@ -1702,7 +1667,6 @@ struct request_queue *scsi_alloc_queue(struct scsi_device *sdev) blk_queue_bounce_limit(q, scsi_calculate_bounce_limit(shost)); blk_queue_segment_boundary(q, shost->dma_boundary); blk_queue_issue_flush_fn(q, scsi_issue_flush_fn); - blk_queue_softirq_done(q, scsi_softirq_done); if (!shost->use_clustering) clear_bit(QUEUE_FLAG_CLUSTER, &q->queue_flags); diff --git a/trunk/drivers/scsi/scsi_priv.h b/trunk/drivers/scsi/scsi_priv.h index 14a6198cb8d2..f04e7e11f57a 100644 --- a/trunk/drivers/scsi/scsi_priv.h +++ b/trunk/drivers/scsi/scsi_priv.h @@ -44,7 +44,6 @@ extern void scsi_init_cmd_from_req(struct scsi_cmnd *cmd, struct scsi_request *sreq); extern void __scsi_release_request(struct scsi_request *sreq); extern void __scsi_done(struct scsi_cmnd *cmd); -extern int scsi_retry_command(struct scsi_cmnd *cmd); #ifdef CONFIG_SCSI_LOGGING void scsi_log_send(struct scsi_cmnd *cmd); void scsi_log_completion(struct scsi_cmnd *cmd, int disposition); diff --git a/trunk/fs/bio.c b/trunk/fs/bio.c index 7b3069589951..dfe242a21eb4 100644 --- a/trunk/fs/bio.c +++ b/trunk/fs/bio.c @@ -126,7 +126,6 @@ static void bio_fs_destructor(struct bio *bio) inline void bio_init(struct bio *bio) { bio->bi_next = NULL; - bio->bi_bdev = NULL; bio->bi_flags = 1 << BIO_UPTODATE; bio->bi_rw = 0; bio->bi_vcnt = 0; diff --git a/trunk/include/linux/blkdev.h b/trunk/include/linux/blkdev.h index 02a585faa62c..fb0985377421 100644 --- a/trunk/include/linux/blkdev.h +++ b/trunk/include/linux/blkdev.h @@ -118,9 +118,9 @@ struct request_list { * try to put the fields that are referenced together in the same cacheline */ struct request { - struct list_head queuelist; - struct list_head donelist; - + struct list_head queuelist; /* looking for ->queue? you must _not_ + * access it directly, use + * blkdev_dequeue_request! */ unsigned long flags; /* see REQ_ bits below */ /* Maintain bio traversal state for part by part I/O submission. @@ -141,7 +141,6 @@ struct request { struct bio *biotail; void *elevator_private; - void *completion_data; unsigned short ioprio; @@ -292,7 +291,6 @@ typedef int (merge_bvec_fn) (request_queue_t *, struct bio *, struct bio_vec *); typedef void (activity_fn) (void *data, int rw); typedef int (issue_flush_fn) (request_queue_t *, struct gendisk *, sector_t *); typedef void (prepare_flush_fn) (request_queue_t *, struct request *); -typedef void (softirq_done_fn)(struct request *); enum blk_queue_state { Queue_down, @@ -334,7 +332,6 @@ struct request_queue activity_fn *activity_fn; issue_flush_fn *issue_flush_fn; prepare_flush_fn *prepare_flush_fn; - softirq_done_fn *softirq_done_fn; /* * Dispatch queue sorting @@ -595,6 +592,7 @@ extern void generic_make_request(struct bio *bio); extern void blk_put_request(struct request *); extern void __blk_put_request(request_queue_t *, struct request *); extern void blk_end_sync_rq(struct request *rq, int error); +extern void blk_attempt_remerge(request_queue_t *, struct request *); extern struct request *blk_get_request(request_queue_t *, int, gfp_t); extern void blk_insert_request(request_queue_t *, struct request *, int, void *); extern void blk_requeue_request(request_queue_t *, struct request *); @@ -648,17 +646,6 @@ extern int end_that_request_first(struct request *, int, int); extern int end_that_request_chunk(struct request *, int, int); extern void end_that_request_last(struct request *, int); extern void end_request(struct request *req, int uptodate); -extern void blk_complete_request(struct request *); - -static inline int rq_all_done(struct request *rq, unsigned int nr_bytes) -{ - if (blk_fs_request(rq)) - return (nr_bytes >= (rq->hard_nr_sectors << 9)); - else if (blk_pc_request(rq)) - return nr_bytes >= rq->data_len; - - return 0; -} /* * end_that_request_first/chunk() takes an uptodate argument. we account @@ -707,7 +694,6 @@ extern void blk_queue_segment_boundary(request_queue_t *, unsigned long); extern void blk_queue_prep_rq(request_queue_t *, prep_rq_fn *pfn); extern void blk_queue_merge_bvec(request_queue_t *, merge_bvec_fn *); extern void blk_queue_dma_alignment(request_queue_t *, int); -extern void blk_queue_softirq_done(request_queue_t *, softirq_done_fn *); extern struct backing_dev_info *blk_get_backing_dev_info(struct block_device *bdev); extern int blk_queue_ordered(request_queue_t *, unsigned, prepare_flush_fn *); extern void blk_queue_issue_flush_fn(request_queue_t *, issue_flush_fn *); diff --git a/trunk/include/linux/elevator.h b/trunk/include/linux/elevator.h index 4a6f50e31c73..fb80fa44c4dd 100644 --- a/trunk/include/linux/elevator.h +++ b/trunk/include/linux/elevator.h @@ -114,6 +114,8 @@ extern ssize_t elv_iosched_store(request_queue_t *, const char *, size_t); extern int elevator_init(request_queue_t *, char *); extern void elevator_exit(elevator_t *); extern int elv_rq_merge_ok(struct request *, struct bio *); +extern int elv_try_merge(struct request *, struct bio *); +extern int elv_try_last_merge(request_queue_t *, struct bio *); /* * Return values from elevator merger diff --git a/trunk/include/linux/ide.h b/trunk/include/linux/ide.h index ef8d0cbb832f..4dd6694963c0 100644 --- a/trunk/include/linux/ide.h +++ b/trunk/include/linux/ide.h @@ -1001,7 +1001,6 @@ extern int noautodma; extern int ide_end_request (ide_drive_t *drive, int uptodate, int nrsecs); extern int __ide_end_request (ide_drive_t *drive, struct request *rq, int uptodate, int nrsecs); -extern void ide_softirq_done(struct request *rq); /* * This is used on exit from the driver to designate the next irq handler diff --git a/trunk/include/linux/interrupt.h b/trunk/include/linux/interrupt.h index 2c08fdc2bdf7..e50a95fbeb11 100644 --- a/trunk/include/linux/interrupt.h +++ b/trunk/include/linux/interrupt.h @@ -112,7 +112,7 @@ enum TIMER_SOFTIRQ, NET_TX_SOFTIRQ, NET_RX_SOFTIRQ, - BLOCK_SOFTIRQ, + SCSI_SOFTIRQ, TASKLET_SOFTIRQ }; diff --git a/trunk/include/linux/rcupdate.h b/trunk/include/linux/rcupdate.h index a1d26cb28925..51747cd88d1a 100644 --- a/trunk/include/linux/rcupdate.h +++ b/trunk/include/linux/rcupdate.h @@ -125,7 +125,36 @@ static inline void rcu_bh_qsctr_inc(int cpu) rdp->passed_quiesc = 1; } -extern int rcu_pending(int cpu); +static inline int __rcu_pending(struct rcu_ctrlblk *rcp, + struct rcu_data *rdp) +{ + /* This cpu has pending rcu entries and the grace period + * for them has completed. + */ + if (rdp->curlist && !rcu_batch_before(rcp->completed, rdp->batch)) + return 1; + + /* This cpu has no pending entries, but there are new entries */ + if (!rdp->curlist && rdp->nxtlist) + return 1; + + /* This cpu has finished callbacks to invoke */ + if (rdp->donelist) + return 1; + + /* The rcu core waits for a quiescent state from the cpu */ + if (rdp->quiescbatch != rcp->cur || rdp->qs_pending) + return 1; + + /* nothing to do */ + return 0; +} + +static inline int rcu_pending(int cpu) +{ + return __rcu_pending(&rcu_ctrlblk, &per_cpu(rcu_data, cpu)) || + __rcu_pending(&rcu_bh_ctrlblk, &per_cpu(rcu_bh_data, cpu)); +} /** * rcu_read_lock - mark the beginning of an RCU read-side critical section. diff --git a/trunk/kernel/rcupdate.c b/trunk/kernel/rcupdate.c index ccc45d49ce71..30b0bba03859 100644 --- a/trunk/kernel/rcupdate.c +++ b/trunk/kernel/rcupdate.c @@ -429,36 +429,6 @@ static void rcu_process_callbacks(unsigned long unused) &__get_cpu_var(rcu_bh_data)); } -static int __rcu_pending(struct rcu_ctrlblk *rcp, struct rcu_data *rdp) -{ - /* This cpu has pending rcu entries and the grace period - * for them has completed. - */ - if (rdp->curlist && !rcu_batch_before(rcp->completed, rdp->batch)) - return 1; - - /* This cpu has no pending entries, but there are new entries */ - if (!rdp->curlist && rdp->nxtlist) - return 1; - - /* This cpu has finished callbacks to invoke */ - if (rdp->donelist) - return 1; - - /* The rcu core waits for a quiescent state from the cpu */ - if (rdp->quiescbatch != rcp->cur || rdp->qs_pending) - return 1; - - /* nothing to do */ - return 0; -} - -int rcu_pending(int cpu) -{ - return __rcu_pending(&rcu_ctrlblk, &per_cpu(rcu_data, cpu)) || - __rcu_pending(&rcu_bh_ctrlblk, &per_cpu(rcu_bh_data, cpu)); -} - void rcu_check_callbacks(int cpu, int user) { if (user || diff --git a/trunk/net/ieee80211/ieee80211_crypt_wep.c b/trunk/net/ieee80211/ieee80211_crypt_wep.c index f8dca31be5dd..073aebdf0f67 100644 --- a/trunk/net/ieee80211/ieee80211_crypt_wep.c +++ b/trunk/net/ieee80211/ieee80211_crypt_wep.c @@ -75,14 +75,22 @@ static void prism2_wep_deinit(void *priv) kfree(priv); } -/* Add WEP IV/key info to a frame that has at least 4 bytes of headroom */ -static int prism2_wep_build_iv(struct sk_buff *skb, int hdr_len, void *priv) +/* Perform WEP encryption on given skb that has at least 4 bytes of headroom + * for IV and 4 bytes of tailroom for ICV. Both IV and ICV will be transmitted, + * so the payload length increases with 8 bytes. + * + * WEP frame payload: IV + TX key idx, RC4(data), ICV = RC4(CRC32(data)) + */ +static int prism2_wep_encrypt(struct sk_buff *skb, int hdr_len, void *priv) { struct prism2_wep_data *wep = priv; - u32 klen, len; - u8 *pos; - - if (skb_headroom(skb) < 4 || skb->len < hdr_len) + u32 crc, klen, len; + u8 key[WEP_KEY_LEN + 3]; + u8 *pos, *icv; + struct scatterlist sg; + + if (skb_headroom(skb) < 4 || skb_tailroom(skb) < 4 || + skb->len < hdr_len) return -1; len = skb->len - hdr_len; @@ -104,47 +112,15 @@ static int prism2_wep_build_iv(struct sk_buff *skb, int hdr_len, void *priv) } /* Prepend 24-bit IV to RC4 key and TX frame */ - *pos++ = (wep->iv >> 16) & 0xff; - *pos++ = (wep->iv >> 8) & 0xff; - *pos++ = wep->iv & 0xff; + *pos++ = key[0] = (wep->iv >> 16) & 0xff; + *pos++ = key[1] = (wep->iv >> 8) & 0xff; + *pos++ = key[2] = wep->iv & 0xff; *pos++ = wep->key_idx << 6; - return 0; -} - -/* Perform WEP encryption on given skb that has at least 4 bytes of headroom - * for IV and 4 bytes of tailroom for ICV. Both IV and ICV will be transmitted, - * so the payload length increases with 8 bytes. - * - * WEP frame payload: IV + TX key idx, RC4(data), ICV = RC4(CRC32(data)) - */ -static int prism2_wep_encrypt(struct sk_buff *skb, int hdr_len, void *priv) -{ - struct prism2_wep_data *wep = priv; - u32 crc, klen, len; - u8 *pos, *icv; - struct scatterlist sg; - u8 key[WEP_KEY_LEN + 3]; - - /* other checks are in prism2_wep_build_iv */ - if (skb_tailroom(skb) < 4) - return -1; - - /* add the IV to the frame */ - if (prism2_wep_build_iv(skb, hdr_len, priv)) - return -1; - - /* Copy the IV into the first 3 bytes of the key */ - memcpy(key, skb->data + hdr_len, 3); - /* Copy rest of the WEP key (the secret part) */ memcpy(key + 3, wep->key, wep->key_len); - - len = skb->len - hdr_len - 4; - pos = skb->data + hdr_len + 4; - klen = 3 + wep->key_len; - /* Append little-endian CRC32 over only the data and encrypt it to produce ICV */ + /* Append little-endian CRC32 and encrypt it to produce ICV */ crc = ~crc32_le(~0, pos, len); icv = skb_put(skb, 4); icv[0] = crc; @@ -255,7 +231,6 @@ static struct ieee80211_crypto_ops ieee80211_crypt_wep = { .name = "WEP", .init = prism2_wep_init, .deinit = prism2_wep_deinit, - .build_iv = prism2_wep_build_iv, .encrypt_mpdu = prism2_wep_encrypt, .decrypt_mpdu = prism2_wep_decrypt, .encrypt_msdu = NULL, diff --git a/trunk/net/ieee80211/ieee80211_tx.c b/trunk/net/ieee80211/ieee80211_tx.c index e5b33c8d5dbc..445f206e65e0 100644 --- a/trunk/net/ieee80211/ieee80211_tx.c +++ b/trunk/net/ieee80211/ieee80211_tx.c @@ -288,7 +288,7 @@ int ieee80211_xmit(struct sk_buff *skb, struct net_device *dev) /* Determine total amount of storage required for TXB packets */ bytes = skb->len + SNAP_SIZE + sizeof(u16); - if (host_encrypt || host_build_iv) + if (host_encrypt) fc = IEEE80211_FTYPE_DATA | IEEE80211_STYPE_DATA | IEEE80211_FCTL_PROTECTED; else diff --git a/trunk/net/ieee80211/ieee80211_wx.c b/trunk/net/ieee80211/ieee80211_wx.c index 406d5b964905..181755f2aa8b 100644 --- a/trunk/net/ieee80211/ieee80211_wx.c +++ b/trunk/net/ieee80211/ieee80211_wx.c @@ -284,7 +284,7 @@ int ieee80211_wx_set_encode(struct ieee80211_device *ieee, }; int i, key, key_provided, len; struct ieee80211_crypt_data **crypt; - int host_crypto = ieee->host_encrypt || ieee->host_decrypt || ieee->host_build_iv; + int host_crypto = ieee->host_encrypt || ieee->host_decrypt; IEEE80211_DEBUG_WX("SET_ENCODE\n"); diff --git a/trunk/net/netlink/af_netlink.c b/trunk/net/netlink/af_netlink.c index a67f1b44c9a3..7849cac14d3a 100644 --- a/trunk/net/netlink/af_netlink.c +++ b/trunk/net/netlink/af_netlink.c @@ -402,7 +402,7 @@ static int netlink_create(struct socket *sock, int protocol) groups = nl_table[protocol].groups; netlink_unlock_table(); - if ((err = __netlink_create(sock, protocol)) < 0) + if ((err = __netlink_create(sock, protocol) < 0)) goto out_module; nlk = nlk_sk(sock->sk);