diff options
Diffstat (limited to 'drivers')
147 files changed, 1694 insertions, 1308 deletions
diff --git a/drivers/Kconfig b/drivers/Kconfig index 8a07363417e..368ae6d3a09 100644 --- a/drivers/Kconfig +++ b/drivers/Kconfig @@ -28,7 +28,7 @@ source "drivers/md/Kconfig" source "drivers/message/fusion/Kconfig" -source "drivers/ieee1394/Kconfig" +source "drivers/firewire/Kconfig" source "drivers/message/i2o/Kconfig" diff --git a/drivers/acpi/sleep.c b/drivers/acpi/sleep.c index 5f2c379ab7b..79d33d908b5 100644 --- a/drivers/acpi/sleep.c +++ b/drivers/acpi/sleep.c @@ -81,6 +81,23 @@ static int acpi_sleep_prepare(u32 acpi_state) #ifdef CONFIG_ACPI_SLEEP static u32 acpi_target_sleep_state = ACPI_STATE_S0; /* + * According to the ACPI specification the BIOS should make sure that ACPI is + * enabled and SCI_EN bit is set on wake-up from S1 - S3 sleep states. Still, + * some BIOSes don't do that and therefore we use acpi_enable() to enable ACPI + * on such systems during resume. Unfortunately that doesn't help in + * particularly pathological cases in which SCI_EN has to be set directly on + * resume, although the specification states very clearly that this flag is + * owned by the hardware. The set_sci_en_on_resume variable will be set in such + * cases. + */ +static bool set_sci_en_on_resume; + +void __init acpi_set_sci_en_on_resume(void) +{ + set_sci_en_on_resume = true; +} + +/* * ACPI 1.0 wants us to execute _PTS before suspending devices, so we allow the * user to request that behavior by using the 'acpi_old_suspend_ordering' * kernel command line option that causes the following variable to be set. @@ -170,18 +187,6 @@ static void acpi_pm_end(void) #endif /* CONFIG_ACPI_SLEEP */ #ifdef CONFIG_SUSPEND -/* - * According to the ACPI specification the BIOS should make sure that ACPI is - * enabled and SCI_EN bit is set on wake-up from S1 - S3 sleep states. Still, - * some BIOSes don't do that and therefore we use acpi_enable() to enable ACPI - * on such systems during resume. Unfortunately that doesn't help in - * particularly pathological cases in which SCI_EN has to be set directly on - * resume, although the specification states very clearly that this flag is - * owned by the hardware. The set_sci_en_on_resume variable will be set in such - * cases. - */ -static bool set_sci_en_on_resume; - extern void do_suspend_lowlevel(void); static u32 acpi_suspend_states[] = { diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c index 05dff631591..72e76b4b653 100644 --- a/drivers/acpi/video.c +++ b/drivers/acpi/video.c @@ -999,8 +999,10 @@ static void acpi_video_device_find_cap(struct acpi_video_device *device) sprintf(name, "acpi_video%d", count++); device->backlight = backlight_device_register(name, NULL, device, &acpi_backlight_ops); - device->backlight->props.max_brightness = device->brightness->count-3; kfree(name); + if (IS_ERR(device->backlight)) + return; + device->backlight->props.max_brightness = device->brightness->count-3; result = sysfs_create_link(&device->backlight->dev.kobj, &device->dev->dev.kobj, "device"); @@ -1979,6 +1981,10 @@ acpi_video_switch_brightness(struct acpi_video_device *device, int event) unsigned long long level_current, level_next; int result = -EINVAL; + /* no warning message if acpi_backlight=vendor is used */ + if (!acpi_video_backlight_support()) + return 0; + if (!device->brightness) goto out; diff --git a/drivers/block/DAC960.c b/drivers/block/DAC960.c index eb4fa194394..ce1fa923c41 100644 --- a/drivers/block/DAC960.c +++ b/drivers/block/DAC960.c @@ -7101,7 +7101,7 @@ static struct DAC960_privdata DAC960_BA_privdata = { static struct DAC960_privdata DAC960_LP_privdata = { .HardwareType = DAC960_LP_Controller, - .FirmwareType = DAC960_LP_Controller, + .FirmwareType = DAC960_V2_Controller, .InterruptHandler = DAC960_LP_InterruptHandler, .MemoryWindowSize = DAC960_LP_RegisterWindowSize, }; diff --git a/drivers/block/aoe/aoecmd.c b/drivers/block/aoe/aoecmd.c index 13bb69d2abb..64a223b0cc2 100644 --- a/drivers/block/aoe/aoecmd.c +++ b/drivers/block/aoe/aoecmd.c @@ -735,21 +735,6 @@ diskstats(struct gendisk *disk, struct bio *bio, ulong duration, sector_t sector part_stat_unlock(); } -/* - * Ensure we don't create aliases in VI caches - */ -static inline void -killalias(struct bio *bio) -{ - struct bio_vec *bv; - int i; - - if (bio_data_dir(bio) == READ) - __bio_for_each_segment(bv, bio, i, 0) { - flush_dcache_page(bv->bv_page); - } -} - void aoecmd_ata_rsp(struct sk_buff *skb) { @@ -871,7 +856,7 @@ aoecmd_ata_rsp(struct sk_buff *skb) if (buf->flags & BUFFL_FAIL) bio_endio(buf->bio, -EIO); else { - killalias(buf->bio); + bio_flush_dcache_pages(buf->bio); bio_endio(buf->bio, 0); } mempool_free(buf, d->bufpool); diff --git a/drivers/block/drbd/drbd_int.h b/drivers/block/drbd/drbd_int.h index 2312d782fe9..c9755876343 100644 --- a/drivers/block/drbd/drbd_int.h +++ b/drivers/block/drbd/drbd_int.h @@ -1490,7 +1490,7 @@ void drbd_bump_write_ordering(struct drbd_conf *mdev, enum write_ordering_e wo); /* drbd_proc.c */ extern struct proc_dir_entry *drbd_proc; -extern struct file_operations drbd_proc_fops; +extern const struct file_operations drbd_proc_fops; extern const char *drbd_conn_str(enum drbd_conns s); extern const char *drbd_role_str(enum drbd_role s); diff --git a/drivers/block/drbd/drbd_main.c b/drivers/block/drbd/drbd_main.c index 157d1e4343c..9348f33f624 100644 --- a/drivers/block/drbd/drbd_main.c +++ b/drivers/block/drbd/drbd_main.c @@ -27,7 +27,6 @@ */ #include <linux/module.h> -#include <linux/version.h> #include <linux/drbd.h> #include <asm/uaccess.h> #include <asm/types.h> @@ -151,7 +150,7 @@ wait_queue_head_t drbd_pp_wait; DEFINE_RATELIMIT_STATE(drbd_ratelimit_state, 5 * HZ, 5); -static struct block_device_operations drbd_ops = { +static const struct block_device_operations drbd_ops = { .owner = THIS_MODULE, .open = drbd_open, .release = drbd_release, @@ -3623,7 +3622,7 @@ _drbd_fault_random(struct fault_random_state *rsp) { long refresh; - if (--rsp->count < 0) { + if (!rsp->count--) { get_random_bytes(&refresh, sizeof(refresh)); rsp->state += refresh; rsp->count = FAULT_RANDOM_REFRESH; diff --git a/drivers/block/drbd/drbd_proc.c b/drivers/block/drbd/drbd_proc.c index bdd0b4943b1..df8ad9660d8 100644 --- a/drivers/block/drbd/drbd_proc.c +++ b/drivers/block/drbd/drbd_proc.c @@ -38,7 +38,7 @@ static int drbd_proc_open(struct inode *inode, struct file *file); struct proc_dir_entry *drbd_proc; -struct file_operations drbd_proc_fops = { +const struct file_operations drbd_proc_fops = { .owner = THIS_MODULE, .open = drbd_proc_open, .read = seq_read, diff --git a/drivers/block/drbd/drbd_receiver.c b/drivers/block/drbd/drbd_receiver.c index c548f24f54a..259c1351b15 100644 --- a/drivers/block/drbd/drbd_receiver.c +++ b/drivers/block/drbd/drbd_receiver.c @@ -28,7 +28,6 @@ #include <asm/uaccess.h> #include <net/sock.h> -#include <linux/version.h> #include <linux/drbd.h> #include <linux/fs.h> #include <linux/file.h> diff --git a/drivers/block/drbd/drbd_worker.c b/drivers/block/drbd/drbd_worker.c index ed8796f1112..b453c2bca3b 100644 --- a/drivers/block/drbd/drbd_worker.c +++ b/drivers/block/drbd/drbd_worker.c @@ -24,7 +24,6 @@ */ #include <linux/module.h> -#include <linux/version.h> #include <linux/drbd.h> #include <linux/sched.h> #include <linux/smp_lock.h> @@ -34,7 +33,6 @@ #include <linux/mm_inline.h> #include <linux/slab.h> #include <linux/random.h> -#include <linux/mm.h> #include <linux/string.h> #include <linux/scatterlist.h> diff --git a/drivers/block/mg_disk.c b/drivers/block/mg_disk.c index e0339aaa181..02b2583df7f 100644 --- a/drivers/block/mg_disk.c +++ b/drivers/block/mg_disk.c @@ -860,7 +860,7 @@ static int mg_probe(struct platform_device *plat_dev) err = -EINVAL; goto probe_err_2; } - host->dev_base = ioremap(rsc->start , rsc->end + 1); + host->dev_base = ioremap(rsc->start, resource_size(rsc)); if (!host->dev_base) { printk(KERN_ERR "%s:%d ioremap fail\n", __func__, __LINE__); diff --git a/drivers/char/agp/amd64-agp.c b/drivers/char/agp/amd64-agp.c index 2fb2e6cc322..5aa7a586a7f 100644 --- a/drivers/char/agp/amd64-agp.c +++ b/drivers/char/agp/amd64-agp.c @@ -725,9 +725,14 @@ static struct pci_driver agp_amd64_pci_driver = { int __init agp_amd64_init(void) { int err = 0; + static int done = 0; if (agp_off) return -EINVAL; + + if (done++) + return agp_bridges_found ? 0 : -ENODEV; + err = pci_register_driver(&agp_amd64_pci_driver); if (err < 0) return err; @@ -771,12 +776,8 @@ static void __exit agp_amd64_cleanup(void) pci_unregister_driver(&agp_amd64_pci_driver); } -/* On AMD64 the PCI driver needs to initialize this driver early - for the IOMMU, so it has to be called via a backdoor. */ -#ifndef CONFIG_GART_IOMMU module_init(agp_amd64_init); module_exit(agp_amd64_cleanup); -#endif MODULE_AUTHOR("Dave Jones <davej@redhat.com>, Andi Kleen"); module_param(agp_try_unsupported, bool, 0); diff --git a/drivers/char/hw_random/core.c b/drivers/char/hw_random/core.c index e989f67bb61..3d9c61e5acb 100644 --- a/drivers/char/hw_random/core.c +++ b/drivers/char/hw_random/core.c @@ -158,10 +158,11 @@ static ssize_t rng_dev_read(struct file *filp, char __user *buf, goto out; } } -out_unlock: - mutex_unlock(&rng_mutex); out: return ret ? : err; +out_unlock: + mutex_unlock(&rng_mutex); + goto out; } diff --git a/drivers/char/ipmi/ipmi_si_intf.c b/drivers/char/ipmi/ipmi_si_intf.c index 679cd08b80b..176f1751237 100644 --- a/drivers/char/ipmi/ipmi_si_intf.c +++ b/drivers/char/ipmi/ipmi_si_intf.c @@ -3204,7 +3204,7 @@ static __devinit int init_ipmi_si(void) #ifdef CONFIG_ACPI spmi_find_bmc(); #endif -#ifdef CONFIG_PNP +#ifdef CONFIG_ACPI pnp_register_driver(&ipmi_pnp_driver); #endif @@ -3330,7 +3330,7 @@ static __exit void cleanup_ipmi_si(void) #ifdef CONFIG_PCI pci_unregister_driver(&ipmi_pci_driver); #endif -#ifdef CONFIG_PNP +#ifdef CONFIG_ACPI pnp_unregister_driver(&ipmi_pnp_driver); #endif diff --git a/drivers/char/sonypi.c b/drivers/char/sonypi.c index 0798754a607..bba727c3807 100644 --- a/drivers/char/sonypi.c +++ b/drivers/char/sonypi.c @@ -50,7 +50,6 @@ #include <linux/err.h> #include <linux/kfifo.h> #include <linux/platform_device.h> -#include <linux/smp_lock.h> #include <asm/uaccess.h> #include <asm/io.h> @@ -905,14 +904,13 @@ static int sonypi_misc_release(struct inode *inode, struct file *file) static int sonypi_misc_open(struct inode *inode, struct file *file) { - lock_kernel(); mutex_lock(&sonypi_device.lock); /* Flush input queue on first open */ if (!sonypi_device.open_count) kfifo_reset(&sonypi_device.fifo); sonypi_device.open_count++; mutex_unlock(&sonypi_device.lock); - unlock_kernel(); + return 0; } @@ -955,10 +953,10 @@ static unsigned int sonypi_misc_poll(struct file *file, poll_table *wait) return 0; } -static int sonypi_misc_ioctl(struct inode *ip, struct file *fp, +static long sonypi_misc_ioctl(struct file *fp, unsigned int cmd, unsigned long arg) { - int ret = 0; + long ret = 0; void __user *argp = (void __user *)arg; u8 val8; u16 val16; @@ -1074,7 +1072,8 @@ static const struct file_operations sonypi_misc_fops = { .open = sonypi_misc_open, .release = sonypi_misc_release, .fasync = sonypi_misc_fasync, - .ioctl = sonypi_misc_ioctl, + .unlocked_ioctl = sonypi_misc_ioctl, + .llseek = no_llseek, }; static struct miscdevice sonypi_misc_device = { diff --git a/drivers/char/toshiba.c b/drivers/char/toshiba.c index 663cd15d7c7..f8bc79f6de3 100644 --- a/drivers/char/toshiba.c +++ b/drivers/char/toshiba.c @@ -68,7 +68,7 @@ #include <linux/stat.h> #include <linux/proc_fs.h> #include <linux/seq_file.h> - +#include <linux/smp_lock.h> #include <linux/toshiba.h> #define TOSH_MINOR_DEV 181 @@ -88,13 +88,13 @@ static int tosh_date; static int tosh_sci; static int tosh_fan; -static int tosh_ioctl(struct inode *, struct file *, unsigned int, +static long tosh_ioctl(struct file *, unsigned int, unsigned long); static const struct file_operations tosh_fops = { .owner = THIS_MODULE, - .ioctl = tosh_ioctl, + .unlocked_ioctl = tosh_ioctl, }; static struct miscdevice tosh_device = { @@ -252,8 +252,7 @@ int tosh_smm(SMMRegisters *regs) EXPORT_SYMBOL(tosh_smm); -static int tosh_ioctl(struct inode *ip, struct file *fp, unsigned int cmd, - unsigned long arg) +static long tosh_ioctl(struct file *fp, unsigned int cmd, unsigned long arg) { SMMRegisters regs; SMMRegisters __user *argp = (SMMRegisters __user *)arg; @@ -275,13 +274,16 @@ static int tosh_ioctl(struct inode *ip, struct file *fp, unsigned int cmd, return -EINVAL; /* do we need to emulate the fan ? */ + lock_kernel(); if (tosh_fan==1) { if (((ax==0xf300) || (ax==0xf400)) && (bx==0x0004)) { err = tosh_emulate_fan(®s); + unlock_kernel(); break; } } err = tosh_smm(®s); + unlock_kernel(); break; default: return -EINVAL; diff --git a/drivers/dma/at_hdmac.c b/drivers/dma/at_hdmac.c index f15112569c1..efc1a61ca23 100644 --- a/drivers/dma/at_hdmac.c +++ b/drivers/dma/at_hdmac.c @@ -815,7 +815,7 @@ atc_is_tx_complete(struct dma_chan *chan, dev_vdbg(chan2dev(chan), "is_tx_complete: %d (d%d, u%d)\n", cookie, done ? *done : 0, used ? *used : 0); - spin_lock_bh(atchan->lock); + spin_lock_bh(&atchan->lock); last_complete = atchan->completed_cookie; last_used = chan->cookie; @@ -830,7 +830,7 @@ atc_is_tx_complete(struct dma_chan *chan, ret = dma_async_is_complete(cookie, last_complete, last_used); } - spin_unlock_bh(atchan->lock); + spin_unlock_bh(&atchan->lock); if (done) *done = last_complete; diff --git a/drivers/dma/coh901318.c b/drivers/dma/coh901318.c index 4a99cd94536..b5f2ee0f8e2 100644 --- a/drivers/dma/coh901318.c +++ b/drivers/dma/coh901318.c @@ -1294,8 +1294,8 @@ static int __exit coh901318_remove(struct platform_device *pdev) dma_async_device_unregister(&base->dma_slave); coh901318_pool_destroy(&base->pool); free_irq(platform_get_irq(pdev, 0), base); - kfree(base); iounmap(base->virtbase); + kfree(base); release_mem_region(pdev->resource->start, resource_size(pdev->resource)); return 0; diff --git a/drivers/dma/dw_dmac.c b/drivers/dma/dw_dmac.c index 285bed0fe17..d28369f7afd 100644 --- a/drivers/dma/dw_dmac.c +++ b/drivers/dma/dw_dmac.c @@ -1270,8 +1270,6 @@ static int __init dw_probe(struct platform_device *pdev) goto err_kfree; } - memset(dw, 0, sizeof *dw); - dw->regs = ioremap(io->start, DW_REGLEN); if (!dw->regs) { err = -ENOMEM; diff --git a/drivers/dma/ioat/dma.c b/drivers/dma/ioat/dma.c index c524d36d3c2..dcc4ab78b32 100644 --- a/drivers/dma/ioat/dma.c +++ b/drivers/dma/ioat/dma.c @@ -1032,7 +1032,7 @@ int __devinit ioat_probe(struct ioatdma_device *device) dma->dev = &pdev->dev; if (!dma->chancnt) { - dev_err(dev, "zero channels detected\n"); + dev_err(dev, "channel enumeration error\n"); goto err_setup_interrupts; } diff --git a/drivers/dma/ioat/dma.h b/drivers/dma/ioat/dma.h index 45edde99648..bbc3e78ef33 100644 --- a/drivers/dma/ioat/dma.h +++ b/drivers/dma/ioat/dma.h @@ -60,6 +60,7 @@ * @dca: direct cache access context * @intr_quirk: interrupt setup quirk (for ioat_v1 devices) * @enumerate_channels: hw version specific channel enumeration + * @reset_hw: hw version specific channel (re)initialization * @cleanup_tasklet: select between the v2 and v3 cleanup routines * @timer_fn: select between the v2 and v3 timer watchdog routines * @self_test: hardware version specific self test for each supported op type @@ -78,6 +79,7 @@ struct ioatdma_device { struct dca_provider *dca; void (*intr_quirk)(struct ioatdma_device *device); int (*enumerate_channels)(struct ioatdma_device *device); + int (*reset_hw)(struct ioat_chan_common *chan); void (*cleanup_tasklet)(unsigned long data); void (*timer_fn)(unsigned long data); int (*self_test)(struct ioatdma_device *device); @@ -264,6 +266,22 @@ static inline void ioat_suspend(struct ioat_chan_common *chan) writeb(IOAT_CHANCMD_SUSPEND, chan->reg_base + IOAT_CHANCMD_OFFSET(ver)); } +static inline void ioat_reset(struct ioat_chan_common *chan) +{ + u8 ver = chan->device->version; + + writeb(IOAT_CHANCMD_RESET, chan->reg_base + IOAT_CHANCMD_OFFSET(ver)); +} + +static inline bool ioat_reset_pending(struct ioat_chan_common *chan) +{ + u8 ver = chan->device->version; + u8 cmd; + + cmd = readb(chan->reg_base + IOAT_CHANCMD_OFFSET(ver)); + return (cmd & IOAT_CHANCMD_RESET) == IOAT_CHANCMD_RESET; +} + static inline void ioat_set_chainaddr(struct ioat_dma_chan *ioat, u64 addr) { struct ioat_chan_common *chan = &ioat->base; diff --git a/drivers/dma/ioat/dma_v2.c b/drivers/dma/ioat/dma_v2.c index 8f1f7f05dea..5f7a500e18d 100644 --- a/drivers/dma/ioat/dma_v2.c +++ b/drivers/dma/ioat/dma_v2.c @@ -239,20 +239,50 @@ void __ioat2_restart_chan(struct ioat2_dma_chan *ioat) __ioat2_start_null_desc(ioat); } -static void ioat2_restart_channel(struct ioat2_dma_chan *ioat) +int ioat2_quiesce(struct ioat_chan_common *chan, unsigned long tmo) { - struct ioat_chan_common *chan = &ioat->base; - unsigned long phys_complete; + unsigned long end = jiffies + tmo; + int err = 0; u32 status; status = ioat_chansts(chan); if (is_ioat_active(status) || is_ioat_idle(status)) ioat_suspend(chan); while (is_ioat_active(status) || is_ioat_idle(status)) { + if (end && time_after(jiffies, end)) { + err = -ETIMEDOUT; + break; + } status = ioat_chansts(chan); cpu_relax(); } + return err; +} + +int ioat2_reset_sync(struct ioat_chan_common *chan, unsigned long tmo) +{ + unsigned long end = jiffies + tmo; + int err = 0; + + ioat_reset(chan); + while (ioat_reset_pending(chan)) { + if (end && time_after(jiffies, end)) { + err = -ETIMEDOUT; + break; + } + cpu_relax(); + } + + return err; +} + +static void ioat2_restart_channel(struct ioat2_dma_chan *ioat) +{ + struct ioat_chan_common *chan = &ioat->base; + unsigned long phys_complete; + + ioat2_quiesce(chan, 0); if (ioat_cleanup_preamble(chan, &phys_complete)) __cleanup(ioat, phys_complete); @@ -318,6 +348,19 @@ void ioat2_timer_event(unsigned long data) spin_unlock_bh(&chan->cleanup_lock); } +static int ioat2_reset_hw(struct ioat_chan_common *chan) +{ + /* throw away whatever the channel was doing and get it initialized */ + u32 chanerr; + + ioat2_quiesce(chan, msecs_to_jiffies(100)); + + chanerr = readl(chan->reg_base + IOAT_CHANERR_OFFSET); + writel(chanerr, chan->reg_base + IOAT_CHANERR_OFFSET); + + return ioat2_reset_sync(chan, msecs_to_jiffies(200)); +} + /** * ioat2_enumerate_channels - find and initialize the device's channels * @device: the device to be enumerated @@ -360,6 +403,10 @@ int ioat2_enumerate_channels(struct ioatdma_device *device) (unsigned long) ioat); ioat->xfercap_log = xfercap_log; spin_lock_init(&ioat->ring_lock); + if (device->reset_hw(&ioat->base)) { + i = 0; + break; + } } dma->chancnt = i; return i; @@ -467,7 +514,6 @@ int ioat2_alloc_chan_resources(struct dma_chan *c) struct ioat2_dma_chan *ioat = to_ioat2_chan(c); struct ioat_chan_common *chan = &ioat->base; struct ioat_ring_ent **ring; - u32 chanerr; int order; /* have we already been set up? */ @@ -477,12 +523,6 @@ int ioat2_alloc_chan_resources(struct dma_chan *c) /* Setup register to interrupt and write completion status on error */ writew(IOAT_CHANCTRL_RUN, chan->reg_base + IOAT_CHANCTRL_OFFSET); - chanerr = readl(chan->reg_base + IOAT_CHANERR_OFFSET); - if (chanerr) { - dev_err(to_dev(chan), "CHANERR = %x, clearing\n", chanerr); - writel(chanerr, chan->reg_base + IOAT_CHANERR_OFFSET); - } - /* allocate a completion writeback area */ /* doing 2 32bit writes to mmio since 1 64b write doesn't work */ chan->completion = pci_pool_alloc(chan->device->completion_pool, @@ -746,13 +786,7 @@ void ioat2_free_chan_resources(struct dma_chan *c) tasklet_disable(&chan->cleanup_task); del_timer_sync(&chan->timer); device->cleanup_tasklet((unsigned long) ioat); - - /* Delay 100ms after reset to allow internal DMA logic to quiesce - * before removing DMA descriptor resources. - */ - writeb(IOAT_CHANCMD_RESET, - chan->reg_base + IOAT_CHANCMD_OFFSET(chan->device->version)); - mdelay(100); + device->reset_hw(chan); spin_lock_bh(&ioat->ring_lock); descs = ioat2_ring_space(ioat); @@ -839,6 +873,7 @@ int __devinit ioat2_dma_probe(struct ioatdma_device *device, int dca) int err; device->enumerate_channels = ioat2_enumerate_channels; + device->reset_hw = ioat2_reset_hw; device->cleanup_tasklet = ioat2_cleanup_tasklet; device->timer_fn = ioat2_timer_event; device->self_test = ioat_dma_self_test; diff --git a/drivers/dma/ioat/dma_v2.h b/drivers/dma/ioat/dma_v2.h index 1d849ef74d5..3afad8da43c 100644 --- a/drivers/dma/ioat/dma_v2.h +++ b/drivers/dma/ioat/dma_v2.h @@ -185,6 +185,8 @@ bool reshape_ring(struct ioat2_dma_chan *ioat, int order); void __ioat2_issue_pending(struct ioat2_dma_chan *ioat); void ioat2_cleanup_tasklet(unsigned long data); void ioat2_timer_event(unsigned long data); +int ioat2_quiesce(struct ioat_chan_common *chan, unsigned long tmo); +int ioat2_reset_sync(struct ioat_chan_common *chan, unsigned long tmo); extern struct kobj_type ioat2_ktype; extern struct kmem_cache *ioat2_cache; #endif /* IOATDMA_V2_H */ diff --git a/drivers/dma/ioat/dma_v3.c b/drivers/dma/ioat/dma_v3.c index 42f6f10fb0c..9908c9e94b2 100644 --- a/drivers/dma/ioat/dma_v3.c +++ b/drivers/dma/ioat/dma_v3.c @@ -650,9 +650,11 @@ __ioat3_prep_pq_lock(struct dma_chan *c, enum sum_check_flags *result, num_descs = ioat2_xferlen_to_descs(ioat, len); /* we need 2x the number of descriptors to cover greater than 3 - * sources + * sources (we need 1 extra source in the q-only continuation + * case and 3 extra sources in the p+q continuation case. */ - if (src_cnt > 3 || flags & DMA_PREP_CONTINUE) { + if (src_cnt + dmaf_p_disabled_continue(flags) > 3 || + (dmaf_continue(flags) && !dmaf_p_disabled_continue(flags))) { with_ext = 1; num_descs *= 2; } else @@ -1128,6 +1130,45 @@ static int __devinit ioat3_dma_self_test(struct ioatdma_device *device) return 0; } +static int ioat3_reset_hw(struct ioat_chan_common *chan) +{ + /* throw away whatever the channel was doing and get it + * initialized, with ioat3 specific workarounds + */ + struct ioatdma_device *device = chan->device; + struct pci_dev *pdev = device->pdev; + u32 chanerr; + u16 dev_id; + int err; + + ioat2_quiesce(chan, msecs_to_jiffies(100)); + + chanerr = readl(chan->reg_base + IOAT_CHANERR_OFFSET); + writel(chanerr, chan->reg_base + IOAT_CHANERR_OFFSET); + + /* -= IOAT ver.3 workarounds =- */ + /* Write CHANERRMSK_INT with 3E07h to mask out the errors + * that can cause stability issues for IOAT ver.3, and clear any + * pending errors + */ + pci_write_config_dword(pdev, IOAT_PCI_CHANERRMASK_INT_OFFSET, 0x3e07); + err = pci_read_config_dword(pdev, IOAT_PCI_CHANERR_INT_OFFSET, &chanerr); + if (err) { + dev_err(&pdev->dev, "channel error register unreachable\n"); + return err; + } + pci_write_config_dword(pdev, IOAT_PCI_CHANERR_INT_OFFSET, chanerr); + + /* Clear DMAUNCERRSTS Cfg-Reg Parity Error status bit + * (workaround for spurious config parity error after restart) + */ + pci_read_config_word(pdev, IOAT_PCI_DEVICE_ID_OFFSET, &dev_id); + if (dev_id == PCI_DEVICE_ID_INTEL_IOAT_TBG0) + pci_write_config_dword(pdev, IOAT_PCI_DMAUNCERRSTS_OFFSET, 0x10); + + return ioat2_reset_sync(chan, msecs_to_jiffies(200)); +} + int __devinit ioat3_dma_probe(struct ioatdma_device *device, int dca) { struct pci_dev *pdev = device->pdev; @@ -1137,10 +1178,10 @@ int __devinit ioat3_dma_probe(struct ioatdma_device *device, int dca) struct ioat_chan_common *chan; bool is_raid_device = false; int err; - u16 dev_id; u32 cap; device->enumerate_channels = ioat2_enumerate_channels; + device->reset_hw = ioat3_reset_hw; device->self_test = ioat3_dma_self_test; dma = &device->common; dma->device_prep_dma_memcpy = ioat2_dma_prep_memcpy_lock; @@ -1216,19 +1257,6 @@ int __devinit ioat3_dma_probe(struct ioatdma_device *device, int dca) dma->device_prep_dma_xor_val = NULL; #endif - /* -= IOAT ver.3 workarounds =- */ - /* Write CHANERRMSK_INT with 3E07h to mask out the errors - * that can cause stability issues for IOAT ver.3 - */ - pci_write_config_dword(pdev, IOAT_PCI_CHANERRMASK_INT_OFFSET, 0x3e07); - - /* Clear DMAUNCERRSTS Cfg-Reg Parity Error status bit - * (workaround for spurious config parity error after restart) - */ - pci_read_config_word(pdev, IOAT_PCI_DEVICE_ID_OFFSET, &dev_id); - if (dev_id == PCI_DEVICE_ID_INTEL_IOAT_TBG0) - pci_write_config_dword(pdev, IOAT_PCI_DMAUNCERRSTS_OFFSET, 0x10); - err = ioat_probe(device); if (err) return err; diff --git a/drivers/dma/ioat/registers.h b/drivers/dma/ioat/registers.h index f015ec19670..e8ae63baf58 100644 --- a/drivers/dma/ioat/registers.h +++ b/drivers/dma/ioat/registers.h @@ -27,6 +27,7 @@ #define IOAT_PCI_DEVICE_ID_OFFSET 0x02 #define IOAT_PCI_DMAUNCERRSTS_OFFSET 0x148 +#define IOAT_PCI_CHANERR_INT_OFFSET 0x180 #define IOAT_PCI_CHANERRMASK_INT_OFFSET 0x184 /* MMIO Device Registers */ diff --git a/drivers/dma/shdma.c b/drivers/dma/shdma.c index 2e4a54c8afe..d10cc899c46 100644 --- a/drivers/dma/shdma.c +++ b/drivers/dma/shdma.c @@ -23,16 +23,19 @@ #include <linux/dmaengine.h> #include <linux/delay.h> #include <linux/dma-mapping.h> -#include <linux/dmapool.h> #include <linux/platform_device.h> #include <cpu/dma.h> #include <asm/dma-sh.h> #include "shdma.h" /* DMA descriptor control */ -#define DESC_LAST (-1) -#define DESC_COMP (1) -#define DESC_NCOMP (0) +enum sh_dmae_desc_status { + DESC_IDLE, + DESC_PREPARED, + DESC_SUBMITTED, + DESC_COMPLETED, /* completed, have to call callback */ + DESC_WAITING, /* callback called, waiting for ack / re-submit */ +}; #define NR_DESCS_PER_CHANNEL 32 /* @@ -45,6 +48,8 @@ */ #define RS_DEFAULT (RS_DUAL) +static void sh_dmae_chan_ld_cleanup(struct sh_dmae_chan *sh_chan, bool all); + #define SH_DMAC_CHAN_BASE(id) (dma_base_addr[id]) static void sh_dmae_writel(struct sh_dmae_chan *sh_dc, u32 data, u32 reg) { @@ -106,11 +111,11 @@ static inline unsigned int calc_xmit_shift(struct sh_dmae_chan *sh_chan) return ts_shift[(chcr & CHCR_TS_MASK) >> CHCR_TS_SHIFT]; } -static void dmae_set_reg(struct sh_dmae_chan *sh_chan, struct sh_dmae_regs hw) +static void dmae_set_reg(struct sh_dmae_chan *sh_chan, struct sh_dmae_regs *hw) { - sh_dmae_writel(sh_chan, hw.sar, SAR); - sh_dmae_writel(sh_chan, hw.dar, DAR); - sh_dmae_writel(sh_chan, hw.tcr >> calc_xmit_shift(sh_chan), TCR); + sh_dmae_writel(sh_chan, hw->sar, SAR); + sh_dmae_writel(sh_chan, hw->dar, DAR); + sh_dmae_writel(sh_chan, hw->tcr >> calc_xmit_shift(sh_chan), TCR); } static void dmae_start(struct sh_dmae_chan *sh_chan) @@ -184,8 +189,9 @@ static int dmae_set_dmars(struct sh_dmae_chan *sh_chan, u16 val) static dma_cookie_t sh_dmae_tx_submit(struct dma_async_tx_descriptor *tx) { - struct sh_desc *desc = tx_to_sh_desc(tx); + struct sh_desc *desc = tx_to_sh_desc(tx), *chunk, *last = desc, *c; struct sh_dmae_chan *sh_chan = to_sh_chan(tx->chan); + dma_async_tx_callback callback = tx->callback; dma_cookie_t cookie; spin_lock_bh(&sh_chan->desc_lock); @@ -195,45 +201,53 @@ static dma_cookie_t sh_dmae_tx_submit(struct dma_async_tx_descriptor *tx) if (cookie < 0) cookie = 1; - /* If desc only in the case of 1 */ - if (desc->async_tx.cookie != -EBUSY) - desc->async_tx.cookie = cookie; - sh_chan->common.cookie = desc->async_tx.cookie; + sh_chan->common.cookie = cookie; + tx->cookie = cookie; + + /* Mark all chunks of this descriptor as submitted, move to the queue */ + list_for_each_entry_safe(chunk, c, desc->node.prev, node) { + /* + * All chunks are on the global ld_free, so, we have to find + * the end of the chain ourselves + */ + if (chunk != desc && (chunk->mark == DESC_IDLE || + chunk->async_tx.cookie > 0 || + chunk->async_tx.cookie == -EBUSY || + &chunk->node == &sh_chan->ld_free)) + break; + chunk->mark = DESC_SUBMITTED; + /* Callback goes to the last chunk */ + chunk->async_tx.callback = NULL; + chunk->cookie = cookie; + list_move_tail(&chunk->node, &sh_chan->ld_queue); + last = chunk; + } + + last->async_tx.callback = callback; + last->async_tx.callback_param = tx->callback_param; - list_splice_init(&desc->tx_list, sh_chan->ld_queue.prev); + dev_dbg(sh_chan->dev, "submit #%d@%p on %d: %x[%d] -> %x\n", + tx->cookie, &last->async_tx, sh_chan->id, + desc->hw.sar, desc->hw.tcr, desc->hw.dar); spin_unlock_bh(&sh_chan->desc_lock); return cookie; } +/* Called with desc_lock held */ static struct sh_desc *sh_dmae_get_desc(struct sh_dmae_chan *sh_chan) { - struct sh_desc *desc, *_desc, *ret = NULL; + struct sh_desc *desc; - spin_lock_bh(&sh_chan->desc_lock); - list_for_each_entry_safe(desc, _desc, &sh_chan->ld_free, node) { - if (async_tx_test_ack(&desc->async_tx)) { + list_for_each_entry(desc, &sh_chan->ld_free, node) + if (desc->mark != DESC_PREPARED) { + BUG_ON(desc->mark != DESC_IDLE); list_del(&desc->node); - ret = desc; - break; + return desc; } - } - spin_unlock_bh(&sh_chan->desc_lock); - - return ret; -} - -static void sh_dmae_put_desc(struct sh_dmae_chan *sh_chan, struct sh_desc *desc) -{ - if (desc) { - spin_lock_bh(&sh_chan->desc_lock); - - list_splice_init(&desc->tx_list, &sh_chan->ld_free); - list_add(&desc->node, &sh_chan->ld_free); - spin_unlock_bh(&sh_chan->desc_lock); - } + return NULL; } static int sh_dmae_alloc_chan_resources(struct dma_chan *chan) @@ -252,11 +266,10 @@ static int sh_dmae_alloc_chan_resources(struct dma_chan *chan) dma_async_tx_descriptor_init(&desc->async_tx, &sh_chan->common); desc->async_tx.tx_submit = sh_dmae_tx_submit; - desc->async_tx.flags = DMA_CTRL_ACK; - INIT_LIST_HEAD(&desc->tx_list); - sh_dmae_put_desc(sh_chan, desc); + desc->mark = DESC_IDLE; spin_lock_bh(&sh_chan->desc_lock); + list_add(&desc->node, &sh_chan->ld_free); sh_chan->descs_allocated++; } spin_unlock_bh(&sh_chan->desc_lock); @@ -273,7 +286,10 @@ static void sh_dmae_free_chan_resources(struct dma_chan *chan) struct sh_desc *desc, *_desc; LIST_HEAD(list); - BUG_ON(!list_empty(&sh_chan->ld_queue)); + /* Prepared and not submitted descriptors can still be on the queue */ + if (!list_empty(&sh_chan->ld_queue)) + sh_dmae_chan_ld_cleanup(sh_chan, true); + spin_lock_bh(&sh_chan->desc_lock); list_splice_init(&sh_chan->ld_free, &list); @@ -292,6 +308,8 @@ static struct dma_async_tx_descriptor *sh_dmae_prep_memcpy( struct sh_dmae_chan *sh_chan; struct sh_desc *first = NULL, *prev = NULL, *new; size_t copy_size; + LIST_HEAD(tx_list); + int chunks = (len + SH_DMA_TCR_MAX) / (SH_DMA_TCR_MAX + 1); if (!chan) return NULL; @@ -301,108 +319,189 @@ static struct dma_async_tx_descriptor *sh_dmae_prep_memcpy( sh_chan = to_sh_chan(chan); + /* Have to lock the whole loop to protect against concurrent release */ + spin_lock_bh(&sh_chan->desc_lock); + + /* + * Chaining: + * first descriptor is what user is dealing with in all API calls, its + * cookie is at first set to -EBUSY, at tx-submit to a positive + * number + * if more than one chunk is needed further chunks have cookie = -EINVAL + * the last chunk, if not equal to the first, has cookie = -ENOSPC + * all chunks are linked onto the tx_list head with their .node heads + * only during this function, then they are immediately spliced + * back onto the free list in form of a chain + */ do { - /* Allocate the link descriptor from DMA pool */ + /* Allocate the link descriptor from the free list */ new = sh_dmae_get_desc(sh_chan); if (!new) { dev_err(sh_chan->dev, "No free memory for link descriptor\n"); - goto err_get_desc; + list_for_each_entry(new, &tx_list, node) + new->mark = DESC_IDLE; + list_splice(&tx_list, &sh_chan->ld_free); + spin_unlock_bh(&sh_chan->desc_lock); + return NULL; } - copy_size = min(len, (size_t)SH_DMA_TCR_MAX); + copy_size = min(len, (size_t)SH_DMA_TCR_MAX + 1); new->hw.sar = dma_src; new->hw.dar = dma_dest; new->hw.tcr = copy_size; - if (!first) + if (!first) { + /* First desc */ + new->async_tx.cookie = -EBUSY; first = new; + } else { + /* Other desc - invisible to the user */ + new->async_tx.cookie = -EINVAL; + } - new->mark = DESC_NCOMP; - async_tx_ack(&new->async_tx); + dev_dbg(sh_chan->dev, + "chaining %u of %u with %p, dst %x, cookie %d\n", + copy_size, len, &new->async_tx, dma_dest, + new->async_tx.cookie); + + new->mark = DESC_PREPARED; + new->async_tx.flags = flags; + new->chunks = chunks--; prev = new; len -= copy_size; dma_src += copy_size; dma_dest += copy_size; /* Insert the link descriptor to the LD ring */ - list_add_tail(&new->node, &first->tx_list); + list_add_tail(&new->node, &tx_list); } while (len); - new->async_tx.flags = flags; /* client is in control of this ack */ - new->async_tx.cookie = -EBUSY; /* Last desc */ + if (new != first) + new->async_tx.cookie = -ENOSPC; - return &first->async_tx; + /* Put them back on the free list, so, they don't get lost */ + list_splice_tail(&tx_list, &sh_chan->ld_free); -err_get_desc: - sh_dmae_put_desc(sh_chan, first); - return NULL; + spin_unlock_bh(&sh_chan->desc_lock); + return &first->async_tx; } -/* - * sh_chan_ld_cleanup - Clean up link descriptors - * - * This function clean up the ld_queue of DMA channel. - */ -static void sh_dmae_chan_ld_cleanup(struct sh_dmae_chan *sh_chan) +static dma_async_tx_callback __ld_cleanup(struct sh_dmae_chan *sh_chan, bool all) { struct sh_desc *desc, *_desc; + /* Is the "exposed" head of a chain acked? */ + bool head_acked = false; + dma_cookie_t cookie = 0; + dma_async_tx_callback callback = NULL; + void *param = NULL; spin_lock_bh(&sh_chan->desc_lock); list_for_each_entry_safe(desc, _desc, &sh_chan->ld_queue, node) { - dma_async_tx_callback callback; - void *callback_param; - - /* non send data */ - if (desc->mark == DESC_NCOMP) + struct dma_async_tx_descriptor *tx = &desc->async_tx; + + BUG_ON(tx->cookie > 0 && tx->cookie != desc->cookie); + BUG_ON(desc->mark != DESC_SUBMITTED && + desc->mark != DESC_COMPLETED && + desc->mark != DESC_WAITING); + + /* + * queue is ordered, and we use this loop to (1) clean up all + * completed descriptors, and to (2) update descriptor flags of + * any chunks in a (partially) completed chain + */ + if (!all && desc->mark == DESC_SUBMITTED && + desc->cookie != cookie) break; - /* send data sesc */ - callback = desc->async_tx.callback; - callback_param = desc->async_tx.callback_param; + if (tx->cookie > 0) + cookie = tx->cookie; - /* Remove from ld_queue list */ - list_splice_init(&desc->tx_list, &sh_chan->ld_free); + if (desc->mark == DESC_COMPLETED && desc->chunks == 1) { + BUG_ON(sh_chan->completed_cookie != desc->cookie - 1); + sh_chan->completed_cookie = desc->cookie; + } - dev_dbg(sh_chan->dev, "link descriptor %p will be recycle.\n", - desc); + /* Call callback on the last chunk */ + if (desc->mark == DESC_COMPLETED && tx->callback) { + desc->mark = DESC_WAITING; + callback = tx->callback; + param = tx->callback_param; + dev_dbg(sh_chan->dev, "descriptor #%d@%p on %d callback\n", + tx->cookie, tx, sh_chan->id); + BUG_ON(desc->chunks != 1); + break; + } - list_move(&desc->node, &sh_chan->ld_free); - /* Run the link descriptor callback function */ - if (callback) { - spin_unlock_bh(&sh_chan->desc_lock); - dev_dbg(sh_chan->dev, "link descriptor %p callback\n", - desc); - callback(callback_param); - spin_lock_bh(&sh_chan->desc_lock); + if (tx->cookie > 0 || tx->cookie == -EBUSY) { + if (desc->mark == DESC_COMPLETED) { + BUG_ON(tx->cookie < 0); + desc->mark = DESC_WAITING; + } + head_acked = async_tx_test_ack(tx); + } else { + switch (desc->mark) { + case DESC_COMPLETED: + desc->mark = DESC_WAITING; + /* Fall through */ + case DESC_WAITING: + if (head_acked) + async_tx_ack(&desc->async_tx); + } + } + + dev_dbg(sh_chan->dev, "descriptor %p #%d completed.\n", + tx, tx->cookie); + + if (((desc->mark == DESC_COMPLETED || + desc->mark == DESC_WAITING) && + async_tx_test_ack(&desc->async_tx)) || all) { + /* Remove from ld_queue list */ + desc->mark = DESC_IDLE; + list_move(&desc->node, &sh_chan->ld_free); } } spin_unlock_bh(&sh_chan->desc_lock); + + if (callback) + callback(param); + + return callback; +} + +/* + * sh_chan_ld_cleanup - Clean up link descriptors + * + * This function cleans up the ld_queue of DMA channel. + */ +static void sh_dmae_chan_ld_cleanup(struct sh_dmae_chan *sh_chan, bool all) +{ + while (__ld_cleanup(sh_chan, all)) + ; } static void sh_chan_xfer_ld_queue(struct sh_dmae_chan *sh_chan) { - struct list_head *ld_node; - struct sh_dmae_regs hw; + struct sh_desc *sd; + spin_lock_bh(&sh_chan->desc_lock); /* DMA work check */ - if (dmae_is_busy(sh_chan)) + if (dmae_is_busy(sh_chan)) { + spin_unlock_bh(&sh_chan->desc_lock); return; + } /* Find the first un-transfer desciptor */ - for (ld_node = sh_chan->ld_queue.next; - (ld_node != &sh_chan->ld_queue) - && (to_sh_desc(ld_node)->mark == DESC_COMP); - ld_node = ld_node->next) - cpu_relax(); - - if (ld_node != &sh_chan->ld_queue) { - /* Get the ld start address from ld_queue */ - hw = to_sh_desc(ld_node)->hw; - dmae_set_reg(sh_chan, hw); - dmae_start(sh_chan); - } + list_for_each_entry(sd, &sh_chan->ld_queue, node) + if (sd->mark == DESC_SUBMITTED) { + /* Get the ld start address from ld_queue */ + dmae_set_reg(sh_chan, &sd->hw); + dmae_start(sh_chan); + break; + } + + spin_unlock_bh(&sh_chan->desc_lock); } static void sh_dmae_memcpy_issue_pending(struct dma_chan *chan) @@ -420,12 +519,11 @@ static enum dma_status sh_dmae_is_complete(struct dma_chan *chan, dma_cookie_t last_used; dma_cookie_t last_complete; - sh_dmae_chan_ld_cleanup(sh_chan); + sh_dmae_chan_ld_cleanup(sh_chan, false); last_used = chan->cookie; last_complete = sh_chan->completed_cookie; - if (last_complete == -EBUSY) - last_complete = last_used; + BUG_ON(last_complete < 0); if (done) *done = last_complete; @@ -480,11 +578,13 @@ static irqreturn_t sh_dmae_err(int irq, void *data) err = sh_dmae_rst(0); if (err) return err; +#ifdef SH_DMAC_BASE1 if (shdev->pdata.mode & SHDMA_DMAOR1) { err = sh_dmae_rst(1); if (err) return err; } +#endif disable_irq(irq); return IRQ_HANDLED; } @@ -494,35 +594,25 @@ static irqreturn_t sh_dmae_err(int irq, void *data) static void dmae_do_tasklet(unsigned long data) { struct sh_dmae_chan *sh_chan = (struct sh_dmae_chan *)data; - struct sh_desc *desc, *_desc, *cur_desc = NULL; + struct sh_desc *desc; u32 sar_buf = sh_dmae_readl(sh_chan, SAR); - list_for_each_entry_safe(desc, _desc, - &sh_chan->ld_queue, node) { - if ((desc->hw.sar + desc->hw.tcr) == sar_buf) { - cur_desc = desc; + spin_lock(&sh_chan->desc_lock); + list_for_each_entry(desc, &sh_chan->ld_queue, node) { + if ((desc->hw.sar + desc->hw.tcr) == sar_buf && + desc->mark == DESC_SUBMITTED) { + dev_dbg(sh_chan->dev, "done #%d@%p dst %u\n", + desc->async_tx.cookie, &desc->async_tx, + desc->hw.dar); + desc->mark = DESC_COMPLETED; break; } } + spin_unlock(&sh_chan->desc_lock); - if (cur_desc) { - switch (cur_desc->async_tx.cookie) { - case 0: /* other desc data */ - break; - case -EBUSY: /* last desc */ - sh_chan->completed_cookie = - cur_desc->async_tx.cookie; - break; - default: /* first desc ( 0 < )*/ - sh_chan->completed_cookie = - cur_desc->async_tx.cookie - 1; - break; - } - cur_desc->mark = DESC_COMP; - } /* Next desc */ sh_chan_xfer_ld_queue(sh_chan); - sh_dmae_chan_ld_cleanup(sh_chan); + sh_dmae_chan_ld_cleanup(sh_chan, false); } static unsigned int get_dmae_irq(unsigned int id) diff --git a/drivers/dma/shdma.h b/drivers/dma/shdma.h index 60b81e529b4..108f1cffb6f 100644 --- a/drivers/dma/shdma.h +++ b/drivers/dma/shdma.h @@ -13,9 +13,9 @@ #ifndef __DMA_SHDMA_H #define __DMA_SHDMA_H -#include <linux/device.h> -#include <linux/dmapool.h> #include <linux/dmaengine.h> +#include <linux/interrupt.h> +#include <linux/list.h> #define SH_DMA_TCR_MAX 0x00FFFFFF /* 16MB */ @@ -26,13 +26,16 @@ struct sh_dmae_regs { }; struct sh_desc { - struct list_head tx_list; struct sh_dmae_regs hw; struct list_head node; struct dma_async_tx_descriptor async_tx; + dma_cookie_t cookie; + int chunks; int mark; }; +struct device; + struct sh_dmae_chan { dma_cookie_t completed_cookie; /* The maximum cookie completed */ spinlock_t desc_lock; /* Descriptor operation lock */ diff --git a/drivers/firewire/Kconfig b/drivers/firewire/Kconfig index 13efcd36207..a9371b36a9b 100644 --- a/drivers/firewire/Kconfig +++ b/drivers/firewire/Kconfig @@ -1,5 +1,10 @@ +menu "IEEE 1394 (FireWire) support" + depends on PCI || BROKEN + # firewire-core does not depend on PCI but is + # not useful without PCI controller driver + comment "You can enable one or both FireWire driver stacks." -comment "See the help texts for more information." +comment "The newer stack is recommended." config FIREWIRE tristate "FireWire driver stack" @@ -15,16 +20,6 @@ config FIREWIRE To compile this driver as a module, say M here: the module will be called firewire-core. - This module functionally replaces ieee1394, raw1394, and video1394. - To access it from application programs, you generally need at least - libraw1394 v2. IIDC/DCAM applications need libdc1394 v2. - No libraries are required to access storage devices through the - firewire-sbp2 driver. - - NOTE: - FireWire audio devices currently require the old drivers (ieee1394, - ohci1394, raw1394). - config FIREWIRE_OHCI tristate "OHCI-1394 controllers" depends on PCI && FIREWIRE @@ -34,22 +29,7 @@ config FIREWIRE_OHCI is the only chipset in use, so say Y here. To compile this driver as a module, say M here: The module will be - called firewire-ohci. It replaces ohci1394 of the classic IEEE 1394 - stack. - - NOTE: - If you want to install firewire-ohci and ohci1394 together, you - should configure them only as modules and blacklist the driver(s) - which you don't want to have auto-loaded. Add either - - blacklist firewire-ohci - or - blacklist ohci1394 - blacklist video1394 - blacklist dv1394 - - to /etc/modprobe.conf or /etc/modprobe.d/* and update modprobe.conf - depending on your distribution. + called firewire-ohci. config FIREWIRE_OHCI_DEBUG bool @@ -66,8 +46,7 @@ config FIREWIRE_SBP2 like scanners. To compile this driver as a module, say M here: The module will be - called firewire-sbp2. It replaces sbp2 of the classic IEEE 1394 - stack. + called firewire-sbp2. You should also enable support for disks, CD-ROMs, etc. in the SCSI configuration section. @@ -83,5 +62,8 @@ config FIREWIRE_NET NOTE, this driver is not stable yet! To compile this driver as a module, say M here: The module will be - called firewire-net. It replaces eth1394 of the classic IEEE 1394 - stack. + called firewire-net. + +source "drivers/ieee1394/Kconfig" + +endmenu diff --git a/drivers/firewire/core-cdev.c b/drivers/firewire/core-cdev.c index 231e6ee5ba4..e6d63849e78 100644 --- a/drivers/firewire/core-cdev.c +++ b/drivers/firewire/core-cdev.c @@ -601,8 +601,9 @@ static void release_request(struct client *client, struct inbound_transaction_resource *r = container_of(resource, struct inbound_transaction_resource, resource); - fw_send_response(client->device->card, r->request, - RCODE_CONFLICT_ERROR); + if (r->request) + fw_send_response(client->device->card, r->request, + RCODE_CONFLICT_ERROR); kfree(r); } @@ -645,7 +646,8 @@ static void handle_request(struct fw_card *card, struct fw_request *request, failed: kfree(r); kfree(e); - fw_send_response(card, request, RCODE_CONFLICT_ERROR); + if (request) + fw_send_response(card, request, RCODE_CONFLICT_ERROR); } static void release_address_handler(struct client *client, @@ -715,15 +717,18 @@ static int ioctl_send_response(struct client *client, void *buffer) r = container_of(resource, struct inbound_transaction_resource, resource); - if (request->length < r->length) - r->length = request->length; - - if (copy_from_user(r->data, u64_to_uptr(request->data), r->length)) { - ret = -EFAULT; - goto out; + if (r->request) { + if (request->length < r->length) + r->length = request->length; + if (copy_from_user(r->data, u64_to_uptr(request->data), + r->length)) { + ret = -EFAULT; + kfree(r->request); + goto out; + } + fw_send_response(client->device->card, r->request, + request->rcode); } - - fw_send_response(client->device->card, r->request, request->rcode); out: kfree(r); diff --git a/drivers/firewire/core-transaction.c b/drivers/firewire/core-transaction.c index 842739df23e..495849eb13c 100644 --- a/drivers/firewire/core-transaction.c +++ b/drivers/firewire/core-transaction.c @@ -432,14 +432,20 @@ static struct fw_address_handler *lookup_overlapping_address_handler( return NULL; } +static bool is_enclosing_handler(struct fw_address_handler *handler, + unsigned long long offset, size_t length) +{ + return handler->offset <= offset && + offset + length <= handler->offset + handler->length; +} + static struct fw_address_handler *lookup_enclosing_address_handler( struct list_head *list, unsigned long long offset, size_t length) { struct fw_address_handler *handler; list_for_each_entry(handler, list, link) { - if (handler->offset <= offset && - offset + length <= handler->offset + handler->length) + if (is_enclosing_handler(handler, offset, length)) return handler; } @@ -465,6 +471,12 @@ const struct fw_address_region fw_unit_space_region = { .start = 0xfffff0000900ULL, .end = 0x1000000000000ULL, }; #endif /* 0 */ +static bool is_in_fcp_region(u64 offset, size_t length) +{ + return offset >= (CSR_REGISTER_BASE | CSR_FCP_COMMAND) && + offset + length <= (CSR_REGISTER_BASE | CSR_FCP_END); +} + /** * fw_core_add_address_handler - register for incoming requests * @handler: callback @@ -477,8 +489,11 @@ const struct fw_address_region fw_unit_space_region = * give the details of the particular request. * * Return value: 0 on success, non-zero otherwise. + * * The start offset of the handler's address region is determined by * fw_core_add_address_handler() and is returned in handler->offset. + * + * Address allocations are exclusive, except for the FCP registers. */ int fw_core_add_address_handler(struct fw_address_handler *handler, const struct fw_address_region *region) @@ -498,10 +513,12 @@ int fw_core_add_address_handler(struct fw_address_handler *handler, handler->offset = region->start; while (handler->offset + handler->length <= region->end) { - other = - lookup_overlapping_address_handler(&address_handler_list, - handler->offset, - handler->length); + if (is_in_fcp_region(handler->offset, handler->length)) + other = NULL; + else + other = lookup_overlapping_address_handler + (&address_handler_list, + handler->offset, handler->length); if (other != NULL) { handler->offset += other->length; } else { @@ -668,6 +685,9 @@ static struct fw_request *allocate_request(struct fw_packet *p) void fw_send_response(struct fw_card *card, struct fw_request *request, int rcode) { + if (WARN_ONCE(!request, "invalid for FCP address handlers")) + return; + /* unified transaction or broadcast transaction: don't respond */ if (request->ack != ACK_PENDING || HEADER_DESTINATION_IS_BROADCAST(request->request_header[0])) { @@ -686,26 +706,15 @@ void fw_send_response(struct fw_card *card, } EXPORT_SYMBOL(fw_send_response); -void fw_core_handle_request(struct fw_card *card, struct fw_packet *p) +static void handle_exclusive_region_request(struct fw_card *card, + struct fw_packet *p, + struct fw_request *request, + unsigned long long offset) { struct fw_address_handler *handler; - struct fw_request *request; - unsigned long long offset; unsigned long flags; int tcode, destination, source; - if (p->ack != ACK_PENDING && p->ack != ACK_COMPLETE) - return; - - request = allocate_request(p); - if (request == NULL) { - /* FIXME: send statically allocated busy packet. */ - return; - } - - offset = - ((unsigned long long) - HEADER_GET_OFFSET_HIGH(p->header[1]) << 32) | p->header[2]; tcode = HEADER_GET_TCODE(p->header[0]); destination = HEADER_GET_DESTINATION(p->header[0]); source = HEADER_GET_SOURCE(p->header[1]); @@ -732,6 +741,73 @@ void fw_core_handle_request(struct fw_card *card, struct fw_packet *p) request->data, request->length, handler->callback_data); } + +static void handle_fcp_region_request(struct fw_card *card, + struct fw_packet *p, + struct fw_request *request, + unsigned long long offset) +{ + struct fw_address_handler *handler; + unsigned long flags; + int tcode, destination, source; + + if ((offset != (CSR_REGISTER_BASE | CSR_FCP_COMMAND) && + offset != (CSR_REGISTER_BASE | CSR_FCP_RESPONSE)) || + request->length > 0x200) { + fw_send_response(card, request, RCODE_ADDRESS_ERROR); + + return; + } + + tcode = HEADER_GET_TCODE(p->header[0]); + destination = HEADER_GET_DESTINATION(p->header[0]); + source = HEADER_GET_SOURCE(p->header[1]); + + if (tcode != TCODE_WRITE_QUADLET_REQUEST && + tcode != TCODE_WRITE_BLOCK_REQUEST) { + fw_send_response(card, request, RCODE_TYPE_ERROR); + + return; + } + + spin_lock_irqsave(&address_handler_lock, flags); + list_for_each_entry(handler, &address_handler_list, link) { + if (is_enclosing_handler(handler, offset, request->length)) + handler->address_callback(card, NULL, tcode, + destination, source, + p->generation, p->speed, + offset, request->data, + request->length, + handler->callback_data); + } + spin_unlock_irqrestore(&address_handler_lock, flags); + + fw_send_response(card, request, RCODE_COMPLETE); +} + +void fw_core_handle_request(struct fw_card *card, struct fw_packet *p) +{ + struct fw_request *request; + unsigned long long offset; + + if (p->ack != ACK_PENDING && p->ack != ACK_COMPLETE) + return; + + request = allocate_request(p); + if (request == NULL) { + /* FIXME: send statically allocated busy packet. */ + return; + } + + offset = ((u64)HEADER_GET_OFFSET_HIGH(p->header[1]) << 32) | + p->header[2]; + + if (!is_in_fcp_region(offset, request->length)) + handle_exclusive_region_request(card, p, request, offset); + else + handle_fcp_region_request(card, p, request, offset); + +} EXPORT_SYMBOL(fw_core_handle_request); void fw_core_handle_response(struct fw_card *card, struct fw_packet *p) diff --git a/drivers/firewire/ohci.c b/drivers/firewire/ohci.c index 96768e16086..a61571c63c5 100644 --- a/drivers/firewire/ohci.c +++ b/drivers/firewire/ohci.c @@ -2226,7 +2226,6 @@ static int ohci_queue_iso_receive_dualbuffer(struct fw_iso_context *base, if (rest == 0) return -EINVAL; - /* FIXME: make packet-per-buffer/dual-buffer a context option */ while (rest > 0) { d = context_get_descriptors(&ctx->context, z + header_z, &d_bus); @@ -2470,7 +2469,10 @@ static int __devinit pci_probe(struct pci_dev *dev, } version = reg_read(ohci, OHCI1394_Version) & 0x00ff00ff; +#if 0 + /* FIXME: make it a context option or remove dual-buffer mode */ ohci->use_dualbuffer = version >= OHCI_VERSION_1_1; +#endif /* dual-buffer mode is broken if more than one IR context is active */ if (dev->vendor == PCI_VENDOR_ID_AGERE && diff --git a/drivers/ieee1394/Kconfig b/drivers/ieee1394/Kconfig index f102fcc7e52..e02096cf7d9 100644 --- a/drivers/ieee1394/Kconfig +++ b/drivers/ieee1394/Kconfig @@ -1,8 +1,3 @@ -menu "IEEE 1394 (FireWire) support" - depends on PCI || BROKEN - -source "drivers/firewire/Kconfig" - config IEEE1394 tristate "Legacy alternative FireWire driver stack" depends on PCI || BROKEN @@ -16,8 +11,13 @@ config IEEE1394 is the core support only, you will also need to select a driver for your IEEE 1394 adapter. - To compile this driver as a module, say M here: the - module will be called ieee1394. + To compile this driver as a module, say M here: the module will be + called ieee1394. + + NOTE: + ieee1394 is superseded by the newer firewire-core driver. See + http://ieee1394.wiki.kernel.org/index.php/Juju_Migration for + further information on how to switch to the new FireWire drivers. config IEEE1394_OHCI1394 tristate "OHCI-1394 controllers" @@ -29,19 +29,23 @@ config IEEE1394_OHCI1394 use one of these chipsets. It should work with any OHCI-1394 compliant card, however. - To compile this driver as a module, say M here: the - module will be called ohci1394. + To compile this driver as a module, say M here: the module will be + called ohci1394. NOTE: + ohci1394 is superseded by the newer firewire-ohci driver. See + http://ieee1394.wiki.kernel.org/index.php/Juju_Migration for + further information on how to switch to the new FireWire drivers. + If you want to install firewire-ohci and ohci1394 together, you should configure them only as modules and blacklist the driver(s) which you don't want to have auto-loaded. Add either - blacklist firewire-ohci - or blacklist ohci1394 blacklist video1394 blacklist dv1394 + or + blacklist firewire-ohci to /etc/modprobe.conf or /etc/modprobe.d/* and update modprobe.conf depending on your distribution. @@ -58,8 +62,8 @@ config IEEE1394_PCILYNX Instruments PCILynx chip. Note: this driver is written for revision 2 of this chip and may not work with revision 0. - To compile this driver as a module, say M here: the - module will be called pcilynx. + To compile this driver as a module, say M here: the module will be + called pcilynx. Only some old and now very rare PCI and CardBus cards and PowerMacs G3 B&W contain the PCILynx controller. Therefore @@ -79,6 +83,14 @@ config IEEE1394_SBP2 You should also enable support for disks, CD-ROMs, etc. in the SCSI configuration section. + To compile this driver as a module, say M here: the module will be + called sbp2. + + NOTE: + sbp2 is superseded by the newer firewire-sbp2 driver. See + http://ieee1394.wiki.kernel.org/index.php/Juju_Migration for + further information on how to switch to the new FireWire drivers. + config IEEE1394_SBP2_PHYS_DMA bool "Enable replacement for physical DMA in SBP2" depends on IEEE1394_SBP2 && VIRT_TO_BUS && EXPERIMENTAL @@ -111,6 +123,11 @@ config IEEE1394_ETH1394 The module is called eth1394 although it does not emulate Ethernet. + NOTE: + eth1394 is superseded by the newer firewire-net driver. See + http://ieee1394.wiki.kernel.org/index.php/Juju_Migration for + further information on how to switch to the new FireWire drivers. + config IEEE1394_RAWIO tristate "raw1394 userspace interface" depends on IEEE1394 @@ -123,6 +140,11 @@ config IEEE1394_RAWIO To compile this driver as a module, say M here: the module will be called raw1394. + NOTE: + raw1394 is superseded by the newer firewire-core driver. See + http://ieee1394.wiki.kernel.org/index.php/Juju_Migration for + further information on how to switch to the new FireWire drivers. + config IEEE1394_VIDEO1394 tristate "video1394 userspace interface" depends on IEEE1394 && IEEE1394_OHCI1394 @@ -136,13 +158,18 @@ config IEEE1394_VIDEO1394 To compile this driver as a module, say M here: the module will be called video1394. + NOTE: + video1394 is superseded by the newer firewire-core driver. See + http://ieee1394.wiki.kernel.org/index.php/Juju_Migration for + further information on how to switch to the new FireWire drivers. + config IEEE1394_DV1394 tristate "dv1394 userspace interface (deprecated)" depends on IEEE1394 && IEEE1394_OHCI1394 help The dv1394 driver is unsupported and may be removed from Linux in a - future release. Its functionality is now provided by raw1394 together - with libraries such as libiec61883. + future release. Its functionality is now provided by either + raw1394 or firewire-core together with libraries such as libiec61883. config IEEE1394_VERBOSEDEBUG bool "Excessive debugging output" @@ -153,5 +180,3 @@ config IEEE1394_VERBOSEDEBUG will quickly result in large amounts of data sent to the system log. Say Y if you really need the debugging output. Everyone else says N. - -endmenu diff --git a/drivers/input/ff-memless.c b/drivers/input/ff-memless.c index b483b2995fa..f967008f332 100644 --- a/drivers/input/ff-memless.c +++ b/drivers/input/ff-memless.c @@ -221,11 +221,27 @@ static int get_compatible_type(struct ff_device *ff, int effect_type) } /* + * Only left/right direction should be used (under/over 0x8000) for + * forward/reverse motor direction (to keep calculation fast & simple). + */ +static u16 ml_calculate_direction(u16 direction, u16 force, + u16 new_direction, u16 new_force) +{ + if (!force) + return new_direction; + if (!new_force) + return direction; + return (((u32)(direction >> 1) * force + + (new_direction >> 1) * new_force) / + (force + new_force)) << 1; +} + +/* * Combine two effects and apply gain. */ static void ml_combine_effects(struct ff_effect *effect, struct ml_effect_state *state, - unsigned int gain) + int gain) { struct ff_effect *new = state->effect; unsigned int strong, weak, i; @@ -252,8 +268,21 @@ static void ml_combine_effects(struct ff_effect *effect, break; case FF_RUMBLE: - strong = new->u.rumble.strong_magnitude * gain / 0xffff; - weak = new->u.rumble.weak_magnitude * gain / 0xffff; + strong = (u32)new->u.rumble.strong_magnitude * gain / 0xffff; + weak = (u32)new->u.rumble.weak_magnitude * gain / 0xffff; + + if (effect->u.rumble.strong_magnitude + strong) + effect->direction = ml_calculate_direction( + effect->direction, + effect->u.rumble.strong_magnitude, + new->direction, strong); + else if (effect->u.rumble.weak_magnitude + weak) + effect->direction = ml_calculate_direction( + effect->direction, + effect->u.rumble.weak_magnitude, + new->direction, weak); + else + effect->direction = 0; effect->u.rumble.strong_magnitude = min(strong + effect->u.rumble.strong_magnitude, 0xffffU); @@ -268,6 +297,13 @@ static void ml_combine_effects(struct ff_effect *effect, /* here we also scale it 0x7fff => 0xffff */ i = i * gain / 0x7fff; + if (effect->u.rumble.strong_magnitude + i) + effect->direction = ml_calculate_direction( + effect->direction, + effect->u.rumble.strong_magnitude, + new->direction, i); + else + effect->direction = 0; effect->u.rumble.strong_magnitude = min(i + effect->u.rumble.strong_magnitude, 0xffffU); effect->u.rumble.weak_magnitude = @@ -411,8 +447,6 @@ static int ml_ff_playback(struct input_dev *dev, int effect_id, int value) msecs_to_jiffies(state->effect->replay.length); state->adj_at = state->play_at; - ml_schedule_timer(ml); - } else { debug("initiated stop"); @@ -420,10 +454,10 @@ static int ml_ff_playback(struct input_dev *dev, int effect_id, int value) __set_bit(FF_EFFECT_ABORTING, &state->flags); else __clear_bit(FF_EFFECT_STARTED, &state->flags); - - ml_play_effects(ml); } + ml_play_effects(ml); + return 0; } diff --git a/drivers/input/joystick/iforce/iforce-main.c b/drivers/input/joystick/iforce/iforce-main.c index f6c688cae33..b1edd778639 100644 --- a/drivers/input/joystick/iforce/iforce-main.c +++ b/drivers/input/joystick/iforce/iforce-main.c @@ -210,7 +210,7 @@ static int iforce_open(struct input_dev *dev) return 0; } -static void iforce_release(struct input_dev *dev) +static void iforce_close(struct input_dev *dev) { struct iforce *iforce = input_get_drvdata(dev); int i; @@ -228,30 +228,17 @@ static void iforce_release(struct input_dev *dev) /* Disable force feedback playback */ iforce_send_packet(iforce, FF_CMD_ENABLE, "\001"); + /* Wait for the command to complete */ + wait_event_interruptible(iforce->wait, + !test_bit(IFORCE_XMIT_RUNNING, iforce->xmit_flags)); } switch (iforce->bus) { #ifdef CONFIG_JOYSTICK_IFORCE_USB - case IFORCE_USB: - usb_kill_urb(iforce->irq); - - /* The device was unplugged before the file - * was released */ - if (iforce->usbdev == NULL) { - iforce_delete_device(iforce); - kfree(iforce); - } - break; -#endif - } -} - -void iforce_delete_device(struct iforce *iforce) -{ - switch (iforce->bus) { -#ifdef CONFIG_JOYSTICK_IFORCE_USB case IFORCE_USB: - iforce_usb_delete(iforce); + usb_kill_urb(iforce->irq); + usb_kill_urb(iforce->out); + usb_kill_urb(iforce->ctrl); break; #endif #ifdef CONFIG_JOYSTICK_IFORCE_232 @@ -303,7 +290,7 @@ int iforce_init_device(struct iforce *iforce) input_dev->name = "Unknown I-Force device"; input_dev->open = iforce_open; - input_dev->close = iforce_release; + input_dev->close = iforce_close; /* * On-device memory allocation. diff --git a/drivers/input/joystick/iforce/iforce-usb.c b/drivers/input/joystick/iforce/iforce-usb.c index 9f289d8f52c..b41303d3ec5 100644 --- a/drivers/input/joystick/iforce/iforce-usb.c +++ b/drivers/input/joystick/iforce/iforce-usb.c @@ -109,6 +109,7 @@ static void iforce_usb_out(struct urb *urb) struct iforce *iforce = urb->context; if (urb->status) { + clear_bit(IFORCE_XMIT_RUNNING, iforce->xmit_flags); dbg("urb->status %d, exiting", urb->status); return; } @@ -186,33 +187,19 @@ fail: return err; } -/* Called by iforce_delete() */ -void iforce_usb_delete(struct iforce* iforce) -{ - usb_kill_urb(iforce->irq); - usb_kill_urb(iforce->out); - usb_kill_urb(iforce->ctrl); - - usb_free_urb(iforce->irq); - usb_free_urb(iforce->out); - usb_free_urb(iforce->ctrl); -} - static void iforce_usb_disconnect(struct usb_interface *intf) { struct iforce *iforce = usb_get_intfdata(intf); - int open = 0; /* FIXME! iforce->dev.handle->open; */ usb_set_intfdata(intf, NULL); - if (iforce) { - iforce->usbdev = NULL; - input_unregister_device(iforce->dev); - if (!open) { - iforce_delete_device(iforce); - kfree(iforce); - } - } + input_unregister_device(iforce->dev); + + usb_free_urb(iforce->irq); + usb_free_urb(iforce->out); + usb_free_urb(iforce->ctrl); + + kfree(iforce); } static struct usb_device_id iforce_usb_ids [] = { diff --git a/drivers/input/joystick/iforce/iforce.h b/drivers/input/joystick/iforce/iforce.h index f2d91f4028c..9f494b75848 100644 --- a/drivers/input/joystick/iforce/iforce.h +++ b/drivers/input/joystick/iforce/iforce.h @@ -150,11 +150,9 @@ void iforce_serial_xmit(struct iforce *iforce); /* iforce-usb.c */ void iforce_usb_xmit(struct iforce *iforce); -void iforce_usb_delete(struct iforce *iforce); /* iforce-main.c */ int iforce_init_device(struct iforce *iforce); -void iforce_delete_device(struct iforce *iforce); /* iforce-packets.c */ int iforce_control_playback(struct iforce*, u16 id, unsigned int); diff --git a/drivers/input/keyboard/atkbd.c b/drivers/input/keyboard/atkbd.c index a3573570c52..1f5e2ce327d 100644 --- a/drivers/input/keyboard/atkbd.c +++ b/drivers/input/keyboard/atkbd.c @@ -134,7 +134,8 @@ static const unsigned short atkbd_unxlate_table[128] = { #define ATKBD_CMD_GETID 0x02f2 #define ATKBD_CMD_SETREP 0x10f3 #define ATKBD_CMD_ENABLE 0x00f4 -#define ATKBD_CMD_RESET_DIS 0x00f5 +#define ATKBD_CMD_RESET_DIS 0x00f5 /* Reset to defaults and disable */ +#define ATKBD_CMD_RESET_DEF 0x00f6 /* Reset to defaults */ #define ATKBD_CMD_SETALL_MBR 0x00fa #define ATKBD_CMD_RESET_BAT 0x02ff #define ATKBD_CMD_RESEND 0x00fe @@ -836,7 +837,7 @@ static void atkbd_cleanup(struct serio *serio) struct atkbd *atkbd = serio_get_drvdata(serio); atkbd_disable(atkbd); - ps2_command(&atkbd->ps2dev, NULL, ATKBD_CMD_RESET_BAT); + ps2_command(&atkbd->ps2dev, NULL, ATKBD_CMD_RESET_DEF); } diff --git a/drivers/input/keyboard/matrix_keypad.c b/drivers/input/keyboard/matrix_keypad.c index 34f4a29d497..d3c8b61a941 100644 --- a/drivers/input/keyboard/matrix_keypad.c +++ b/drivers/input/keyboard/matrix_keypad.c @@ -29,11 +29,13 @@ struct matrix_keypad { unsigned short *keycodes; unsigned int row_shift; + DECLARE_BITMAP(disabled_gpios, MATRIX_MAX_ROWS); + uint32_t last_key_state[MATRIX_MAX_COLS]; struct delayed_work work; + spinlock_t lock; bool scan_pending; bool stopped; - spinlock_t lock; }; /* @@ -222,9 +224,16 @@ static int matrix_keypad_suspend(struct device *dev) matrix_keypad_stop(keypad->input_dev); - if (device_may_wakeup(&pdev->dev)) - for (i = 0; i < pdata->num_row_gpios; i++) - enable_irq_wake(gpio_to_irq(pdata->row_gpios[i])); + if (device_may_wakeup(&pdev->dev)) { + for (i = 0; i < pdata->num_row_gpios; i++) { + if (!test_bit(i, keypad->disabled_gpios)) { + unsigned int gpio = pdata->row_gpios[i]; + + if (enable_irq_wake(gpio_to_irq(gpio)) == 0) + __set_bit(i, keypad->disabled_gpios); + } + } + } return 0; } @@ -236,9 +245,15 @@ static int matrix_keypad_resume(struct device *dev) const struct matrix_keypad_platform_data *pdata = keypad->pdata; int i; - if (device_may_wakeup(&pdev->dev)) - for (i = 0; i < pdata->num_row_gpios; i++) - disable_irq_wake(gpio_to_irq(pdata->row_gpios[i])); + if (device_may_wakeup(&pdev->dev)) { + for (i = 0; i < pdata->num_row_gpios; i++) { + if (test_and_clear_bit(i, keypad->disabled_gpios)) { + unsigned int gpio = pdata->row_gpios[i]; + + disable_irq_wake(gpio_to_irq(gpio)); + } + } + } matrix_keypad_start(keypad->input_dev); diff --git a/drivers/input/keyboard/twl4030_keypad.c b/drivers/input/keyboard/twl4030_keypad.c index eeaa7acb9cf..21d6184efa9 100644 --- a/drivers/input/keyboard/twl4030_keypad.c +++ b/drivers/input/keyboard/twl4030_keypad.c @@ -253,14 +253,6 @@ static irqreturn_t do_kp_irq(int irq, void *_kp) u8 reg; int ret; -#ifdef CONFIG_LOCKDEP - /* WORKAROUND for lockdep forcing IRQF_DISABLED on us, which - * we don't want and can't tolerate. Although it might be - * friendlier not to borrow this thread context... - */ - local_irq_enable(); -#endif - /* Read & Clear TWL4030 pending interrupt */ ret = twl4030_kpread(kp, ®, KEYP_ISR1, 1); @@ -403,7 +395,8 @@ static int __devinit twl4030_kp_probe(struct platform_device *pdev) * * NOTE: we assume this host is wired to TWL4040 INT1, not INT2 ... */ - error = request_irq(kp->irq, do_kp_irq, 0, pdev->name, kp); + error = request_threaded_irq(kp->irq, NULL, do_kp_irq, + 0, pdev->name, kp); if (error) { dev_info(kp->dbg_dev, "request_irq failed for irq no=%d\n", kp->irq); diff --git a/drivers/input/misc/twl4030-pwrbutton.c b/drivers/input/misc/twl4030-pwrbutton.c index bdde5c88903..e9069b87fde 100644 --- a/drivers/input/misc/twl4030-pwrbutton.c +++ b/drivers/input/misc/twl4030-pwrbutton.c @@ -39,18 +39,8 @@ static irqreturn_t powerbutton_irq(int irq, void *_pwr) int err; u8 value; -#ifdef CONFIG_LOCKDEP - /* WORKAROUND for lockdep forcing IRQF_DISABLED on us, which - * we don't want and can't tolerate since this is a threaded - * IRQ and can sleep due to the i2c reads it has to issue. - * Although it might be friendlier not to borrow this thread - * context... - */ - local_irq_enable(); -#endif - err = twl_i2c_read_u8(TWL4030_MODULE_PM_MASTER, &value, - STS_HW_CONDITIONS); + STS_HW_CONDITIONS); if (!err) { input_report_key(pwr, KEY_POWER, value & PWR_PWRON_IRQ); input_sync(pwr); @@ -80,7 +70,7 @@ static int __devinit twl4030_pwrbutton_probe(struct platform_device *pdev) pwr->phys = "twl4030_pwrbutton/input0"; pwr->dev.parent = &pdev->dev; - err = request_irq(irq, powerbutton_irq, + err = request_threaded_irq(irq, NULL, powerbutton_irq, IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING, "twl4030_pwrbutton", pwr); if (err < 0) { diff --git a/drivers/input/misc/wistron_btns.c b/drivers/input/misc/wistron_btns.c index 38da6ab0438..c0afb71a3a6 100644 --- a/drivers/input/misc/wistron_btns.c +++ b/drivers/input/misc/wistron_btns.c @@ -1328,7 +1328,7 @@ static struct platform_driver wistron_driver = { .driver = { .name = "wistron-bios", .owner = THIS_MODULE, -#if CONFIG_PM +#ifdef CONFIG_PM .pm = &wistron_pm_ops, #endif }, diff --git a/drivers/input/mouse/Kconfig b/drivers/input/mouse/Kconfig index 3feeb3af8ab..c714ca2407f 100644 --- a/drivers/input/mouse/Kconfig +++ b/drivers/input/mouse/Kconfig @@ -70,7 +70,7 @@ config MOUSE_PS2_SYNAPTICS config MOUSE_PS2_LIFEBOOK bool "Fujitsu Lifebook PS/2 mouse protocol extension" if EMBEDDED default y - depends on MOUSE_PS2 && X86 + depends on MOUSE_PS2 && X86 && DMI help Say Y here if you have a Fujitsu B-series Lifebook PS/2 TouchScreen connected to your system. diff --git a/drivers/input/mouse/hgpk.c b/drivers/input/mouse/hgpk.c index b146237266d..90be30e9355 100644 --- a/drivers/input/mouse/hgpk.c +++ b/drivers/input/mouse/hgpk.c @@ -427,7 +427,6 @@ static void hgpk_recalib_work(struct work_struct *work) static int hgpk_register(struct psmouse *psmouse) { - struct input_dev *dev = psmouse->dev; int err; /* register handlers */ diff --git a/drivers/input/mouse/lifebook.c b/drivers/input/mouse/lifebook.c index 2e6bdfea016..6d7aa10d10f 100644 --- a/drivers/input/mouse/lifebook.c +++ b/drivers/input/mouse/lifebook.c @@ -44,7 +44,6 @@ static int lifebook_set_6byte_proto(const struct dmi_system_id *d) } static const struct dmi_system_id __initconst lifebook_dmi_table[] = { -#if defined(CONFIG_DMI) && defined(CONFIG_X86) { /* FLORA-ie 55mi */ .matches = { @@ -118,7 +117,6 @@ static const struct dmi_system_id __initconst lifebook_dmi_table[] = { }, }, { } -#endif }; void __init lifebook_module_init(void) diff --git a/drivers/input/mouse/psmouse-base.c b/drivers/input/mouse/psmouse-base.c index fd0bc094616..401ac6b6edd 100644 --- a/drivers/input/mouse/psmouse-base.c +++ b/drivers/input/mouse/psmouse-base.c @@ -1137,7 +1137,10 @@ static void psmouse_cleanup(struct serio *serio) if (psmouse->cleanup) psmouse->cleanup(psmouse); - psmouse_reset(psmouse); +/* + * Reset the mouse to defaults (bare PS/2 protocol). + */ + ps2_command(&psmouse->ps2dev, NULL, PSMOUSE_CMD_RESET_DIS); /* * Some boxes, such as HP nx7400, get terribly confused if mouse diff --git a/drivers/input/serio/serio.c b/drivers/input/serio/serio.c index 0236f0d5fd9..e0f30186d51 100644 --- a/drivers/input/serio/serio.c +++ b/drivers/input/serio/serio.c @@ -284,13 +284,7 @@ static void serio_handle_event(void) mutex_lock(&serio_mutex); - /* - * Note that we handle only one event here to give swsusp - * a chance to freeze kseriod thread. Serio events should - * be pretty rare so we are not concerned about taking - * performance hit. - */ - if ((event = serio_get_event())) { + while ((event = serio_get_event())) { switch (event->type) { case SERIO_REGISTER_PORT: @@ -380,10 +374,9 @@ static struct serio *serio_get_pending_child(struct serio *parent) static int serio_thread(void *nothing) { - set_freezable(); do { serio_handle_event(); - wait_event_freezable(serio_wait, + wait_event_interruptible(serio_wait, kthread_should_stop() || !list_empty(&serio_event_list)); } while (!kthread_should_stop()); diff --git a/drivers/md/md.c b/drivers/md/md.c index f4f5f82f9f5..dd3dfe42d5a 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -386,7 +386,9 @@ static void mddev_put(mddev_t *mddev) if (!atomic_dec_and_lock(&mddev->active, &all_mddevs_lock)) return; if (!mddev->raid_disks && list_empty(&mddev->disks) && - !mddev->hold_active) { + mddev->ctime == 0 && !mddev->hold_active) { + /* Array is not configured at all, and not held active, + * so destroy it */ list_del(&mddev->all_mddevs); if (mddev->gendisk) { /* we did a probe so need to clean up. @@ -4355,7 +4357,7 @@ static int do_md_run(mddev_t * mddev) mddev->barriers_work = 1; mddev->ok_start_degraded = start_dirty_degraded; - if (start_readonly) + if (start_readonly && mddev->ro == 0) mddev->ro = 2; /* read-only, but switch on first write */ err = mddev->pers->run(mddev); @@ -4419,33 +4421,6 @@ static int do_md_run(mddev_t * mddev) set_capacity(disk, mddev->array_sectors); - /* If there is a partially-recovered drive we need to - * start recovery here. If we leave it to md_check_recovery, - * it will remove the drives and not do the right thing - */ - if (mddev->degraded && !mddev->sync_thread) { - int spares = 0; - list_for_each_entry(rdev, &mddev->disks, same_set) - if (rdev->raid_disk >= 0 && - !test_bit(In_sync, &rdev->flags) && - !test_bit(Faulty, &rdev->flags)) - /* complete an interrupted recovery */ - spares++; - if (spares && mddev->pers->sync_request) { - mddev->recovery = 0; - set_bit(MD_RECOVERY_RUNNING, &mddev->recovery); - mddev->sync_thread = md_register_thread(md_do_sync, - mddev, - "resync"); - if (!mddev->sync_thread) { - printk(KERN_ERR "%s: could not start resync" - " thread...\n", - mdname(mddev)); - /* leave the spares where they are, it shouldn't hurt */ - mddev->recovery = 0; - } - } - } md_wakeup_thread(mddev->thread); md_wakeup_thread(mddev->sync_thread); /* possibly kick off a reshape */ @@ -5262,6 +5237,10 @@ static int set_array_info(mddev_t * mddev, mdu_array_info_t *info) mddev->minor_version = info->minor_version; mddev->patch_version = info->patch_version; mddev->persistent = !info->not_persistent; + /* ensure mddev_put doesn't delete this now that there + * is some minimal configuration. + */ + mddev->ctime = get_seconds(); return 0; } mddev->major_version = MD_MAJOR_VERSION; @@ -6494,10 +6473,11 @@ void md_do_sync(mddev_t *mddev) mddev->curr_resync = 2; try_again: - if (kthread_should_stop()) { + if (kthread_should_stop()) set_bit(MD_RECOVERY_INTR, &mddev->recovery); + + if (test_bit(MD_RECOVERY_INTR, &mddev->recovery)) goto skip; - } for_each_mddev(mddev2, tmp) { if (mddev2 == mddev) continue; diff --git a/drivers/media/dvb/firewire/firedtv-fw.c b/drivers/media/dvb/firewire/firedtv-fw.c index fe44789ab03..6223bf01efe 100644 --- a/drivers/media/dvb/firewire/firedtv-fw.c +++ b/drivers/media/dvb/firewire/firedtv-fw.c @@ -202,14 +202,8 @@ static void handle_fcp(struct fw_card *card, struct fw_request *request, unsigned long flags; int su; - if ((tcode != TCODE_WRITE_QUADLET_REQUEST && - tcode != TCODE_WRITE_BLOCK_REQUEST) || - offset != CSR_REGISTER_BASE + CSR_FCP_RESPONSE || - length == 0 || - (((u8 *)payload)[0] & 0xf0) != 0) { - fw_send_response(card, request, RCODE_TYPE_ERROR); + if (length < 2 || (((u8 *)payload)[0] & 0xf0) != 0) return; - } su = ((u8 *)payload)[1] & 0x7; @@ -230,10 +224,8 @@ static void handle_fcp(struct fw_card *card, struct fw_request *request, } spin_unlock_irqrestore(&node_list_lock, flags); - if (fdtv) { + if (fdtv) avc_recv(fdtv, payload, length); - fw_send_response(card, request, RCODE_COMPLETE); - } } static struct fw_address_handler fcp_handler = { diff --git a/drivers/message/i2o/i2o_config.c b/drivers/message/i2o/i2o_config.c index efba7021948..3d5f40cd69d 100644 --- a/drivers/message/i2o/i2o_config.c +++ b/drivers/message/i2o/i2o_config.c @@ -40,8 +40,7 @@ #define SG_TABLESIZE 30 -static int i2o_cfg_ioctl(struct inode *, struct file *, unsigned int, - unsigned long); +static long i2o_cfg_ioctl(struct file *, unsigned int, unsigned long); static spinlock_t i2o_config_lock; @@ -751,7 +750,7 @@ static long i2o_cfg_compat_ioctl(struct file *file, unsigned cmd, lock_kernel(); switch (cmd) { case I2OGETIOPS: - ret = i2o_cfg_ioctl(NULL, file, cmd, arg); + ret = i2o_cfg_ioctl(file, cmd, arg); break; case I2OPASSTHRU32: ret = i2o_cfg_passthru32(file, cmd, arg); @@ -984,11 +983,11 @@ out: /* * IOCTL Handler */ -static int i2o_cfg_ioctl(struct inode *inode, struct file *fp, unsigned int cmd, - unsigned long arg) +static long i2o_cfg_ioctl(struct file *fp, unsigned int cmd, unsigned long arg) { int ret; + lock_kernel(); switch (cmd) { case I2OGETIOPS: ret = i2o_cfg_getiops(arg); @@ -1044,7 +1043,7 @@ static int i2o_cfg_ioctl(struct inode *inode, struct file *fp, unsigned int cmd, osm_debug("unknown ioctl called!\n"); ret = -EINVAL; } - + unlock_kernel(); return ret; } @@ -1118,7 +1117,7 @@ static int cfg_release(struct inode *inode, struct file *file) static const struct file_operations config_fops = { .owner = THIS_MODULE, .llseek = no_llseek, - .ioctl = i2o_cfg_ioctl, + .unlocked_ioctl = i2o_cfg_ioctl, #ifdef CONFIG_COMPAT .compat_ioctl = i2o_cfg_compat_ioctl, #endif diff --git a/drivers/mfd/twl4030-irq.c b/drivers/mfd/twl4030-irq.c index 20d29bafc9f..9df9a5ad38f 100644 --- a/drivers/mfd/twl4030-irq.c +++ b/drivers/mfd/twl4030-irq.c @@ -568,12 +568,12 @@ static void twl4030_sih_do_edge(struct work_struct *work) bytes[byte] &= ~(0x03 << off); - spin_lock_irq(&d->lock); + raw_spin_lock_irq(&d->lock); if (d->status & IRQ_TYPE_EDGE_RISING) bytes[byte] |= BIT(off + 1); if (d->status & IRQ_TYPE_EDGE_FALLING) bytes[byte] |= BIT(off + 0); - spin_unlock_irq(&d->lock); + raw_spin_unlock_irq(&d->lock); edge_change &= ~BIT(i); } diff --git a/drivers/net/3c507.c b/drivers/net/3c507.c index fbc231153e5..77cf0901a44 100644 --- a/drivers/net/3c507.c +++ b/drivers/net/3c507.c @@ -56,6 +56,7 @@ static const char version[] = #include <linux/errno.h> #include <linux/netdevice.h> #include <linux/etherdevice.h> +#include <linux/if_ether.h> #include <linux/skbuff.h> #include <linux/slab.h> #include <linux/init.h> @@ -734,8 +735,7 @@ static void init_82586_mem(struct net_device *dev) memcpy_toio(lp->base, init_words + 5, sizeof(init_words) - 10); /* Fill in the station address. */ - memcpy_toio(lp->base+SA_OFFSET, dev->dev_addr, - sizeof(dev->dev_addr)); + memcpy_toio(lp->base+SA_OFFSET, dev->dev_addr, ETH_ALEN); /* The Tx-block list is written as needed. We just set up the values. */ lp->tx_cmd_link = IDLELOOP + 4; diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index e58a65391ad..dd9a09c72df 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -2346,6 +2346,7 @@ config GELIC_NET config GELIC_WIRELESS bool "PS3 Wireless support" + depends on WLAN depends on GELIC_NET select WIRELESS_EXT help @@ -2358,6 +2359,7 @@ config GELIC_WIRELESS config GELIC_WIRELESS_OLD_PSK_INTERFACE bool "PS3 Wireless private PSK interface (OBSOLETE)" depends on GELIC_WIRELESS + select WEXT_PRIV help This option retains the obsolete private interface to pass the PSK from user space programs to the driver. The PSK diff --git a/drivers/net/benet/be.h b/drivers/net/benet/be.h index 9e56014d27e..9fd8e5ecd5d 100644 --- a/drivers/net/benet/be.h +++ b/drivers/net/benet/be.h @@ -275,6 +275,7 @@ struct be_adapter { u32 tx_fc; /* Tx flow control */ int link_speed; u8 port_type; + u8 transceiver; }; extern const struct ethtool_ops be_ethtool_ops; diff --git a/drivers/net/benet/be_cmds.c b/drivers/net/benet/be_cmds.c index 1b68bd98dc0..102ade13416 100644 --- a/drivers/net/benet/be_cmds.c +++ b/drivers/net/benet/be_cmds.c @@ -1479,6 +1479,41 @@ err: return status; } +int be_cmd_set_loopback(struct be_adapter *adapter, u8 port_num, + u8 loopback_type, u8 enable) +{ + struct be_mcc_wrb *wrb; + struct be_cmd_req_set_lmode *req; + int status; + + spin_lock_bh(&adapter->mcc_lock); + + wrb = wrb_from_mccq(adapter); + if (!wrb) { + status = -EBUSY; + goto err; + } + + req = embedded_payload(wrb); + + be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0, + OPCODE_LOWLEVEL_SET_LOOPBACK_MODE); + + be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_LOWLEVEL, + OPCODE_LOWLEVEL_SET_LOOPBACK_MODE, + sizeof(*req)); + + req->src_port = port_num; + req->dest_port = port_num; + req->loopback_type = loopback_type; + req->loopback_state = enable; + + status = be_mcc_notify_wait(adapter); +err: + spin_unlock_bh(&adapter->mcc_lock); + return status; +} + int be_cmd_loopback_test(struct be_adapter *adapter, u32 port_num, u32 loopback_type, u32 pkt_size, u32 num_pkts, u64 pattern) { @@ -1501,6 +1536,7 @@ int be_cmd_loopback_test(struct be_adapter *adapter, u32 port_num, be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_LOWLEVEL, OPCODE_LOWLEVEL_LOOPBACK_TEST, sizeof(*req)); + req->hdr.timeout = 4; req->pattern = cpu_to_le64(pattern); req->src_port = cpu_to_le32(port_num); diff --git a/drivers/net/benet/be_cmds.h b/drivers/net/benet/be_cmds.h index 92b87ef156e..c002b8391b4 100644 --- a/drivers/net/benet/be_cmds.h +++ b/drivers/net/benet/be_cmds.h @@ -155,6 +155,7 @@ struct be_mcc_mailbox { #define OPCODE_LOWLEVEL_HOST_DDR_DMA 17 #define OPCODE_LOWLEVEL_LOOPBACK_TEST 18 +#define OPCODE_LOWLEVEL_SET_LOOPBACK_MODE 19 struct be_cmd_req_hdr { u8 opcode; /* dword 0 */ @@ -821,6 +822,19 @@ struct be_cmd_resp_loopback_test { u32 ticks_compl; }; +struct be_cmd_req_set_lmode { + struct be_cmd_req_hdr hdr; + u8 src_port; + u8 dest_port; + u8 loopback_type; + u8 loopback_state; +}; + +struct be_cmd_resp_set_lmode { + struct be_cmd_resp_hdr resp_hdr; + u8 rsvd0[4]; +}; + /********************** DDR DMA test *********************/ struct be_cmd_req_ddrdma_test { struct be_cmd_req_hdr hdr; @@ -912,3 +926,5 @@ extern int be_cmd_loopback_test(struct be_adapter *adapter, u32 port_num, u32 num_pkts, u64 pattern); extern int be_cmd_ddr_dma_test(struct be_adapter *adapter, u64 pattern, u32 byte_cnt, struct be_dma_mem *cmd); +extern int be_cmd_set_loopback(struct be_adapter *adapter, u8 port_num, + u8 loopback_type, u8 enable); diff --git a/drivers/net/benet/be_ethtool.c b/drivers/net/benet/be_ethtool.c index 298b92cbd68..5d001c4deac 100644 --- a/drivers/net/benet/be_ethtool.c +++ b/drivers/net/benet/be_ethtool.c @@ -118,6 +118,7 @@ static const char et_self_tests[][ETH_GSTRING_LEN] = { #define BE_MAC_LOOPBACK 0x0 #define BE_PHY_LOOPBACK 0x1 #define BE_ONE_PORT_EXT_LOOPBACK 0x2 +#define BE_NO_LOOPBACK 0xff static void be_get_drvinfo(struct net_device *netdev, struct ethtool_drvinfo *drvinfo) @@ -339,28 +340,50 @@ static int be_get_settings(struct net_device *netdev, struct ethtool_cmd *ecmd) status = be_cmd_read_port_type(adapter, adapter->port_num, &connector); - switch (connector) { - case 7: - ecmd->port = PORT_FIBRE; - break; - default: - ecmd->port = PORT_TP; - break; + if (!status) { + switch (connector) { + case 7: + ecmd->port = PORT_FIBRE; + ecmd->transceiver = XCVR_EXTERNAL; + break; + case 0: + ecmd->port = PORT_TP; + ecmd->transceiver = XCVR_EXTERNAL; + break; + default: + ecmd->port = PORT_TP; + ecmd->transceiver = XCVR_INTERNAL; + break; + } + } else { + ecmd->port = PORT_AUI; + ecmd->transceiver = XCVR_INTERNAL; } /* Save for future use */ adapter->link_speed = ecmd->speed; adapter->port_type = ecmd->port; + adapter->transceiver = ecmd->transceiver; } else { ecmd->speed = adapter->link_speed; ecmd->port = adapter->port_type; + ecmd->transceiver = adapter->transceiver; } ecmd->duplex = DUPLEX_FULL; ecmd->autoneg = AUTONEG_DISABLE; - ecmd->supported = (SUPPORTED_10000baseT_Full | SUPPORTED_TP); ecmd->phy_address = adapter->port_num; - ecmd->transceiver = XCVR_INTERNAL; + switch (ecmd->port) { + case PORT_FIBRE: + ecmd->supported = (SUPPORTED_10000baseT_Full | SUPPORTED_FIBRE); + break; + case PORT_TP: + ecmd->supported = (SUPPORTED_10000baseT_Full | SUPPORTED_TP); + break; + case PORT_AUI: + ecmd->supported = (SUPPORTED_10000baseT_Full | SUPPORTED_AUI); + break; + } return 0; } @@ -489,6 +512,19 @@ err: return ret; } +static u64 be_loopback_test(struct be_adapter *adapter, u8 loopback_type, + u64 *status) +{ + be_cmd_set_loopback(adapter, adapter->port_num, + loopback_type, 1); + *status = be_cmd_loopback_test(adapter, adapter->port_num, + loopback_type, 1500, + 2, 0xabc); + be_cmd_set_loopback(adapter, adapter->port_num, + BE_NO_LOOPBACK, 1); + return *status; +} + static void be_self_test(struct net_device *netdev, struct ethtool_test *test, u64 *data) { @@ -497,23 +533,18 @@ be_self_test(struct net_device *netdev, struct ethtool_test *test, u64 *data) memset(data, 0, sizeof(u64) * ETHTOOL_TESTS_NUM); if (test->flags & ETH_TEST_FL_OFFLINE) { - data[0] = be_cmd_loopback_test(adapter, adapter->port_num, - BE_MAC_LOOPBACK, 1500, - 2, 0xabc); - if (data[0] != 0) + if (be_loopback_test(adapter, BE_MAC_LOOPBACK, + &data[0]) != 0) { test->flags |= ETH_TEST_FL_FAILED; - - data[1] = be_cmd_loopback_test(adapter, adapter->port_num, - BE_PHY_LOOPBACK, 1500, - 2, 0xabc); - if (data[1] != 0) + } + if (be_loopback_test(adapter, BE_PHY_LOOPBACK, + &data[1]) != 0) { test->flags |= ETH_TEST_FL_FAILED; - - data[2] = be_cmd_loopback_test(adapter, adapter->port_num, - BE_ONE_PORT_EXT_LOOPBACK, - 1500, 2, 0xabc); - if (data[2] != 0) + } + if (be_loopback_test(adapter, BE_ONE_PORT_EXT_LOOPBACK, + &data[2]) != 0) { test->flags |= ETH_TEST_FL_FAILED; + } data[3] = be_test_ddr_dma(adapter); if (data[3] != 0) diff --git a/drivers/net/bnx2x_main.c b/drivers/net/bnx2x_main.c index 77ba13520d8..306c2b8165e 100644 --- a/drivers/net/bnx2x_main.c +++ b/drivers/net/bnx2x_main.c @@ -7593,6 +7593,8 @@ static int bnx2x_nic_load(struct bnx2x *bp, int load_mode) if (bp->cnic_eth_dev.drv_state & CNIC_DRV_STATE_REGD) { bnx2x_set_iscsi_eth_mac_addr(bp, 1); bp->cnic_flags |= BNX2X_CNIC_FLAG_MAC_SET; + bnx2x_init_sb(bp, bp->cnic_sb, bp->cnic_sb_mapping, + CNIC_SB_ID(bp)); } mutex_unlock(&bp->cnic_mutex); #endif diff --git a/drivers/net/bonding/bond_3ad.c b/drivers/net/bonding/bond_3ad.c index 0fb7a4964e7..822f586d72a 100644 --- a/drivers/net/bonding/bond_3ad.c +++ b/drivers/net/bonding/bond_3ad.c @@ -1580,7 +1580,7 @@ static void ad_agg_selection_logic(struct aggregator *agg) // check if any partner replys if (best->is_individual) { pr_warning("%s: Warning: No 802.3ad response from the link partner for any adapters in the bond\n", - best->slave->dev->master->name); + best->slave ? best->slave->dev->master->name : "NULL"); } best->is_active = 1; diff --git a/drivers/net/gianfar.c b/drivers/net/gianfar.c index e0620d08464..8bd3c9f1753 100644 --- a/drivers/net/gianfar.c +++ b/drivers/net/gianfar.c @@ -143,7 +143,6 @@ void gfar_start(struct net_device *dev); static void gfar_clear_exact_match(struct net_device *dev); static void gfar_set_mac_for_addr(struct net_device *dev, int num, u8 *addr); static int gfar_ioctl(struct net_device *dev, struct ifreq *rq, int cmd); -u16 gfar_select_queue(struct net_device *dev, struct sk_buff *skb); MODULE_AUTHOR("Freescale Semiconductor, Inc"); MODULE_DESCRIPTION("Gianfar Ethernet Driver"); @@ -455,7 +454,6 @@ static const struct net_device_ops gfar_netdev_ops = { .ndo_set_multicast_list = gfar_set_multi, .ndo_tx_timeout = gfar_timeout, .ndo_do_ioctl = gfar_ioctl, - .ndo_select_queue = gfar_select_queue, .ndo_get_stats = gfar_get_stats, .ndo_vlan_rx_register = gfar_vlan_rx_register, .ndo_set_mac_address = eth_mac_addr, @@ -506,10 +504,6 @@ static inline int gfar_uses_fcb(struct gfar_private *priv) return priv->vlgrp || priv->rx_csum_enable; } -u16 gfar_select_queue(struct net_device *dev, struct sk_buff *skb) -{ - return skb_get_queue_mapping(skb); -} static void free_tx_pointers(struct gfar_private *priv) { int i = 0; @@ -2470,10 +2464,11 @@ static int gfar_process_frame(struct net_device *dev, struct sk_buff *skb, fcb = (struct rxfcb *)skb->data; /* Remove the FCB from the skb */ - skb_set_queue_mapping(skb, fcb->rq); /* Remove the padded bytes, if there are any */ - if (amount_pull) + if (amount_pull) { + skb_record_rx_queue(skb, fcb->rq); skb_pull(skb, amount_pull); + } if (priv->rx_csum_enable) gfar_rx_checksum(skb, fcb); @@ -2554,7 +2549,7 @@ int gfar_clean_rx_ring(struct gfar_priv_rx_q *rx_queue, int rx_work_limit) /* Remove the FCS from the packet length */ skb_put(skb, pkt_len); rx_queue->stats.rx_bytes += pkt_len; - + skb_record_rx_queue(skb, rx_queue->qindex); gfar_process_frame(dev, skb, amount_pull); } else { diff --git a/drivers/net/ibmlana.c b/drivers/net/ibmlana.c index 090a6d3af11..052c74091d9 100644 --- a/drivers/net/ibmlana.c +++ b/drivers/net/ibmlana.c @@ -87,6 +87,7 @@ History: #include <linux/module.h> #include <linux/netdevice.h> #include <linux/etherdevice.h> +#include <linux/if_ether.h> #include <linux/skbuff.h> #include <linux/bitops.h> @@ -988,7 +989,7 @@ static int __devinit ibmlana_init_one(struct device *kdev) /* copy out MAC address */ - for (z = 0; z < sizeof(dev->dev_addr); z++) + for (z = 0; z < ETH_ALEN; z++) dev->dev_addr[z] = inb(dev->base_addr + MACADDRPROM + z); /* print config */ diff --git a/drivers/net/igb/e1000_82575.c b/drivers/net/igb/e1000_82575.c index e8e9e9194a8..c505b50d1fa 100644 --- a/drivers/net/igb/e1000_82575.c +++ b/drivers/net/igb/e1000_82575.c @@ -1096,9 +1096,7 @@ static s32 igb_setup_serdes_link_82575(struct e1000_hw *hw) hw_dbg("Configuring Autoneg:PCS_LCTL=0x%08X\n", reg); } else { /* Set PCS register for forced link */ - reg |= E1000_PCS_LCTL_FSD | /* Force Speed */ - E1000_PCS_LCTL_FORCE_LINK | /* Force Link */ - E1000_PCS_LCTL_FLV_LINK_UP; /* Force link value up */ + reg |= E1000_PCS_LCTL_FSD; /* Force Speed */ hw_dbg("Configuring Forced Link:PCS_LCTL=0x%08X\n", reg); } diff --git a/drivers/net/igb/e1000_phy.c b/drivers/net/igb/e1000_phy.c index 5c9d73e9bb8..3670a66401b 100644 --- a/drivers/net/igb/e1000_phy.c +++ b/drivers/net/igb/e1000_phy.c @@ -457,15 +457,6 @@ s32 igb_copper_link_setup_82580(struct e1000_hw *hw) phy_data |= I82580_CFG_ENABLE_DOWNSHIFT; ret_val = phy->ops.write_reg(hw, I82580_CFG_REG, phy_data); - if (ret_val) - goto out; - - /* Set number of link attempts before downshift */ - ret_val = phy->ops.read_reg(hw, I82580_CTRL_REG, &phy_data); - if (ret_val) - goto out; - phy_data &= ~I82580_CTRL_DOWNSHIFT_MASK; - ret_val = phy->ops.write_reg(hw, I82580_CTRL_REG, phy_data); out: return ret_val; diff --git a/drivers/net/igb/igb_ethtool.c b/drivers/net/igb/igb_ethtool.c index ac9d5272650..f771a6c0877 100644 --- a/drivers/net/igb/igb_ethtool.c +++ b/drivers/net/igb/igb_ethtool.c @@ -1795,7 +1795,7 @@ static int igb_wol_exclusion(struct igb_adapter *adapter, /* dual port cards only support WoL on port A from now on * unless it was enabled in the eeprom for port B * so exclude FUNC_1 ports from having WoL enabled */ - if (rd32(E1000_STATUS) & E1000_STATUS_FUNC_1 && + if ((rd32(E1000_STATUS) & E1000_STATUS_FUNC_MASK) && !adapter->eeprom_wol) { wol->supported = 0; break; diff --git a/drivers/net/igb/igb_main.c b/drivers/net/igb/igb_main.c index 78963a0e128..933c64ff246 100644 --- a/drivers/net/igb/igb_main.c +++ b/drivers/net/igb/igb_main.c @@ -1306,13 +1306,8 @@ void igb_reset(struct igb_adapter *adapter) hwm = min(((pba << 10) * 9 / 10), ((pba << 10) - 2 * adapter->max_frame_size)); - if (mac->type < e1000_82576) { - fc->high_water = hwm & 0xFFF8; /* 8-byte granularity */ - fc->low_water = fc->high_water - 8; - } else { - fc->high_water = hwm & 0xFFF0; /* 16-byte granularity */ - fc->low_water = fc->high_water - 16; - } + fc->high_water = hwm & 0xFFF0; /* 16-byte granularity */ + fc->low_water = fc->high_water - 16; fc->pause_time = 0xFFFF; fc->send_xon = 1; fc->current_mode = fc->requested_mode; diff --git a/drivers/net/igbvf/netdev.c b/drivers/net/igbvf/netdev.c index e9dd95f136a..0dbd0320023 100644 --- a/drivers/net/igbvf/netdev.c +++ b/drivers/net/igbvf/netdev.c @@ -2763,7 +2763,8 @@ static int __devinit igbvf_probe(struct pci_dev *pdev, err = hw->mac.ops.reset_hw(hw); if (err) { dev_info(&pdev->dev, - "PF still in reset state, assigning new address\n"); + "PF still in reset state, assigning new address." + " Is the PF interface up?\n"); random_ether_addr(hw->mac.addr); } else { err = hw->mac.ops.read_mac_addr(hw); diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c index bd64387563f..1a2ea621e37 100644 --- a/drivers/net/ixgbe/ixgbe_main.c +++ b/drivers/net/ixgbe/ixgbe_main.c @@ -4373,6 +4373,11 @@ static int ixgbe_resume(struct pci_dev *pdev) pci_set_power_state(pdev, PCI_D0); pci_restore_state(pdev); + /* + * pci_restore_state clears dev->state_saved so call + * pci_save_state to restore it. + */ + pci_save_state(pdev); err = pci_enable_device_mem(pdev); if (err) { diff --git a/drivers/net/pcnet32.c b/drivers/net/pcnet32.c index dcc67a35e8f..e154677ff70 100644 --- a/drivers/net/pcnet32.c +++ b/drivers/net/pcnet32.c @@ -45,6 +45,7 @@ static const char *const version = #include <linux/crc32.h> #include <linux/netdevice.h> #include <linux/etherdevice.h> +#include <linux/if_ether.h> #include <linux/skbuff.h> #include <linux/spinlock.h> #include <linux/moduleparam.h> @@ -1765,7 +1766,7 @@ pcnet32_probe1(unsigned long ioaddr, int shared, struct pci_dev *pdev) /* if the ethernet address is not valid, force to 00:00:00:00:00:00 */ if (!is_valid_ether_addr(dev->perm_addr)) - memset(dev->dev_addr, 0, sizeof(dev->dev_addr)); + memset(dev->dev_addr, 0, ETH_ALEN); if (pcnet32_debug & NETIF_MSG_PROBE) { printk(" %pM", dev->dev_addr); diff --git a/drivers/net/sfc/efx.c b/drivers/net/sfc/efx.c index f983e3b507c..103e8b0e2a0 100644 --- a/drivers/net/sfc/efx.c +++ b/drivers/net/sfc/efx.c @@ -741,14 +741,14 @@ static int efx_probe_port(struct efx_nic *efx) EFX_LOG(efx, "create port\n"); + if (phy_flash_cfg) + efx->phy_mode = PHY_MODE_SPECIAL; + /* Connect up MAC/PHY operations table */ rc = efx->type->probe_port(efx); if (rc) goto err; - if (phy_flash_cfg) - efx->phy_mode = PHY_MODE_SPECIAL; - /* Sanity check MAC address */ if (is_valid_ether_addr(efx->mac_address)) { memcpy(efx->net_dev->dev_addr, efx->mac_address, ETH_ALEN); diff --git a/drivers/net/sfc/falcon.c b/drivers/net/sfc/falcon.c index 17afcd26e87..9d009c46e96 100644 --- a/drivers/net/sfc/falcon.c +++ b/drivers/net/sfc/falcon.c @@ -925,6 +925,7 @@ static int falcon_probe_port(struct efx_nic *efx) static void falcon_remove_port(struct efx_nic *efx) { + efx->phy_op->remove(efx); efx_nic_free_buffer(efx, &efx->stats_buffer); } diff --git a/drivers/net/sfc/falcon_xmac.c b/drivers/net/sfc/falcon_xmac.c index 3da933f8f07..8ccab2c67a2 100644 --- a/drivers/net/sfc/falcon_xmac.c +++ b/drivers/net/sfc/falcon_xmac.c @@ -111,16 +111,12 @@ static void falcon_mask_status_intr(struct efx_nic *efx, bool enable) efx_writeo(efx, ®, FR_AB_XM_MGT_INT_MASK); } -/* Get status of XAUI link */ -static bool falcon_xaui_link_ok(struct efx_nic *efx) +static bool falcon_xgxs_link_ok(struct efx_nic *efx) { efx_oword_t reg; bool align_done, link_ok = false; int sync_status; - if (LOOPBACK_INTERNAL(efx)) - return true; - /* Read link status */ efx_reado(efx, ®, FR_AB_XX_CORE_STAT); @@ -135,14 +131,24 @@ static bool falcon_xaui_link_ok(struct efx_nic *efx) EFX_SET_OWORD_FIELD(reg, FRF_AB_XX_DISPERR, FFE_AB_XX_STAT_ALL_LANES); efx_writeo(efx, ®, FR_AB_XX_CORE_STAT); - /* If the link is up, then check the phy side of the xaui link */ - if (efx->link_state.up && link_ok) - if (efx->mdio.mmds & (1 << MDIO_MMD_PHYXS)) - link_ok = efx_mdio_phyxgxs_lane_sync(efx); - return link_ok; } +static bool falcon_xmac_link_ok(struct efx_nic *efx) +{ + /* + * Check MAC's XGXS link status except when using XGMII loopback + * which bypasses the XGXS block. + * If possible, check PHY's XGXS link status except when using + * MAC loopback. + */ + return (efx->loopback_mode == LOOPBACK_XGMII || + falcon_xgxs_link_ok(efx)) && + (!(efx->mdio.mmds & (1 << MDIO_MMD_PHYXS)) || + LOOPBACK_INTERNAL(efx) || + efx_mdio_phyxgxs_lane_sync(efx)); +} + void falcon_reconfigure_xmac_core(struct efx_nic *efx) { unsigned int max_frame_len; @@ -245,9 +251,9 @@ static void falcon_reconfigure_xgxs_core(struct efx_nic *efx) /* Try to bring up the Falcon side of the Falcon-Phy XAUI link */ -static bool falcon_check_xaui_link_up(struct efx_nic *efx, int tries) +static bool falcon_xmac_link_ok_retry(struct efx_nic *efx, int tries) { - bool mac_up = falcon_xaui_link_ok(efx); + bool mac_up = falcon_xmac_link_ok(efx); if (LOOPBACK_MASK(efx) & LOOPBACKS_EXTERNAL(efx) & LOOPBACKS_WS || efx_phy_mode_disabled(efx->phy_mode)) @@ -261,7 +267,7 @@ static bool falcon_check_xaui_link_up(struct efx_nic *efx, int tries) falcon_reset_xaui(efx); udelay(200); - mac_up = falcon_xaui_link_ok(efx); + mac_up = falcon_xmac_link_ok(efx); --tries; } @@ -272,7 +278,7 @@ static bool falcon_check_xaui_link_up(struct efx_nic *efx, int tries) static bool falcon_xmac_check_fault(struct efx_nic *efx) { - return !falcon_check_xaui_link_up(efx, 5); + return !falcon_xmac_link_ok_retry(efx, 5); } static int falcon_reconfigure_xmac(struct efx_nic *efx) @@ -284,7 +290,7 @@ static int falcon_reconfigure_xmac(struct efx_nic *efx) falcon_reconfigure_mac_wrapper(efx); - efx->xmac_poll_required = !falcon_check_xaui_link_up(efx, 5); + efx->xmac_poll_required = !falcon_xmac_link_ok_retry(efx, 5); falcon_mask_status_intr(efx, true); return 0; @@ -357,7 +363,7 @@ void falcon_poll_xmac(struct efx_nic *efx) return; falcon_mask_status_intr(efx, false); - efx->xmac_poll_required = !falcon_check_xaui_link_up(efx, 1); + efx->xmac_poll_required = !falcon_xmac_link_ok_retry(efx, 1); falcon_mask_status_intr(efx, true); } diff --git a/drivers/net/sfc/mcdi_phy.c b/drivers/net/sfc/mcdi_phy.c index 0e1bcc5a0d5..eb694af7a47 100644 --- a/drivers/net/sfc/mcdi_phy.c +++ b/drivers/net/sfc/mcdi_phy.c @@ -304,31 +304,47 @@ static u32 mcdi_to_ethtool_media(u32 media) static int efx_mcdi_phy_probe(struct efx_nic *efx) { - struct efx_mcdi_phy_cfg *phy_cfg; + struct efx_mcdi_phy_cfg *phy_data; + u8 outbuf[MC_CMD_GET_LINK_OUT_LEN]; + u32 caps; int rc; - /* TODO: Move phy_data initialisation to - * phy_op->probe/remove, rather than init/fini */ - phy_cfg = kzalloc(sizeof(*phy_cfg), GFP_KERNEL); - if (phy_cfg == NULL) { - rc = -ENOMEM; - goto fail_alloc; - } - rc = efx_mcdi_get_phy_cfg(efx, phy_cfg); + /* Initialise and populate phy_data */ + phy_data = kzalloc(sizeof(*phy_data), GFP_KERNEL); + if (phy_data == NULL) + return -ENOMEM; + + rc = efx_mcdi_get_phy_cfg(efx, phy_data); if (rc != 0) goto fail; - efx->phy_type = phy_cfg->type; + /* Read initial link advertisement */ + BUILD_BUG_ON(MC_CMD_GET_LINK_IN_LEN != 0); + rc = efx_mcdi_rpc(efx, MC_CMD_GET_LINK, NULL, 0, + outbuf, sizeof(outbuf), NULL); + if (rc) + goto fail; + + /* Fill out nic state */ + efx->phy_data = phy_data; + efx->phy_type = phy_data->type; - efx->mdio_bus = phy_cfg->channel; - efx->mdio.prtad = phy_cfg->port; - efx->mdio.mmds = phy_cfg->mmd_mask & ~(1 << MC_CMD_MMD_CLAUSE22); + efx->mdio_bus = phy_data->channel; + efx->mdio.prtad = phy_data->port; + efx->mdio.mmds = phy_data->mmd_mask & ~(1 << MC_CMD_MMD_CLAUSE22); efx->mdio.mode_support = 0; - if (phy_cfg->mmd_mask & (1 << MC_CMD_MMD_CLAUSE22)) + if (phy_data->mmd_mask & (1 << MC_CMD_MMD_CLAUSE22)) efx->mdio.mode_support |= MDIO_SUPPORTS_C22; - if (phy_cfg->mmd_mask & ~(1 << MC_CMD_MMD_CLAUSE22)) + if (phy_data->mmd_mask & ~(1 << MC_CMD_MMD_CLAUSE22)) efx->mdio.mode_support |= MDIO_SUPPORTS_C45 | MDIO_EMULATE_C22; + caps = MCDI_DWORD(outbuf, GET_LINK_OUT_CAP); + if (caps & (1 << MC_CMD_PHY_CAP_AN_LBN)) + efx->link_advertising = + mcdi_to_ethtool_cap(phy_data->media, caps); + else + phy_data->forced_cap = caps; + /* Assert that we can map efx -> mcdi loopback modes */ BUILD_BUG_ON(LOOPBACK_NONE != MC_CMD_LOOPBACK_NONE); BUILD_BUG_ON(LOOPBACK_DATA != MC_CMD_LOOPBACK_DATA); @@ -365,46 +381,6 @@ static int efx_mcdi_phy_probe(struct efx_nic *efx) * but by convention we don't */ efx->loopback_modes &= ~(1 << LOOPBACK_NONE); - kfree(phy_cfg); - - return 0; - -fail: - kfree(phy_cfg); -fail_alloc: - return rc; -} - -static int efx_mcdi_phy_init(struct efx_nic *efx) -{ - struct efx_mcdi_phy_cfg *phy_data; - u8 outbuf[MC_CMD_GET_LINK_OUT_LEN]; - u32 caps; - int rc; - - phy_data = kzalloc(sizeof(*phy_data), GFP_KERNEL); - if (phy_data == NULL) - return -ENOMEM; - - rc = efx_mcdi_get_phy_cfg(efx, phy_data); - if (rc != 0) - goto fail; - - efx->phy_data = phy_data; - - BUILD_BUG_ON(MC_CMD_GET_LINK_IN_LEN != 0); - rc = efx_mcdi_rpc(efx, MC_CMD_GET_LINK, NULL, 0, - outbuf, sizeof(outbuf), NULL); - if (rc) - goto fail; - - caps = MCDI_DWORD(outbuf, GET_LINK_OUT_CAP); - if (caps & (1 << MC_CMD_PHY_CAP_AN_LBN)) - efx->link_advertising = - mcdi_to_ethtool_cap(phy_data->media, caps); - else - phy_data->forced_cap = caps; - return 0; fail: @@ -504,7 +480,7 @@ static bool efx_mcdi_phy_poll(struct efx_nic *efx) return !efx_link_state_equal(&efx->link_state, &old_state); } -static void efx_mcdi_phy_fini(struct efx_nic *efx) +static void efx_mcdi_phy_remove(struct efx_nic *efx) { struct efx_mcdi_phy_data *phy_data = efx->phy_data; @@ -586,10 +562,11 @@ static int efx_mcdi_phy_set_settings(struct efx_nic *efx, struct ethtool_cmd *ec struct efx_phy_operations efx_mcdi_phy_ops = { .probe = efx_mcdi_phy_probe, - .init = efx_mcdi_phy_init, + .init = efx_port_dummy_op_int, .reconfigure = efx_mcdi_phy_reconfigure, .poll = efx_mcdi_phy_poll, - .fini = efx_mcdi_phy_fini, + .fini = efx_port_dummy_op_void, + .remove = efx_mcdi_phy_remove, .get_settings = efx_mcdi_phy_get_settings, .set_settings = efx_mcdi_phy_set_settings, .run_tests = NULL, diff --git a/drivers/net/sfc/net_driver.h b/drivers/net/sfc/net_driver.h index 34c381f009b..d5aab5b3fa0 100644 --- a/drivers/net/sfc/net_driver.h +++ b/drivers/net/sfc/net_driver.h @@ -524,6 +524,7 @@ struct efx_phy_operations { int (*probe) (struct efx_nic *efx); int (*init) (struct efx_nic *efx); void (*fini) (struct efx_nic *efx); + void (*remove) (struct efx_nic *efx); int (*reconfigure) (struct efx_nic *efx); bool (*poll) (struct efx_nic *efx); void (*get_settings) (struct efx_nic *efx, diff --git a/drivers/net/sfc/nic.c b/drivers/net/sfc/nic.c index a577be22786..db44224ed2c 100644 --- a/drivers/net/sfc/nic.c +++ b/drivers/net/sfc/nic.c @@ -1576,6 +1576,8 @@ void efx_nic_init_common(struct efx_nic *efx) EFX_SET_OWORD_FIELD(temp, FRF_AZ_TX_SOFT_EVT_EN, 1); /* Prefetch threshold 2 => fetch when descriptor cache half empty */ EFX_SET_OWORD_FIELD(temp, FRF_AZ_TX_PREF_THRESHOLD, 2); + /* Disable hardware watchdog which can misfire */ + EFX_SET_OWORD_FIELD(temp, FRF_AZ_TX_PREF_WD_TMR, 0x3fffff); /* Squash TX of packets of 16 bytes or less */ if (efx_nic_rev(efx) >= EFX_REV_FALCON_B0) EFX_SET_OWORD_FIELD(temp, FRF_BZ_TX_FLUSH_MIN_LEN_EN, 1); diff --git a/drivers/net/sfc/qt202x_phy.c b/drivers/net/sfc/qt202x_phy.c index 3800fc791b2..ff8f0a417fa 100644 --- a/drivers/net/sfc/qt202x_phy.c +++ b/drivers/net/sfc/qt202x_phy.c @@ -33,6 +33,9 @@ #define PCS_FW_HEARTBEAT_REG 0xd7ee #define PCS_FW_HEARTB_LBN 0 #define PCS_FW_HEARTB_WIDTH 8 +#define PCS_FW_PRODUCT_CODE_1 0xd7f0 +#define PCS_FW_VERSION_1 0xd7f3 +#define PCS_FW_BUILD_1 0xd7f6 #define PCS_UC8051_STATUS_REG 0xd7fd #define PCS_UC_STATUS_LBN 0 #define PCS_UC_STATUS_WIDTH 8 @@ -52,14 +55,24 @@ void falcon_qt202x_set_led(struct efx_nic *p, int led, int mode) struct qt202x_phy_data { enum efx_phy_mode phy_mode; + bool bug17190_in_bad_state; + unsigned long bug17190_timer; + u32 firmware_ver; }; #define QT2022C2_MAX_RESET_TIME 500 #define QT2022C2_RESET_WAIT 10 -static int qt2025c_wait_reset(struct efx_nic *efx) +#define QT2025C_MAX_HEARTB_TIME (5 * HZ) +#define QT2025C_HEARTB_WAIT 100 +#define QT2025C_MAX_FWSTART_TIME (25 * HZ / 10) +#define QT2025C_FWSTART_WAIT 100 + +#define BUG17190_INTERVAL (2 * HZ) + +static int qt2025c_wait_heartbeat(struct efx_nic *efx) { - unsigned long timeout = jiffies + 10 * HZ; + unsigned long timeout = jiffies + QT2025C_MAX_HEARTB_TIME; int reg, old_counter = 0; /* Wait for firmware heartbeat to start */ @@ -74,11 +87,25 @@ static int qt2025c_wait_reset(struct efx_nic *efx) old_counter = counter; else if (counter != old_counter) break; - if (time_after(jiffies, timeout)) + if (time_after(jiffies, timeout)) { + /* Some cables have EEPROMs that conflict with the + * PHY's on-board EEPROM so it cannot load firmware */ + EFX_ERR(efx, "If an SFP+ direct attach cable is" + " connected, please check that it complies" + " with the SFP+ specification\n"); return -ETIMEDOUT; - msleep(10); + } + msleep(QT2025C_HEARTB_WAIT); } + return 0; +} + +static int qt2025c_wait_fw_status_good(struct efx_nic *efx) +{ + unsigned long timeout = jiffies + QT2025C_MAX_FWSTART_TIME; + int reg; + /* Wait for firmware status to look good */ for (;;) { reg = efx_mdio_read(efx, MDIO_MMD_PCS, PCS_UC8051_STATUS_REG); @@ -90,7 +117,178 @@ static int qt2025c_wait_reset(struct efx_nic *efx) break; if (time_after(jiffies, timeout)) return -ETIMEDOUT; + msleep(QT2025C_FWSTART_WAIT); + } + + return 0; +} + +static void qt2025c_restart_firmware(struct efx_nic *efx) +{ + /* Restart microcontroller execution of firmware from RAM */ + efx_mdio_write(efx, 3, 0xe854, 0x00c0); + efx_mdio_write(efx, 3, 0xe854, 0x0040); + msleep(50); +} + +static int qt2025c_wait_reset(struct efx_nic *efx) +{ + int rc; + + rc = qt2025c_wait_heartbeat(efx); + if (rc != 0) + return rc; + + rc = qt2025c_wait_fw_status_good(efx); + if (rc == -ETIMEDOUT) { + /* Bug 17689: occasionally heartbeat starts but firmware status + * code never progresses beyond 0x00. Try again, once, after + * restarting execution of the firmware image. */ + EFX_LOG(efx, "bashing QT2025C microcontroller\n"); + qt2025c_restart_firmware(efx); + rc = qt2025c_wait_heartbeat(efx); + if (rc != 0) + return rc; + rc = qt2025c_wait_fw_status_good(efx); + } + + return rc; +} + +static void qt2025c_firmware_id(struct efx_nic *efx) +{ + struct qt202x_phy_data *phy_data = efx->phy_data; + u8 firmware_id[9]; + size_t i; + + for (i = 0; i < sizeof(firmware_id); i++) + firmware_id[i] = efx_mdio_read(efx, MDIO_MMD_PCS, + PCS_FW_PRODUCT_CODE_1 + i); + EFX_INFO(efx, "QT2025C firmware %xr%d v%d.%d.%d.%d [20%02d-%02d-%02d]\n", + (firmware_id[0] << 8) | firmware_id[1], firmware_id[2], + firmware_id[3] >> 4, firmware_id[3] & 0xf, + firmware_id[4], firmware_id[5], + firmware_id[6], firmware_id[7], firmware_id[8]); + phy_data->firmware_ver = ((firmware_id[3] & 0xf0) << 20) | + ((firmware_id[3] & 0x0f) << 16) | + (firmware_id[4] << 8) | firmware_id[5]; +} + +static void qt2025c_bug17190_workaround(struct efx_nic *efx) +{ + struct qt202x_phy_data *phy_data = efx->phy_data; + + /* The PHY can get stuck in a state where it reports PHY_XS and PMA/PMD + * layers up, but PCS down (no block_lock). If we notice this state + * persisting for a couple of seconds, we switch PMA/PMD loopback + * briefly on and then off again, which is normally sufficient to + * recover it. + */ + if (efx->link_state.up || + !efx_mdio_links_ok(efx, MDIO_DEVS_PMAPMD | MDIO_DEVS_PHYXS)) { + phy_data->bug17190_in_bad_state = false; + return; + } + + if (!phy_data->bug17190_in_bad_state) { + phy_data->bug17190_in_bad_state = true; + phy_data->bug17190_timer = jiffies + BUG17190_INTERVAL; + return; + } + + if (time_after_eq(jiffies, phy_data->bug17190_timer)) { + EFX_LOG(efx, "bashing QT2025C PMA/PMD\n"); + efx_mdio_set_flag(efx, MDIO_MMD_PMAPMD, MDIO_CTRL1, + MDIO_PMA_CTRL1_LOOPBACK, true); msleep(100); + efx_mdio_set_flag(efx, MDIO_MMD_PMAPMD, MDIO_CTRL1, + MDIO_PMA_CTRL1_LOOPBACK, false); + phy_data->bug17190_timer = jiffies + BUG17190_INTERVAL; + } +} + +static int qt2025c_select_phy_mode(struct efx_nic *efx) +{ + struct qt202x_phy_data *phy_data = efx->phy_data; + struct falcon_board *board = falcon_board(efx); + int reg, rc, i; + uint16_t phy_op_mode; + + /* Only 2.0.1.0+ PHY firmware supports the more optimal SFP+ + * Self-Configure mode. Don't attempt any switching if we encounter + * older firmware. */ + if (phy_data->firmware_ver < 0x02000100) + return 0; + + /* In general we will get optimal behaviour in "SFP+ Self-Configure" + * mode; however, that powers down most of the PHY when no module is + * present, so we must use a different mode (any fixed mode will do) + * to be sure that loopbacks will work. */ + phy_op_mode = (efx->loopback_mode == LOOPBACK_NONE) ? 0x0038 : 0x0020; + + /* Only change mode if really necessary */ + reg = efx_mdio_read(efx, 1, 0xc319); + if ((reg & 0x0038) == phy_op_mode) + return 0; + EFX_LOG(efx, "Switching PHY to mode 0x%04x\n", phy_op_mode); + + /* This sequence replicates the register writes configured in the boot + * EEPROM (including the differences between board revisions), except + * that the operating mode is changed, and the PHY is prevented from + * unnecessarily reloading the main firmware image again. */ + efx_mdio_write(efx, 1, 0xc300, 0x0000); + /* (Note: this portion of the boot EEPROM sequence, which bit-bashes 9 + * STOPs onto the firmware/module I2C bus to reset it, varies across + * board revisions, as the bus is connected to different GPIO/LED + * outputs on the PHY.) */ + if (board->major == 0 && board->minor < 2) { + efx_mdio_write(efx, 1, 0xc303, 0x4498); + for (i = 0; i < 9; i++) { + efx_mdio_write(efx, 1, 0xc303, 0x4488); + efx_mdio_write(efx, 1, 0xc303, 0x4480); + efx_mdio_write(efx, 1, 0xc303, 0x4490); + efx_mdio_write(efx, 1, 0xc303, 0x4498); + } + } else { + efx_mdio_write(efx, 1, 0xc303, 0x0920); + efx_mdio_write(efx, 1, 0xd008, 0x0004); + for (i = 0; i < 9; i++) { + efx_mdio_write(efx, 1, 0xc303, 0x0900); + efx_mdio_write(efx, 1, 0xd008, 0x0005); + efx_mdio_write(efx, 1, 0xc303, 0x0920); + efx_mdio_write(efx, 1, 0xd008, 0x0004); + } + efx_mdio_write(efx, 1, 0xc303, 0x4900); + } + efx_mdio_write(efx, 1, 0xc303, 0x4900); + efx_mdio_write(efx, 1, 0xc302, 0x0004); + efx_mdio_write(efx, 1, 0xc316, 0x0013); + efx_mdio_write(efx, 1, 0xc318, 0x0054); + efx_mdio_write(efx, 1, 0xc319, phy_op_mode); + efx_mdio_write(efx, 1, 0xc31a, 0x0098); + efx_mdio_write(efx, 3, 0x0026, 0x0e00); + efx_mdio_write(efx, 3, 0x0027, 0x0013); + efx_mdio_write(efx, 3, 0x0028, 0xa528); + efx_mdio_write(efx, 1, 0xd006, 0x000a); + efx_mdio_write(efx, 1, 0xd007, 0x0009); + efx_mdio_write(efx, 1, 0xd008, 0x0004); + /* This additional write is not present in the boot EEPROM. It + * prevents the PHY's internal boot ROM doing another pointless (and + * slow) reload of the firmware image (the microcontroller's code + * memory is not affected by the microcontroller reset). */ + efx_mdio_write(efx, 1, 0xc317, 0x00ff); + efx_mdio_write(efx, 1, 0xc300, 0x0002); + msleep(20); + + /* Restart microcontroller execution of firmware from RAM */ + qt2025c_restart_firmware(efx); + + /* Wait for the microcontroller to be ready again */ + rc = qt2025c_wait_reset(efx); + if (rc < 0) { + EFX_ERR(efx, "PHY microcontroller reset during mode switch " + "timed out\n"); + return rc; } return 0; @@ -137,6 +335,16 @@ static int qt202x_reset_phy(struct efx_nic *efx) static int qt202x_phy_probe(struct efx_nic *efx) { + struct qt202x_phy_data *phy_data; + + phy_data = kzalloc(sizeof(struct qt202x_phy_data), GFP_KERNEL); + if (!phy_data) + return -ENOMEM; + efx->phy_data = phy_data; + phy_data->phy_mode = efx->phy_mode; + phy_data->bug17190_in_bad_state = false; + phy_data->bug17190_timer = 0; + efx->mdio.mmds = QT202X_REQUIRED_DEVS; efx->mdio.mode_support = MDIO_SUPPORTS_C45 | MDIO_EMULATE_C22; efx->loopback_modes = QT202X_LOOPBACKS | FALCON_XMAC_LOOPBACKS; @@ -145,7 +353,6 @@ static int qt202x_phy_probe(struct efx_nic *efx) static int qt202x_phy_init(struct efx_nic *efx) { - struct qt202x_phy_data *phy_data; u32 devid; int rc; @@ -155,17 +362,14 @@ static int qt202x_phy_init(struct efx_nic *efx) return rc; } - phy_data = kzalloc(sizeof(struct qt202x_phy_data), GFP_KERNEL); - if (!phy_data) - return -ENOMEM; - efx->phy_data = phy_data; - devid = efx_mdio_read_id(efx, MDIO_MMD_PHYXS); EFX_INFO(efx, "PHY ID reg %x (OUI %06x model %02x revision %x)\n", devid, efx_mdio_id_oui(devid), efx_mdio_id_model(devid), efx_mdio_id_rev(devid)); - phy_data->phy_mode = efx->phy_mode; + if (efx->phy_type == PHY_TYPE_QT2025C) + qt2025c_firmware_id(efx); + return 0; } @@ -183,6 +387,9 @@ static bool qt202x_phy_poll(struct efx_nic *efx) efx->link_state.fd = true; efx->link_state.fc = efx->wanted_fc; + if (efx->phy_type == PHY_TYPE_QT2025C) + qt2025c_bug17190_workaround(efx); + return efx->link_state.up != was_up; } @@ -191,6 +398,10 @@ static int qt202x_phy_reconfigure(struct efx_nic *efx) struct qt202x_phy_data *phy_data = efx->phy_data; if (efx->phy_type == PHY_TYPE_QT2025C) { + int rc = qt2025c_select_phy_mode(efx); + if (rc) + return rc; + /* There are several different register bits which can * disable TX (and save power) on direct-attach cables * or optical transceivers, varying somewhat between @@ -224,7 +435,7 @@ static void qt202x_phy_get_settings(struct efx_nic *efx, struct ethtool_cmd *ecm mdio45_ethtool_gset(&efx->mdio, ecmd); } -static void qt202x_phy_fini(struct efx_nic *efx) +static void qt202x_phy_remove(struct efx_nic *efx) { /* Free the context block */ kfree(efx->phy_data); @@ -236,7 +447,8 @@ struct efx_phy_operations falcon_qt202x_phy_ops = { .init = qt202x_phy_init, .reconfigure = qt202x_phy_reconfigure, .poll = qt202x_phy_poll, - .fini = qt202x_phy_fini, + .fini = efx_port_dummy_op_void, + .remove = qt202x_phy_remove, .get_settings = qt202x_phy_get_settings, .set_settings = efx_mdio_set_settings, }; diff --git a/drivers/net/sfc/siena.c b/drivers/net/sfc/siena.c index de07a4f031b..f8c6771e66d 100644 --- a/drivers/net/sfc/siena.c +++ b/drivers/net/sfc/siena.c @@ -133,6 +133,7 @@ static int siena_probe_port(struct efx_nic *efx) void siena_remove_port(struct efx_nic *efx) { + efx->phy_op->remove(efx); efx_nic_free_buffer(efx, &efx->stats_buffer); } diff --git a/drivers/net/sfc/tenxpress.c b/drivers/net/sfc/tenxpress.c index ca11572a49a..3009c297c13 100644 --- a/drivers/net/sfc/tenxpress.c +++ b/drivers/net/sfc/tenxpress.c @@ -202,10 +202,14 @@ static ssize_t set_phy_short_reach(struct device *dev, int rc; rtnl_lock(); - efx_mdio_set_flag(efx, MDIO_MMD_PMAPMD, MDIO_PMA_10GBT_TXPWR, - MDIO_PMA_10GBT_TXPWR_SHORT, - count != 0 && *buf != '0'); - rc = efx_reconfigure_port(efx); + if (efx->state != STATE_RUNNING) { + rc = -EBUSY; + } else { + efx_mdio_set_flag(efx, MDIO_MMD_PMAPMD, MDIO_PMA_10GBT_TXPWR, + MDIO_PMA_10GBT_TXPWR_SHORT, + count != 0 && *buf != '0'); + rc = efx_reconfigure_port(efx); + } rtnl_unlock(); return rc < 0 ? rc : (ssize_t)count; @@ -298,36 +302,62 @@ static int tenxpress_init(struct efx_nic *efx) return 0; } -static int sfx7101_phy_probe(struct efx_nic *efx) +static int tenxpress_phy_probe(struct efx_nic *efx) { - efx->mdio.mmds = TENXPRESS_REQUIRED_DEVS; - efx->mdio.mode_support = MDIO_SUPPORTS_C45 | MDIO_EMULATE_C22; - efx->loopback_modes = SFX7101_LOOPBACKS | FALCON_XMAC_LOOPBACKS; - return 0; -} + struct tenxpress_phy_data *phy_data; + int rc; + + /* Allocate phy private storage */ + phy_data = kzalloc(sizeof(*phy_data), GFP_KERNEL); + if (!phy_data) + return -ENOMEM; + efx->phy_data = phy_data; + phy_data->phy_mode = efx->phy_mode; + + /* Create any special files */ + if (efx->phy_type == PHY_TYPE_SFT9001B) { + rc = device_create_file(&efx->pci_dev->dev, + &dev_attr_phy_short_reach); + if (rc) + goto fail; + } + + if (efx->phy_type == PHY_TYPE_SFX7101) { + efx->mdio.mmds = TENXPRESS_REQUIRED_DEVS; + efx->mdio.mode_support = MDIO_SUPPORTS_C45; + + efx->loopback_modes = SFX7101_LOOPBACKS | FALCON_XMAC_LOOPBACKS; + + efx->link_advertising = (ADVERTISED_TP | ADVERTISED_Autoneg | + ADVERTISED_10000baseT_Full); + } else { + efx->mdio.mmds = TENXPRESS_REQUIRED_DEVS; + efx->mdio.mode_support = MDIO_SUPPORTS_C45 | MDIO_EMULATE_C22; + + efx->loopback_modes = (SFT9001_LOOPBACKS | + FALCON_XMAC_LOOPBACKS | + FALCON_GMAC_LOOPBACKS); + + efx->link_advertising = (ADVERTISED_TP | ADVERTISED_Autoneg | + ADVERTISED_10000baseT_Full | + ADVERTISED_1000baseT_Full | + ADVERTISED_100baseT_Full); + } -static int sft9001_phy_probe(struct efx_nic *efx) -{ - efx->mdio.mmds = TENXPRESS_REQUIRED_DEVS; - efx->mdio.mode_support = MDIO_SUPPORTS_C45 | MDIO_EMULATE_C22; - efx->loopback_modes = (SFT9001_LOOPBACKS | FALCON_XMAC_LOOPBACKS | - FALCON_GMAC_LOOPBACKS); return 0; + +fail: + kfree(efx->phy_data); + efx->phy_data = NULL; + return rc; } static int tenxpress_phy_init(struct efx_nic *efx) { - struct tenxpress_phy_data *phy_data; - int rc = 0; + int rc; falcon_board(efx)->type->init_phy(efx); - phy_data = kzalloc(sizeof(*phy_data), GFP_KERNEL); - if (!phy_data) - return -ENOMEM; - efx->phy_data = phy_data; - phy_data->phy_mode = efx->phy_mode; - if (!(efx->phy_mode & PHY_MODE_SPECIAL)) { if (efx->phy_type == PHY_TYPE_SFT9001A) { int reg; @@ -341,44 +371,27 @@ static int tenxpress_phy_init(struct efx_nic *efx) rc = efx_mdio_wait_reset_mmds(efx, TENXPRESS_REQUIRED_DEVS); if (rc < 0) - goto fail; + return rc; rc = efx_mdio_check_mmds(efx, TENXPRESS_REQUIRED_DEVS, 0); if (rc < 0) - goto fail; + return rc; } rc = tenxpress_init(efx); if (rc < 0) - goto fail; + return rc; - /* Initialise advertising flags */ - efx->link_advertising = (ADVERTISED_TP | ADVERTISED_Autoneg | - ADVERTISED_10000baseT_Full); - if (efx->phy_type != PHY_TYPE_SFX7101) - efx->link_advertising |= (ADVERTISED_1000baseT_Full | - ADVERTISED_100baseT_Full); + /* Reinitialise flow control settings */ efx_link_set_wanted_fc(efx, efx->wanted_fc); efx_mdio_an_reconfigure(efx); - if (efx->phy_type == PHY_TYPE_SFT9001B) { - rc = device_create_file(&efx->pci_dev->dev, - &dev_attr_phy_short_reach); - if (rc) - goto fail; - } - schedule_timeout_uninterruptible(HZ / 5); /* 200ms */ /* Let XGXS and SerDes out of reset */ falcon_reset_xaui(efx); return 0; - - fail: - kfree(efx->phy_data); - efx->phy_data = NULL; - return rc; } /* Perform a "special software reset" on the PHY. The caller is @@ -589,25 +602,26 @@ static bool tenxpress_phy_poll(struct efx_nic *efx) return !efx_link_state_equal(&efx->link_state, &old_state); } -static void tenxpress_phy_fini(struct efx_nic *efx) +static void sfx7101_phy_fini(struct efx_nic *efx) { int reg; + /* Power down the LNPGA */ + reg = (1 << PMA_PMD_LNPGA_POWERDOWN_LBN); + efx_mdio_write(efx, MDIO_MMD_PMAPMD, PMA_PMD_XCONTROL_REG, reg); + + /* Waiting here ensures that the board fini, which can turn + * off the power to the PHY, won't get run until the LNPGA + * powerdown has been given long enough to complete. */ + schedule_timeout_uninterruptible(LNPGA_PDOWN_WAIT); /* 200 ms */ +} + +static void tenxpress_phy_remove(struct efx_nic *efx) +{ if (efx->phy_type == PHY_TYPE_SFT9001B) device_remove_file(&efx->pci_dev->dev, &dev_attr_phy_short_reach); - if (efx->phy_type == PHY_TYPE_SFX7101) { - /* Power down the LNPGA */ - reg = (1 << PMA_PMD_LNPGA_POWERDOWN_LBN); - efx_mdio_write(efx, MDIO_MMD_PMAPMD, PMA_PMD_XCONTROL_REG, reg); - - /* Waiting here ensures that the board fini, which can turn - * off the power to the PHY, won't get run until the LNPGA - * powerdown has been given long enough to complete. */ - schedule_timeout_uninterruptible(LNPGA_PDOWN_WAIT); /* 200 ms */ - } - kfree(efx->phy_data); efx->phy_data = NULL; } @@ -819,11 +833,12 @@ static void sft9001_set_npage_adv(struct efx_nic *efx, u32 advertising) } struct efx_phy_operations falcon_sfx7101_phy_ops = { - .probe = sfx7101_phy_probe, + .probe = tenxpress_phy_probe, .init = tenxpress_phy_init, .reconfigure = tenxpress_phy_reconfigure, .poll = tenxpress_phy_poll, - .fini = tenxpress_phy_fini, + .fini = sfx7101_phy_fini, + .remove = tenxpress_phy_remove, .get_settings = tenxpress_get_settings, .set_settings = tenxpress_set_settings, .set_npage_adv = sfx7101_set_npage_adv, @@ -832,11 +847,12 @@ struct efx_phy_operations falcon_sfx7101_phy_ops = { }; struct efx_phy_operations falcon_sft9001_phy_ops = { - .probe = sft9001_phy_probe, + .probe = tenxpress_phy_probe, .init = tenxpress_phy_init, .reconfigure = tenxpress_phy_reconfigure, .poll = tenxpress_phy_poll, - .fini = tenxpress_phy_fini, + .fini = efx_port_dummy_op_void, + .remove = tenxpress_phy_remove, .get_settings = tenxpress_get_settings, .set_settings = tenxpress_set_settings, .set_npage_adv = sft9001_set_npage_adv, diff --git a/drivers/net/sfc/tx.c b/drivers/net/sfc/tx.c index e669f94e821..a8b70ef6d81 100644 --- a/drivers/net/sfc/tx.c +++ b/drivers/net/sfc/tx.c @@ -821,8 +821,6 @@ static void efx_enqueue_unwind(struct efx_tx_queue *tx_queue) EFX_TXQ_MASK]; efx_tsoh_free(tx_queue, buffer); EFX_BUG_ON_PARANOID(buffer->skb); - buffer->len = 0; - buffer->continuation = true; if (buffer->unmap_len) { unmap_addr = (buffer->dma_addr + buffer->len - buffer->unmap_len); @@ -836,6 +834,8 @@ static void efx_enqueue_unwind(struct efx_tx_queue *tx_queue) PCI_DMA_TODEVICE); buffer->unmap_len = 0; } + buffer->len = 0; + buffer->continuation = true; } } diff --git a/drivers/net/tun.c b/drivers/net/tun.c index 01e99f22210..2834a01bae2 100644 --- a/drivers/net/tun.c +++ b/drivers/net/tun.c @@ -849,13 +849,13 @@ static void tun_sock_write_space(struct sock *sk) if (sk->sk_sleep && waitqueue_active(sk->sk_sleep)) wake_up_interruptible_sync(sk->sk_sleep); - tun = container_of(sk, struct tun_sock, sk)->tun; + tun = tun_sk(sk)->tun; kill_fasync(&tun->fasync, SIGIO, POLL_OUT); } static void tun_sock_destruct(struct sock *sk) { - free_netdev(container_of(sk, struct tun_sock, sk)->tun->dev); + free_netdev(tun_sk(sk)->tun->dev); } static struct proto tun_proto = { @@ -990,7 +990,7 @@ static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr) sk->sk_write_space = tun_sock_write_space; sk->sk_sndbuf = INT_MAX; - container_of(sk, struct tun_sock, sk)->tun = tun; + tun_sk(sk)->tun = tun; security_tun_dev_post_create(sk); diff --git a/drivers/net/ucc_geth.c b/drivers/net/ucc_geth.c index afaf088b72e..41ad2f3697c 100644 --- a/drivers/net/ucc_geth.c +++ b/drivers/net/ucc_geth.c @@ -1563,7 +1563,10 @@ static int ugeth_disable(struct ucc_geth_private *ugeth, enum comm_dir mode) static void ugeth_quiesce(struct ucc_geth_private *ugeth) { - /* Wait for and prevent any further xmits. */ + /* Prevent any further xmits, plus detach the device. */ + netif_device_detach(ugeth->ndev); + + /* Wait for any current xmits to finish. */ netif_tx_disable(ugeth->ndev); /* Disable the interrupt to avoid NAPI rescheduling. */ @@ -1577,7 +1580,7 @@ static void ugeth_activate(struct ucc_geth_private *ugeth) { napi_enable(&ugeth->napi); enable_irq(ugeth->ug_info->uf_info.irq); - netif_tx_wake_all_queues(ugeth->ndev); + netif_device_attach(ugeth->ndev); } /* Called every time the controller might need to be made @@ -1648,25 +1651,28 @@ static void adjust_link(struct net_device *dev) ugeth->oldspeed = phydev->speed; } - /* - * To change the MAC configuration we need to disable the - * controller. To do so, we have to either grab ugeth->lock, - * which is a bad idea since 'graceful stop' commands might - * take quite a while, or we can quiesce driver's activity. - */ - ugeth_quiesce(ugeth); - ugeth_disable(ugeth, COMM_DIR_RX_AND_TX); - - out_be32(&ug_regs->maccfg2, tempval); - out_be32(&uf_regs->upsmr, upsmr); - - ugeth_enable(ugeth, COMM_DIR_RX_AND_TX); - ugeth_activate(ugeth); - if (!ugeth->oldlink) { new_state = 1; ugeth->oldlink = 1; } + + if (new_state) { + /* + * To change the MAC configuration we need to disable + * the controller. To do so, we have to either grab + * ugeth->lock, which is a bad idea since 'graceful + * stop' commands might take quite a while, or we can + * quiesce driver's activity. + */ + ugeth_quiesce(ugeth); + ugeth_disable(ugeth, COMM_DIR_RX_AND_TX); + + out_be32(&ug_regs->maccfg2, tempval); + out_be32(&uf_regs->upsmr, upsmr); + + ugeth_enable(ugeth, COMM_DIR_RX_AND_TX); + ugeth_activate(ugeth); + } } else if (ugeth->oldlink) { new_state = 1; ugeth->oldlink = 0; @@ -3273,7 +3279,7 @@ static int ucc_geth_tx(struct net_device *dev, u8 txQ) /* Handle the transmitted buffer and release */ /* the BD to be used with the current frame */ - if ((bd == ugeth->txBd[txQ]) && (netif_queue_stopped(dev) == 0)) + if (bd == ugeth->txBd[txQ]) /* queue empty? */ break; dev->stats.tx_packets++; diff --git a/drivers/net/via-rhine.c b/drivers/net/via-rhine.c index 593e01f64e9..611b8043595 100644 --- a/drivers/net/via-rhine.c +++ b/drivers/net/via-rhine.c @@ -102,6 +102,7 @@ static const int multicast_filter_limit = 32; #include <linux/ethtool.h> #include <linux/crc32.h> #include <linux/bitops.h> +#include <linux/workqueue.h> #include <asm/processor.h> /* Processor type for cache alignment. */ #include <asm/io.h> #include <asm/irq.h> @@ -389,6 +390,7 @@ struct rhine_private { struct net_device *dev; struct napi_struct napi; spinlock_t lock; + struct work_struct reset_task; /* Frequently used values: keep some adjacent for cache effect. */ u32 quirks; @@ -407,6 +409,7 @@ struct rhine_private { static int mdio_read(struct net_device *dev, int phy_id, int location); static void mdio_write(struct net_device *dev, int phy_id, int location, int value); static int rhine_open(struct net_device *dev); +static void rhine_reset_task(struct work_struct *work); static void rhine_tx_timeout(struct net_device *dev); static netdev_tx_t rhine_start_tx(struct sk_buff *skb, struct net_device *dev); @@ -775,6 +778,8 @@ static int __devinit rhine_init_one(struct pci_dev *pdev, dev->irq = pdev->irq; spin_lock_init(&rp->lock); + INIT_WORK(&rp->reset_task, rhine_reset_task); + rp->mii_if.dev = dev; rp->mii_if.mdio_read = mdio_read; rp->mii_if.mdio_write = mdio_write; @@ -1179,22 +1184,18 @@ static int rhine_open(struct net_device *dev) return 0; } -static void rhine_tx_timeout(struct net_device *dev) +static void rhine_reset_task(struct work_struct *work) { - struct rhine_private *rp = netdev_priv(dev); - void __iomem *ioaddr = rp->base; - - printk(KERN_WARNING "%s: Transmit timed out, status %4.4x, PHY status " - "%4.4x, resetting...\n", - dev->name, ioread16(ioaddr + IntrStatus), - mdio_read(dev, rp->mii_if.phy_id, MII_BMSR)); + struct rhine_private *rp = container_of(work, struct rhine_private, + reset_task); + struct net_device *dev = rp->dev; /* protect against concurrent rx interrupts */ disable_irq(rp->pdev->irq); napi_disable(&rp->napi); - spin_lock(&rp->lock); + spin_lock_bh(&rp->lock); /* clear all descriptors */ free_tbufs(dev); @@ -1206,7 +1207,7 @@ static void rhine_tx_timeout(struct net_device *dev) rhine_chip_reset(dev); init_registers(dev); - spin_unlock(&rp->lock); + spin_unlock_bh(&rp->lock); enable_irq(rp->pdev->irq); dev->trans_start = jiffies; @@ -1214,6 +1215,19 @@ static void rhine_tx_timeout(struct net_device *dev) netif_wake_queue(dev); } +static void rhine_tx_timeout(struct net_device *dev) +{ + struct rhine_private *rp = netdev_priv(dev); + void __iomem *ioaddr = rp->base; + + printk(KERN_WARNING "%s: Transmit timed out, status %4.4x, PHY status " + "%4.4x, resetting...\n", + dev->name, ioread16(ioaddr + IntrStatus), + mdio_read(dev, rp->mii_if.phy_id, MII_BMSR)); + + schedule_work(&rp->reset_task); +} + static netdev_tx_t rhine_start_tx(struct sk_buff *skb, struct net_device *dev) { @@ -1830,10 +1844,11 @@ static int rhine_close(struct net_device *dev) struct rhine_private *rp = netdev_priv(dev); void __iomem *ioaddr = rp->base; - spin_lock_irq(&rp->lock); - - netif_stop_queue(dev); napi_disable(&rp->napi); + cancel_work_sync(&rp->reset_task); + netif_stop_queue(dev); + + spin_lock_irq(&rp->lock); if (debug > 1) printk(KERN_DEBUG "%s: Shutting down ethercard, " diff --git a/drivers/net/vxge/vxge-main.c b/drivers/net/vxge/vxge-main.c index f1c4b2a1e86..0fdfd58a35a 100644 --- a/drivers/net/vxge/vxge-main.c +++ b/drivers/net/vxge/vxge-main.c @@ -4087,21 +4087,21 @@ vxge_probe(struct pci_dev *pdev, const struct pci_device_id *pre) goto _exit0; } - if (!pci_set_dma_mask(pdev, 0xffffffffffffffffULL)) { + if (!pci_set_dma_mask(pdev, DMA_BIT_MASK(64))) { vxge_debug_ll_config(VXGE_TRACE, "%s : using 64bit DMA", __func__); high_dma = 1; if (pci_set_consistent_dma_mask(pdev, - 0xffffffffffffffffULL)) { + DMA_BIT_MASK(64))) { vxge_debug_init(VXGE_ERR, "%s : unable to obtain 64bit DMA for " "consistent allocations", __func__); ret = -ENOMEM; goto _exit1; } - } else if (!pci_set_dma_mask(pdev, 0xffffffffUL)) { + } else if (!pci_set_dma_mask(pdev, DMA_BIT_MASK(32))) { vxge_debug_ll_config(VXGE_TRACE, "%s : using 32bit DMA", __func__); } else { diff --git a/drivers/net/wireless/ath/ath5k/base.c b/drivers/net/wireless/ath/ath5k/base.c index a4c086f069b..e63b7c40d0e 100644 --- a/drivers/net/wireless/ath/ath5k/base.c +++ b/drivers/net/wireless/ath/ath5k/base.c @@ -1903,17 +1903,6 @@ accept: rxs->noise = sc->ah->ah_noise_floor; rxs->signal = rxs->noise + rs.rs_rssi; - /* An rssi of 35 indicates you should be able use - * 54 Mbps reliably. A more elaborate scheme can be used - * here but it requires a map of SNR/throughput for each - * possible mode used */ - rxs->qual = rs.rs_rssi * 100 / 35; - - /* rssi can be more than 35 though, anything above that - * should be considered at 100% */ - if (rxs->qual > 100) - rxs->qual = 100; - rxs->antenna = rs.rs_antenna; rxs->rate_idx = ath5k_hw_to_driver_rix(sc, rs.rs_rate); rxs->flag |= ath5k_rx_decrypted(sc, ds, skb, &rs); @@ -2381,6 +2370,9 @@ ath5k_init(struct ath5k_softc *sc) */ ath5k_stop_locked(sc); + /* Set PHY calibration interval */ + ah->ah_cal_intval = ath5k_calinterval; + /* * The basic interface to setting the hardware in a good * state is ``reset''. On return the hardware is known to @@ -2408,10 +2400,6 @@ ath5k_init(struct ath5k_softc *sc) /* Set ack to be sent at low bit-rates */ ath5k_hw_set_ack_bitrate_high(ah, false); - - /* Set PHY calibration inteval */ - ah->ah_cal_intval = ath5k_calinterval; - ret = 0; done: mmiowb(); diff --git a/drivers/net/wireless/ath/ath9k/mac.c b/drivers/net/wireless/ath/ath9k/mac.c index 71b84d91dcf..efc420cd42b 100644 --- a/drivers/net/wireless/ath/ath9k/mac.c +++ b/drivers/net/wireless/ath/ath9k/mac.c @@ -186,7 +186,7 @@ bool ath9k_hw_stoptxdma(struct ath_hw *ah, u32 q) wait = wait_time; while (ath9k_hw_numtxpending(ah, q)) { if ((--wait) == 0) { - ath_print(common, ATH_DBG_QUEUE, + ath_print(common, ATH_DBG_FATAL, "Failed to stop TX DMA in 100 " "msec after killing last frame\n"); break; diff --git a/drivers/net/wireless/ath/ath9k/mac.h b/drivers/net/wireless/ath/ath9k/mac.h index 0c87771383f..e185479e295 100644 --- a/drivers/net/wireless/ath/ath9k/mac.h +++ b/drivers/net/wireless/ath/ath9k/mac.h @@ -77,6 +77,9 @@ #define ATH9K_TXERR_XTXOP 0x08 #define ATH9K_TXERR_TIMER_EXPIRED 0x10 #define ATH9K_TX_ACKED 0x20 +#define ATH9K_TXERR_MASK \ + (ATH9K_TXERR_XRETRY | ATH9K_TXERR_FILT | ATH9K_TXERR_FIFO | \ + ATH9K_TXERR_XTXOP | ATH9K_TXERR_TIMER_EXPIRED) #define ATH9K_TX_BA 0x01 #define ATH9K_TX_PWRMGMT 0x02 diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index c4874345251..996eb90263c 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c @@ -1973,6 +1973,9 @@ int ath_reset(struct ath_softc *sc, bool retry_tx) struct ieee80211_hw *hw = sc->hw; int r; + /* Stop ANI */ + del_timer_sync(&common->ani.timer); + ath9k_hw_set_interrupts(ah, 0); ath_drain_all_txq(sc, retry_tx); ath_stoprecv(sc); @@ -2014,6 +2017,9 @@ int ath_reset(struct ath_softc *sc, bool retry_tx) } } + /* Start ANI */ + ath_start_ani(common); + return r; } @@ -2508,6 +2514,9 @@ static void ath9k_stop(struct ieee80211_hw *hw) return; /* another wiphy still in use */ } + /* Ensure HW is awake when we try to shut it down. */ + ath9k_ps_wakeup(sc); + if (ah->btcoex_hw.enabled) { ath9k_hw_btcoex_disable(ah); if (ah->btcoex_hw.scheme == ATH_BTCOEX_CFG_3WIRE) @@ -2528,6 +2537,9 @@ static void ath9k_stop(struct ieee80211_hw *hw) /* disable HAL and put h/w to sleep */ ath9k_hw_disable(ah); ath9k_hw_configpcipowersave(ah, 1, 1); + ath9k_ps_restore(sc); + + /* Finally, put the chip in FULL SLEEP mode */ ath9k_setpower(sc, ATH9K_PM_FULL_SLEEP); sc->sc_flags |= SC_OP_INVALID; @@ -2641,8 +2653,10 @@ static void ath9k_remove_interface(struct ieee80211_hw *hw, if ((sc->sc_ah->opmode == NL80211_IFTYPE_AP) || (sc->sc_ah->opmode == NL80211_IFTYPE_ADHOC) || (sc->sc_ah->opmode == NL80211_IFTYPE_MESH_POINT)) { + ath9k_ps_wakeup(sc); ath9k_hw_stoptxdma(sc->sc_ah, sc->beacon.beaconq); ath_beacon_return(sc, avp); + ath9k_ps_restore(sc); } sc->sc_flags &= ~SC_OP_BEACONS; @@ -3091,15 +3105,21 @@ static int ath9k_ampdu_action(struct ieee80211_hw *hw, case IEEE80211_AMPDU_RX_STOP: break; case IEEE80211_AMPDU_TX_START: + ath9k_ps_wakeup(sc); ath_tx_aggr_start(sc, sta, tid, ssn); ieee80211_start_tx_ba_cb_irqsafe(vif, sta->addr, tid); + ath9k_ps_restore(sc); break; case IEEE80211_AMPDU_TX_STOP: + ath9k_ps_wakeup(sc); ath_tx_aggr_stop(sc, sta, tid); ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid); + ath9k_ps_restore(sc); break; case IEEE80211_AMPDU_TX_OPERATIONAL: + ath9k_ps_wakeup(sc); ath_tx_aggr_resume(sc, sta, tid); + ath9k_ps_restore(sc); break; default: ath_print(ath9k_hw_common(sc->sc_ah), ATH_DBG_FATAL, diff --git a/drivers/net/wireless/ath/ath9k/pci.c b/drivers/net/wireless/ath/ath9k/pci.c index 5321f735e5a..f7af5ea5475 100644 --- a/drivers/net/wireless/ath/ath9k/pci.c +++ b/drivers/net/wireless/ath/ath9k/pci.c @@ -96,7 +96,7 @@ static void ath_pci_bt_coex_prep(struct ath_common *common) pci_write_config_byte(pdev, ATH_PCIE_CAP_LINK_CTRL, aspm); } -const static struct ath_bus_ops ath_pci_bus_ops = { +static const struct ath_bus_ops ath_pci_bus_ops = { .read_cachesize = ath_pci_read_cachesize, .cleanup = ath_pci_cleanup, .eeprom_read = ath_pci_eeprom_read, diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c index 2a11cc57cee..fa12b9060b0 100644 --- a/drivers/net/wireless/ath/ath9k/xmit.c +++ b/drivers/net/wireless/ath/ath9k/xmit.c @@ -1108,11 +1108,11 @@ void ath_drain_all_txq(struct ath_softc *sc, bool retry_tx) if (npend) { int r; - ath_print(common, ATH_DBG_XMIT, + ath_print(common, ATH_DBG_FATAL, "Unable to stop TxDMA. Reset HAL!\n"); spin_lock_bh(&sc->sc_resetlock); - r = ath9k_hw_reset(ah, sc->sc_ah->curchan, true); + r = ath9k_hw_reset(ah, sc->sc_ah->curchan, false); if (r) ath_print(common, ATH_DBG_FATAL, "Unable to reset hardware; reset status %d\n", @@ -1414,17 +1414,9 @@ static void assign_aggr_tid_seqno(struct sk_buff *skb, * For HT capable stations, we save tidno for later use. * We also override seqno set by upper layer with the one * in tx aggregation state. - * - * If fragmentation is on, the sequence number is - * not overridden, since it has been - * incremented by the fragmentation routine. - * - * FIXME: check if the fragmentation threshold exceeds - * IEEE80211 max. */ tid = ATH_AN_2_TID(an, bf->bf_tidno); - hdr->seq_ctrl = cpu_to_le16(tid->seq_next << - IEEE80211_SEQ_SEQ_SHIFT); + hdr->seq_ctrl = cpu_to_le16(tid->seq_next << IEEE80211_SEQ_SEQ_SHIFT); bf->bf_seqno = tid->seq_next; INCR(tid->seq_next, IEEE80211_SEQ_MAX); } @@ -1636,7 +1628,8 @@ static int ath_tx_setup_buffer(struct ieee80211_hw *hw, struct ath_buf *bf, bf->bf_keyix = ATH9K_TXKEYIX_INVALID; } - if (ieee80211_is_data_qos(fc) && (sc->sc_flags & SC_OP_TXAGGR)) + if (ieee80211_is_data_qos(fc) && bf_isht(bf) && + (sc->sc_flags & SC_OP_TXAGGR)) assign_aggr_tid_seqno(skb, bf); bf->bf_mpdu = skb; @@ -1780,7 +1773,8 @@ void ath_tx_cabq(struct ieee80211_hw *hw, struct sk_buff *skb) struct ath_wiphy *aphy = hw->priv; struct ath_softc *sc = aphy->sc; struct ath_common *common = ath9k_hw_common(sc->sc_ah); - int hdrlen, padsize; + struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; + int padpos, padsize; struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); struct ath_tx_control txctl; @@ -1792,7 +1786,6 @@ void ath_tx_cabq(struct ieee80211_hw *hw, struct sk_buff *skb) * BSSes. */ if (info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) { - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; if (info->flags & IEEE80211_TX_CTL_FIRST_FRAGMENT) sc->tx.seq_no += 0x10; hdr->seq_ctrl &= cpu_to_le16(IEEE80211_SCTL_FRAG); @@ -1800,9 +1793,9 @@ void ath_tx_cabq(struct ieee80211_hw *hw, struct sk_buff *skb) } /* Add the padding after the header if this is not already done */ - hdrlen = ieee80211_get_hdrlen_from_skb(skb); - if (hdrlen & 3) { - padsize = hdrlen % 4; + padpos = ath9k_cmn_padpos(hdr->frame_control); + padsize = padpos & 3; + if (padsize && skb->len>padpos) { if (skb_headroom(skb) < padsize) { ath_print(common, ATH_DBG_XMIT, "TX CABQ padding failed\n"); @@ -1810,7 +1803,7 @@ void ath_tx_cabq(struct ieee80211_hw *hw, struct sk_buff *skb) return; } skb_push(skb, padsize); - memmove(skb->data, skb->data + padsize, hdrlen); + memmove(skb->data, skb->data + padsize, padpos); } txctl.txq = sc->beacon.cabq; @@ -1838,7 +1831,8 @@ static void ath_tx_complete(struct ath_softc *sc, struct sk_buff *skb, struct ieee80211_hw *hw = sc->hw; struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); struct ath_common *common = ath9k_hw_common(sc->sc_ah); - int hdrlen, padsize; + struct ieee80211_hdr * hdr = (struct ieee80211_hdr *)skb->data; + int padpos, padsize; ath_print(common, ATH_DBG_XMIT, "TX complete: skb: %p\n", skb); @@ -1853,14 +1847,14 @@ static void ath_tx_complete(struct ath_softc *sc, struct sk_buff *skb, tx_info->flags |= IEEE80211_TX_STAT_ACK; } - hdrlen = ieee80211_get_hdrlen_from_skb(skb); - padsize = hdrlen & 3; - if (padsize && hdrlen >= 24) { + padpos = ath9k_cmn_padpos(hdr->frame_control); + padsize = padpos & 3; + if (padsize && skb->len>padpos+padsize) { /* * Remove MAC header padding before giving the frame back to * mac80211. */ - memmove(skb->data + padsize, skb->data, hdrlen); + memmove(skb->data + padsize, skb->data, padpos); skb_pull(skb, padsize); } @@ -2078,7 +2072,7 @@ static void ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq) &txq->axq_q, lastbf->list.prev); txq->axq_depth--; - txok = !(ds->ds_txstat.ts_status & ATH9K_TXERR_FILT); + txok = !(ds->ds_txstat.ts_status & ATH9K_TXERR_MASK); txq->axq_tx_inprogress = false; spin_unlock_bh(&txq->axq_lock); diff --git a/drivers/net/wireless/b43/dma.c b/drivers/net/wireless/b43/dma.c index 027be275e03..88d1fd02d40 100644 --- a/drivers/net/wireless/b43/dma.c +++ b/drivers/net/wireless/b43/dma.c @@ -383,160 +383,44 @@ static inline } } -/* Check if a DMA region fits the device constraints. - * Returns true, if the region is OK for usage with this device. */ -static inline bool b43_dma_address_ok(struct b43_dmaring *ring, - dma_addr_t addr, size_t size) -{ - switch (ring->type) { - case B43_DMA_30BIT: - if ((u64)addr + size > (1ULL << 30)) - return 0; - break; - case B43_DMA_32BIT: - if ((u64)addr + size > (1ULL << 32)) - return 0; - break; - case B43_DMA_64BIT: - /* Currently we can't have addresses beyond - * 64bit in the kernel. */ - break; - } - return 1; -} - -#define is_4k_aligned(addr) (((u64)(addr) & 0x0FFFull) == 0) -#define is_8k_aligned(addr) (((u64)(addr) & 0x1FFFull) == 0) - -static void b43_unmap_and_free_ringmem(struct b43_dmaring *ring, void *base, - dma_addr_t dmaaddr, size_t size) -{ - ssb_dma_unmap_single(ring->dev->dev, dmaaddr, size, DMA_TO_DEVICE); - free_pages((unsigned long)base, get_order(size)); -} - -static void * __b43_get_and_map_ringmem(struct b43_dmaring *ring, - dma_addr_t *dmaaddr, size_t size, - gfp_t gfp_flags) -{ - void *base; - - base = (void *)__get_free_pages(gfp_flags, get_order(size)); - if (!base) - return NULL; - memset(base, 0, size); - *dmaaddr = ssb_dma_map_single(ring->dev->dev, base, size, - DMA_TO_DEVICE); - if (ssb_dma_mapping_error(ring->dev->dev, *dmaaddr)) { - free_pages((unsigned long)base, get_order(size)); - return NULL; - } - - return base; -} - -static void * b43_get_and_map_ringmem(struct b43_dmaring *ring, - dma_addr_t *dmaaddr, size_t size) -{ - void *base; - - base = __b43_get_and_map_ringmem(ring, dmaaddr, size, - GFP_KERNEL); - if (!base) { - b43err(ring->dev->wl, "Failed to allocate or map pages " - "for DMA ringmemory\n"); - return NULL; - } - if (!b43_dma_address_ok(ring, *dmaaddr, size)) { - /* The memory does not fit our device constraints. - * Retry with GFP_DMA set to get lower memory. */ - b43_unmap_and_free_ringmem(ring, base, *dmaaddr, size); - base = __b43_get_and_map_ringmem(ring, dmaaddr, size, - GFP_KERNEL | GFP_DMA); - if (!base) { - b43err(ring->dev->wl, "Failed to allocate or map pages " - "in the GFP_DMA region for DMA ringmemory\n"); - return NULL; - } - if (!b43_dma_address_ok(ring, *dmaaddr, size)) { - b43_unmap_and_free_ringmem(ring, base, *dmaaddr, size); - b43err(ring->dev->wl, "Failed to allocate DMA " - "ringmemory that fits device constraints\n"); - return NULL; - } - } - /* We expect the memory to be 4k aligned, at least. */ - if (B43_WARN_ON(!is_4k_aligned(*dmaaddr))) { - b43_unmap_and_free_ringmem(ring, base, *dmaaddr, size); - return NULL; - } - - return base; -} - static int alloc_ringmemory(struct b43_dmaring *ring) { - unsigned int required; - void *base; - dma_addr_t dmaaddr; - - /* There are several requirements to the descriptor ring memory: - * - The memory region needs to fit the address constraints for the - * device (same as for frame buffers). - * - For 30/32bit DMA devices, the descriptor ring must be 4k aligned. - * - For 64bit DMA devices, the descriptor ring must be 8k aligned. + gfp_t flags = GFP_KERNEL; + + /* The specs call for 4K buffers for 30- and 32-bit DMA with 4K + * alignment and 8K buffers for 64-bit DMA with 8K alignment. Testing + * has shown that 4K is sufficient for the latter as long as the buffer + * does not cross an 8K boundary. + * + * For unknown reasons - possibly a hardware error - the BCM4311 rev + * 02, which uses 64-bit DMA, needs the ring buffer in very low memory, + * which accounts for the GFP_DMA flag below. + * + * The flags here must match the flags in free_ringmemory below! */ - if (ring->type == B43_DMA_64BIT) - required = ring->nr_slots * sizeof(struct b43_dmadesc64); - else - required = ring->nr_slots * sizeof(struct b43_dmadesc32); - if (B43_WARN_ON(required > 0x1000)) + flags |= GFP_DMA; + ring->descbase = ssb_dma_alloc_consistent(ring->dev->dev, + B43_DMA_RINGMEMSIZE, + &(ring->dmabase), flags); + if (!ring->descbase) { + b43err(ring->dev->wl, "DMA ringmemory allocation failed\n"); return -ENOMEM; - - ring->alloc_descsize = 0x1000; - base = b43_get_and_map_ringmem(ring, &dmaaddr, ring->alloc_descsize); - if (!base) - return -ENOMEM; - ring->alloc_descbase = base; - ring->alloc_dmabase = dmaaddr; - - if ((ring->type != B43_DMA_64BIT) || is_8k_aligned(dmaaddr)) { - /* We're on <=32bit DMA, or we already got 8k aligned memory. - * That's all we need, so we're fine. */ - ring->descbase = base; - ring->dmabase = dmaaddr; - return 0; - } - b43_unmap_and_free_ringmem(ring, base, dmaaddr, ring->alloc_descsize); - - /* Ok, we failed at the 8k alignment requirement. - * Try to force-align the memory region now. */ - ring->alloc_descsize = 0x2000; - base = b43_get_and_map_ringmem(ring, &dmaaddr, ring->alloc_descsize); - if (!base) - return -ENOMEM; - ring->alloc_descbase = base; - ring->alloc_dmabase = dmaaddr; - - if (is_8k_aligned(dmaaddr)) { - /* We're already 8k aligned. That Ok, too. */ - ring->descbase = base; - ring->dmabase = dmaaddr; - return 0; } - /* Force-align it to 8k */ - ring->descbase = (void *)((u8 *)base + 0x1000); - ring->dmabase = dmaaddr + 0x1000; - B43_WARN_ON(!is_8k_aligned(ring->dmabase)); + memset(ring->descbase, 0, B43_DMA_RINGMEMSIZE); return 0; } static void free_ringmemory(struct b43_dmaring *ring) { - b43_unmap_and_free_ringmem(ring, ring->alloc_descbase, - ring->alloc_dmabase, ring->alloc_descsize); + gfp_t flags = GFP_KERNEL; + + if (ring->type == B43_DMA_64BIT) + flags |= GFP_DMA; + + ssb_dma_free_consistent(ring->dev->dev, B43_DMA_RINGMEMSIZE, + ring->descbase, ring->dmabase, flags); } /* Reset the RX DMA channel */ @@ -646,14 +530,29 @@ static bool b43_dma_mapping_error(struct b43_dmaring *ring, if (unlikely(ssb_dma_mapping_error(ring->dev->dev, addr))) return 1; - if (!b43_dma_address_ok(ring, addr, buffersize)) { - /* We can't support this address. Unmap it again. */ - unmap_descbuffer(ring, addr, buffersize, dma_to_device); - return 1; + switch (ring->type) { + case B43_DMA_30BIT: + if ((u64)addr + buffersize > (1ULL << 30)) + goto address_error; + break; + case B43_DMA_32BIT: + if ((u64)addr + buffersize > (1ULL << 32)) + goto address_error; + break; + case B43_DMA_64BIT: + /* Currently we can't have addresses beyond + * 64bit in the kernel. */ + break; } /* The address is OK. */ return 0; + +address_error: + /* We can't support this address. Unmap it again. */ + unmap_descbuffer(ring, addr, buffersize, dma_to_device); + + return 1; } static bool b43_rx_buffer_is_poisoned(struct b43_dmaring *ring, struct sk_buff *skb) @@ -715,9 +614,6 @@ static int setup_rx_descbuffer(struct b43_dmaring *ring, meta->dmaaddr = dmaaddr; ring->ops->fill_descriptor(ring, desc, dmaaddr, ring->rx_buffersize, 0, 0, 0); - ssb_dma_sync_single_for_device(ring->dev->dev, - ring->alloc_dmabase, - ring->alloc_descsize, DMA_TO_DEVICE); return 0; } @@ -1354,9 +1250,6 @@ static int dma_tx_fragment(struct b43_dmaring *ring, } /* Now transfer the whole frame. */ wmb(); - ssb_dma_sync_single_for_device(ring->dev->dev, - ring->alloc_dmabase, - ring->alloc_descsize, DMA_TO_DEVICE); ops->poke_tx(ring, next_slot(ring, slot)); return 0; diff --git a/drivers/net/wireless/b43/dma.h b/drivers/net/wireless/b43/dma.h index e607b392314..f7ab37c4cdb 100644 --- a/drivers/net/wireless/b43/dma.h +++ b/drivers/net/wireless/b43/dma.h @@ -157,6 +157,7 @@ struct b43_dmadesc_generic { } __attribute__ ((__packed__)); /* Misc DMA constants */ +#define B43_DMA_RINGMEMSIZE PAGE_SIZE #define B43_DMA0_RX_FRAMEOFFSET 30 /* DMA engine tuning knobs */ @@ -246,12 +247,6 @@ struct b43_dmaring { /* The QOS priority assigned to this ring. Only used for TX rings. * This is the mac80211 "queue" value. */ u8 queue_prio; - /* Pointers and size of the originally allocated and mapped memory - * region for the descriptor ring. */ - void *alloc_descbase; - dma_addr_t alloc_dmabase; - unsigned int alloc_descsize; - /* Pointer to our wireless device. */ struct b43_wldev *dev; #ifdef CONFIG_B43_DEBUG /* Maximum number of used slots. */ diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c index 7da1dab933d..234891d8cc1 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945.c @@ -681,19 +681,13 @@ static void iwl3945_rx_reply_rx(struct iwl_priv *priv, snr = rx_stats_sig_avg / rx_stats_noise_diff; rx_status.noise = rx_status.signal - iwl3945_calc_db_from_ratio(snr); - rx_status.qual = iwl3945_calc_sig_qual(rx_status.signal, - rx_status.noise); - - /* If noise info not available, calculate signal quality indicator (%) - * using just the dBm signal level. */ } else { rx_status.noise = priv->last_rx_noise; - rx_status.qual = iwl3945_calc_sig_qual(rx_status.signal, 0); } - IWL_DEBUG_STATS(priv, "Rssi %d noise %d qual %d sig_avg %d noise_diff %d\n", - rx_status.signal, rx_status.noise, rx_status.qual, + IWL_DEBUG_STATS(priv, "Rssi %d noise %d sig_avg %d noise_diff %d\n", + rx_status.signal, rx_status.noise, rx_stats_sig_avg, rx_stats_noise_diff); header = (struct ieee80211_hdr *)IWL_RX_DATA(pkt); @@ -1835,8 +1829,7 @@ static int iwl3945_send_rxon_assoc(struct iwl_priv *priv) rc = -EIO; } - priv->alloc_rxb_page--; - free_pages(cmd.reply_page, priv->hw_params.rx_page_order); + iwl_free_pages(priv, cmd.reply_page); return rc; } @@ -2836,6 +2829,7 @@ static struct iwl_cfg iwl3945_bg_cfg = { .use_isr_legacy = true, .ht_greenfield_support = false, .led_compensation = 64, + .broken_powersave = true, }; static struct iwl_cfg iwl3945_abg_cfg = { @@ -2852,6 +2846,7 @@ static struct iwl_cfg iwl3945_abg_cfg = { .use_isr_legacy = true, .ht_greenfield_support = false, .led_compensation = 64, + .broken_powersave = true, }; struct pci_device_id iwl3945_hw_card_ids[] = { diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.h b/drivers/net/wireless/iwlwifi/iwl-3945.h index ecc23ec1f6a..531fa125f5a 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.h +++ b/drivers/net/wireless/iwlwifi/iwl-3945.h @@ -222,7 +222,6 @@ struct iwl3945_ibss_seq { * *****************************************************************************/ extern int iwl3945_calc_db_from_ratio(int sig_ratio); -extern int iwl3945_calc_sig_qual(int rssi_dbm, int noise_dbm); extern void iwl3945_rx_replenish(void *data); extern void iwl3945_rx_queue_reset(struct iwl_priv *priv, struct iwl_rx_queue *rxq); extern unsigned int iwl3945_fill_beacon_frame(struct iwl_priv *priv, diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c index 386513b601f..484c5fdf7c2 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965.c @@ -1204,7 +1204,7 @@ static int iwl4965_fill_txpower_tbl(struct iwl_priv *priv, u8 band, u16 channel, iwl4965_interpolate_chan(priv, channel, &ch_eeprom_info); /* calculate tx gain adjustment based on power supply voltage */ - voltage = priv->calib_info->voltage; + voltage = le16_to_cpu(priv->calib_info->voltage); init_voltage = (s32)le32_to_cpu(priv->card_alive_init.voltage); voltage_compensation = iwl4965_get_voltage_compensation(voltage, init_voltage); diff --git a/drivers/net/wireless/iwlwifi/iwl-5000-hw.h b/drivers/net/wireless/iwlwifi/iwl-5000-hw.h index 4ef6804a455..bc056e9ab85 100644 --- a/drivers/net/wireless/iwlwifi/iwl-5000-hw.h +++ b/drivers/net/wireless/iwlwifi/iwl-5000-hw.h @@ -92,11 +92,15 @@ static inline s32 iwl_temp_calib_to_offset(struct iwl_priv *priv) { - u16 *temp_calib = (u16 *)iwl_eeprom_query_addr(priv, - EEPROM_5000_TEMPERATURE); - /* offset = temperature - voltage / coef */ - s32 offset = (s32)(temp_calib[0] - temp_calib[1] / IWL_5150_VOLTAGE_TO_TEMPERATURE_COEFF); - return offset; + u16 temperature, voltage; + __le16 *temp_calib = + (__le16 *)iwl_eeprom_query_addr(priv, EEPROM_5000_TEMPERATURE); + + temperature = le16_to_cpu(temp_calib[0]); + voltage = le16_to_cpu(temp_calib[1]); + + /* offset = temp - volt / coeff */ + return (s32)(temperature - voltage / IWL_5150_VOLTAGE_TO_TEMPERATURE_COEFF); } /* Fixed (non-configurable) rx data from phy */ diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c index e2f8615c8c9..33a5866538e 100644 --- a/drivers/net/wireless/iwlwifi/iwl-5000.c +++ b/drivers/net/wireless/iwlwifi/iwl-5000.c @@ -333,14 +333,15 @@ static void iwl5000_set_ct_threshold(struct iwl_priv *priv) static int iwl5000_set_Xtal_calib(struct iwl_priv *priv) { struct iwl_calib_xtal_freq_cmd cmd; - u16 *xtal_calib = (u16 *)iwl_eeprom_query_addr(priv, EEPROM_5000_XTAL); + __le16 *xtal_calib = + (__le16 *)iwl_eeprom_query_addr(priv, EEPROM_5000_XTAL); cmd.hdr.op_code = IWL_PHY_CALIBRATE_CRYSTAL_FRQ_CMD; cmd.hdr.first_group = 0; cmd.hdr.groups_num = 1; cmd.hdr.data_valid = 1; - cmd.cap_pin1 = (u8)xtal_calib[0]; - cmd.cap_pin2 = (u8)xtal_calib[1]; + cmd.cap_pin1 = le16_to_cpu(xtal_calib[0]); + cmd.cap_pin2 = le16_to_cpu(xtal_calib[1]); return iwl_calib_set(&priv->calib_results[IWL_CALIB_XTAL], (u8 *)&cmd, sizeof(cmd)); } diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c index fe511cbf012..b93e4915819 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c @@ -150,7 +150,7 @@ static s32 expected_tpt_mimo3_40MHz[4][IWL_RATE_COUNT] = { }; /* mbps, mcs */ -const static struct iwl_rate_mcs_info iwl_rate_mcs[IWL_RATE_COUNT] = { +static const struct iwl_rate_mcs_info iwl_rate_mcs[IWL_RATE_COUNT] = { { "1", "BPSK DSSS"}, { "2", "QPSK DSSS"}, {"5.5", "BPSK CCK"}, diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index b8377efb3ba..1c9866daf81 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -1842,7 +1842,7 @@ void iwl_dump_nic_event_log(struct iwl_priv *priv, bool full_log) } #ifdef CONFIG_IWLWIFI_DEBUG - if (!(iwl_get_debug_level(priv) & IWL_DL_FW_ERRORS)) + if (!(iwl_get_debug_level(priv) & IWL_DL_FW_ERRORS) && !full_log) size = (size > DEFAULT_DUMP_EVENT_LOG_ENTRIES) ? DEFAULT_DUMP_EVENT_LOG_ENTRIES : size; #else @@ -3173,7 +3173,6 @@ static int iwl_init_drv(struct iwl_priv *priv) priv->ibss_beacon = NULL; - spin_lock_init(&priv->lock); spin_lock_init(&priv->sta_lock); spin_lock_init(&priv->hcmd_lock); @@ -3361,10 +3360,11 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) (unsigned long long) pci_resource_len(pdev, 0)); IWL_DEBUG_INFO(priv, "pci_resource_base = %p\n", priv->hw_base); - /* this spin lock will be used in apm_ops.init and EEPROM access + /* these spin locks will be used in apm_ops.init and EEPROM access * we should init now */ spin_lock_init(&priv->reg_lock); + spin_lock_init(&priv->lock); iwl_hw_detect(priv); IWL_INFO(priv, "Detected Intel Wireless WiFi Link %s REV=0x%X\n", priv->cfg->name, priv->hw_rev); diff --git a/drivers/net/wireless/iwlwifi/iwl-csr.h b/drivers/net/wireless/iwlwifi/iwl-csr.h index a7bfae01f19..1ec8cb4d5ea 100644 --- a/drivers/net/wireless/iwlwifi/iwl-csr.h +++ b/drivers/net/wireless/iwlwifi/iwl-csr.h @@ -77,8 +77,7 @@ * The MAC (uCode processor, etc.) does not need to be powered up for accessing * the CSR registers. * - * NOTE: Newer devices using one-time-programmable (OTP) memory - * require device to be awake in order to read this memory + * NOTE: Device does need to be awake in order to read this memory * via CSR_EEPROM and CSR_OTP registers */ #define CSR_BASE (0x000) @@ -111,9 +110,8 @@ /* * EEPROM and OTP (one-time-programmable) memory reads * - * NOTE: For (newer) devices using OTP, device must be awake, initialized via - * apm_ops.init() in order to read. Older devices (3945/4965/5000) - * use EEPROM and do not require this. + * NOTE: Device must be awake, initialized via apm_ops.init(), + * in order to read. */ #define CSR_EEPROM_REG (CSR_BASE+0x02c) #define CSR_EEPROM_GP (CSR_BASE+0x030) diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index 2673e9a4db9..165d1f6e2dd 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -1168,7 +1168,7 @@ struct iwl_priv { u32 last_beacon_time; u64 last_tsf; - /* eeprom */ + /* eeprom -- this is in the card's little endian byte order */ u8 *eeprom; int nvm_device_type; struct iwl_eeprom_calib_info *calib_info; @@ -1353,4 +1353,15 @@ static inline int is_channel_ibss(const struct iwl_channel_info *ch) return ((ch->flags & EEPROM_CHANNEL_IBSS)) ? 1 : 0; } +static inline void __iwl_free_pages(struct iwl_priv *priv, struct page *page) +{ + __free_pages(page, priv->hw_params.rx_page_order); + priv->alloc_rxb_page--; +} + +static inline void iwl_free_pages(struct iwl_priv *priv, unsigned long page) +{ + free_pages(page, priv->hw_params.rx_page_order); + priv->alloc_rxb_page--; +} #endif /* __iwl_dev_h__ */ diff --git a/drivers/net/wireless/iwlwifi/iwl-eeprom.c b/drivers/net/wireless/iwlwifi/iwl-eeprom.c index 3946e5c03f8..4a30969689f 100644 --- a/drivers/net/wireless/iwlwifi/iwl-eeprom.c +++ b/drivers/net/wireless/iwlwifi/iwl-eeprom.c @@ -370,7 +370,7 @@ static int iwl_init_otp_access(struct iwl_priv *priv) return ret; } -static int iwl_read_otp_word(struct iwl_priv *priv, u16 addr, u16 *eeprom_data) +static int iwl_read_otp_word(struct iwl_priv *priv, u16 addr, __le16 *eeprom_data) { int ret = 0; u32 r; @@ -404,7 +404,7 @@ static int iwl_read_otp_word(struct iwl_priv *priv, u16 addr, u16 *eeprom_data) CSR_OTP_GP_REG_ECC_CORR_STATUS_MSK); IWL_ERR(priv, "Correctable OTP ECC error, continue read\n"); } - *eeprom_data = le16_to_cpu((__force __le16)(r >> 16)); + *eeprom_data = cpu_to_le16(r >> 16); return 0; } @@ -413,7 +413,8 @@ static int iwl_read_otp_word(struct iwl_priv *priv, u16 addr, u16 *eeprom_data) */ static bool iwl_is_otp_empty(struct iwl_priv *priv) { - u16 next_link_addr = 0, link_value; + u16 next_link_addr = 0; + __le16 link_value; bool is_empty = false; /* locate the beginning of OTP link list */ @@ -443,7 +444,8 @@ static bool iwl_is_otp_empty(struct iwl_priv *priv) static int iwl_find_otp_image(struct iwl_priv *priv, u16 *validblockaddr) { - u16 next_link_addr = 0, link_value = 0, valid_addr; + u16 next_link_addr = 0, valid_addr; + __le16 link_value = 0; int usedblocks = 0; /* set addressing mode to absolute to traverse the link list */ @@ -463,7 +465,7 @@ static int iwl_find_otp_image(struct iwl_priv *priv, * check for more block on the link list */ valid_addr = next_link_addr; - next_link_addr = link_value * sizeof(u16); + next_link_addr = le16_to_cpu(link_value) * sizeof(u16); IWL_DEBUG_INFO(priv, "OTP blocks %d addr 0x%x\n", usedblocks, next_link_addr); if (iwl_read_otp_word(priv, next_link_addr, &link_value)) @@ -497,7 +499,7 @@ static int iwl_find_otp_image(struct iwl_priv *priv, */ int iwl_eeprom_init(struct iwl_priv *priv) { - u16 *e; + __le16 *e; u32 gp = iwl_read32(priv, CSR_EEPROM_GP); int sz; int ret; @@ -516,12 +518,9 @@ int iwl_eeprom_init(struct iwl_priv *priv) ret = -ENOMEM; goto alloc_err; } - e = (u16 *)priv->eeprom; + e = (__le16 *)priv->eeprom; - if (priv->nvm_device_type == NVM_DEVICE_TYPE_OTP) { - /* OTP reads require powered-up chip */ - priv->cfg->ops->lib->apm_ops.init(priv); - } + priv->cfg->ops->lib->apm_ops.init(priv); ret = priv->cfg->ops->lib->eeprom_ops.verify_signature(priv); if (ret < 0) { @@ -562,7 +561,7 @@ int iwl_eeprom_init(struct iwl_priv *priv) } for (addr = validblockaddr; addr < validblockaddr + sz; addr += sizeof(u16)) { - u16 eeprom_data; + __le16 eeprom_data; ret = iwl_read_otp_word(priv, addr, &eeprom_data); if (ret) @@ -570,13 +569,6 @@ int iwl_eeprom_init(struct iwl_priv *priv) e[cache_addr / 2] = eeprom_data; cache_addr += sizeof(u16); } - - /* - * Now that OTP reads are complete, reset chip to save - * power until we load uCode during "up". - */ - priv->cfg->ops->lib->apm_ops.stop(priv); - } else { /* eeprom is an array of 16bit values */ for (addr = 0; addr < sz; addr += sizeof(u16)) { @@ -594,7 +586,7 @@ int iwl_eeprom_init(struct iwl_priv *priv) goto done; } r = _iwl_read_direct32(priv, CSR_EEPROM_REG); - e[addr / 2] = le16_to_cpu((__force __le16)(r >> 16)); + e[addr / 2] = cpu_to_le16(r >> 16); } } ret = 0; @@ -603,6 +595,8 @@ done: err: if (ret) iwl_eeprom_free(priv); + /* Reset chip to save power until we load uCode during "up". */ + priv->cfg->ops->lib->apm_ops.stop(priv); alloc_err: return ret; } @@ -755,7 +749,8 @@ static int iwl_mod_ht40_chan_info(struct iwl_priv *priv, ch_info->ht40_eeprom = *eeprom_ch; ch_info->ht40_max_power_avg = eeprom_ch->max_power_avg; ch_info->ht40_flags = eeprom_ch->flags; - ch_info->ht40_extension_channel &= ~clear_ht40_extension_channel; + if (eeprom_ch->flags & EEPROM_CHANNEL_VALID) + ch_info->ht40_extension_channel &= ~clear_ht40_extension_channel; return 0; } diff --git a/drivers/net/wireless/iwlwifi/iwl-eeprom.h b/drivers/net/wireless/iwlwifi/iwl-eeprom.h index 5cd2b66bbe4..0cd9c02ee04 100644 --- a/drivers/net/wireless/iwlwifi/iwl-eeprom.h +++ b/drivers/net/wireless/iwlwifi/iwl-eeprom.h @@ -137,7 +137,7 @@ struct iwl_eeprom_channel { * */ struct iwl_eeprom_enhanced_txpwr { - u16 common; + __le16 common; s8 chain_a_max; s8 chain_b_max; s8 chain_c_max; @@ -360,7 +360,7 @@ struct iwl_eeprom_calib_subband_info { struct iwl_eeprom_calib_info { u8 saturation_power24; /* half-dBm (e.g. "34" = 17 dBm) */ u8 saturation_power52; /* half-dBm */ - s16 voltage; /* signed */ + __le16 voltage; /* signed */ struct iwl_eeprom_calib_subband_info band_info[EEPROM_TX_POWER_BANDS]; } __attribute__ ((packed)); diff --git a/drivers/net/wireless/iwlwifi/iwl-hcmd.c b/drivers/net/wireless/iwlwifi/iwl-hcmd.c index a2316594820..30e9ea6d54e 100644 --- a/drivers/net/wireless/iwlwifi/iwl-hcmd.c +++ b/drivers/net/wireless/iwlwifi/iwl-hcmd.c @@ -234,7 +234,7 @@ cancel: } fail: if (cmd->reply_page) { - free_pages(cmd->reply_page, priv->hw_params.rx_page_order); + iwl_free_pages(priv, cmd->reply_page); cmd->reply_page = 0; } out: diff --git a/drivers/net/wireless/iwlwifi/iwl-rx.c b/drivers/net/wireless/iwlwifi/iwl-rx.c index 6090bc15a6d..6f36b6e79f5 100644 --- a/drivers/net/wireless/iwlwifi/iwl-rx.c +++ b/drivers/net/wireless/iwlwifi/iwl-rx.c @@ -345,10 +345,8 @@ void iwl_rx_queue_free(struct iwl_priv *priv, struct iwl_rx_queue *rxq) pci_unmap_page(priv->pci_dev, rxq->pool[i].page_dma, PAGE_SIZE << priv->hw_params.rx_page_order, PCI_DMA_FROMDEVICE); - __free_pages(rxq->pool[i].page, - priv->hw_params.rx_page_order); + __iwl_free_pages(priv, rxq->pool[i].page); rxq->pool[i].page = NULL; - priv->alloc_rxb_page--; } } @@ -416,9 +414,7 @@ void iwl_rx_queue_reset(struct iwl_priv *priv, struct iwl_rx_queue *rxq) pci_unmap_page(priv->pci_dev, rxq->pool[i].page_dma, PAGE_SIZE << priv->hw_params.rx_page_order, PCI_DMA_FROMDEVICE); - priv->alloc_rxb_page--; - __free_pages(rxq->pool[i].page, - priv->hw_params.rx_page_order); + __iwl_free_pages(priv, rxq->pool[i].page); rxq->pool[i].page = NULL; } list_add_tail(&rxq->pool[i].list, &rxq->rx_used); @@ -654,47 +650,6 @@ void iwl_reply_statistics(struct iwl_priv *priv, } EXPORT_SYMBOL(iwl_reply_statistics); -#define PERFECT_RSSI (-20) /* dBm */ -#define WORST_RSSI (-95) /* dBm */ -#define RSSI_RANGE (PERFECT_RSSI - WORST_RSSI) - -/* Calculate an indication of rx signal quality (a percentage, not dBm!). - * See http://www.ces.clemson.edu/linux/signal_quality.shtml for info - * about formulas used below. */ -static int iwl_calc_sig_qual(int rssi_dbm, int noise_dbm) -{ - int sig_qual; - int degradation = PERFECT_RSSI - rssi_dbm; - - /* If we get a noise measurement, use signal-to-noise ratio (SNR) - * as indicator; formula is (signal dbm - noise dbm). - * SNR at or above 40 is a great signal (100%). - * Below that, scale to fit SNR of 0 - 40 dB within 0 - 100% indicator. - * Weakest usable signal is usually 10 - 15 dB SNR. */ - if (noise_dbm) { - if (rssi_dbm - noise_dbm >= 40) - return 100; - else if (rssi_dbm < noise_dbm) - return 0; - sig_qual = ((rssi_dbm - noise_dbm) * 5) / 2; - - /* Else use just the signal level. - * This formula is a least squares fit of data points collected and - * compared with a reference system that had a percentage (%) display - * for signal quality. */ - } else - sig_qual = (100 * (RSSI_RANGE * RSSI_RANGE) - degradation * - (15 * RSSI_RANGE + 62 * degradation)) / - (RSSI_RANGE * RSSI_RANGE); - - if (sig_qual > 100) - sig_qual = 100; - else if (sig_qual < 1) - sig_qual = 0; - - return sig_qual; -} - /* Calc max signal level (dBm) among 3 possible receivers */ static inline int iwl_calc_rssi(struct iwl_priv *priv, struct iwl_rx_phy_res *rx_resp) @@ -1105,11 +1060,8 @@ void iwl_rx_reply_rx(struct iwl_priv *priv, if (iwl_is_associated(priv) && !test_bit(STATUS_SCANNING, &priv->status)) { rx_status.noise = priv->last_rx_noise; - rx_status.qual = iwl_calc_sig_qual(rx_status.signal, - rx_status.noise); } else { rx_status.noise = IWL_NOISE_MEAS_NOT_AVAILABLE; - rx_status.qual = iwl_calc_sig_qual(rx_status.signal, 0); } /* Reset beacon noise level if not associated. */ @@ -1122,8 +1074,8 @@ void iwl_rx_reply_rx(struct iwl_priv *priv, iwl_dbg_report_frame(priv, phy_res, len, header, 1); #endif iwl_dbg_log_rx_data_frame(priv, len, header); - IWL_DEBUG_STATS_LIMIT(priv, "Rssi %d, noise %d, qual %d, TSF %llu\n", - rx_status.signal, rx_status.noise, rx_status.qual, + IWL_DEBUG_STATS_LIMIT(priv, "Rssi %d, noise %d, TSF %llu\n", + rx_status.signal, rx_status.noise, (unsigned long long)rx_status.mactime); /* diff --git a/drivers/net/wireless/iwlwifi/iwl-scan.c b/drivers/net/wireless/iwlwifi/iwl-scan.c index a2b2b8315ff..fa1c89ba645 100644 --- a/drivers/net/wireless/iwlwifi/iwl-scan.c +++ b/drivers/net/wireless/iwlwifi/iwl-scan.c @@ -144,8 +144,7 @@ static int iwl_send_scan_abort(struct iwl_priv *priv) clear_bit(STATUS_SCAN_HW, &priv->status); } - priv->alloc_rxb_page--; - free_pages(cmd.reply_page, priv->hw_params.rx_page_order); + iwl_free_pages(priv, cmd.reply_page); return ret; } diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.c b/drivers/net/wireless/iwlwifi/iwl-sta.c index cd6a6901216..cde09a890b7 100644 --- a/drivers/net/wireless/iwlwifi/iwl-sta.c +++ b/drivers/net/wireless/iwlwifi/iwl-sta.c @@ -164,9 +164,7 @@ int iwl_send_add_sta(struct iwl_priv *priv, break; } } - - priv->alloc_rxb_page--; - free_pages(cmd.reply_page, priv->hw_params.rx_page_order); + iwl_free_pages(priv, cmd.reply_page); return ret; } @@ -391,9 +389,7 @@ static int iwl_send_remove_station(struct iwl_priv *priv, const u8 *addr, break; } } - - priv->alloc_rxb_page--; - free_pages(cmd.reply_page, priv->hw_params.rx_page_order); + iwl_free_pages(priv, cmd.reply_page); return ret; } diff --git a/drivers/net/wireless/iwlwifi/iwl-tx.c b/drivers/net/wireless/iwlwifi/iwl-tx.c index 00da5e152d4..87ce2bd292c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-tx.c @@ -407,13 +407,14 @@ void iwl_hw_txq_ctx_free(struct iwl_priv *priv) int txq_id; /* Tx queues */ - if (priv->txq) + if (priv->txq) { for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++) if (txq_id == IWL_CMD_QUEUE_NUM) iwl_cmd_queue_free(priv); else iwl_tx_queue_free(priv, txq_id); + } iwl_free_dma_ptr(priv, &priv->kw); iwl_free_dma_ptr(priv, &priv->scd_bc_tbls); diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index 2a28a1f8b1f..f8e4e4b18d0 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -548,6 +548,9 @@ static int iwl3945_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) txq = &priv->txq[txq_id]; q = &txq->q; + if ((iwl_queue_space(q) < q->high_mark)) + goto drop; + spin_lock_irqsave(&priv->lock, flags); idx = get_cmd_index(q, q->write_ptr, 0); @@ -812,7 +815,7 @@ static int iwl3945_get_measurement(struct iwl_priv *priv, break; } - free_pages(cmd.reply_page, priv->hw_params.rx_page_order); + iwl_free_pages(priv, cmd.reply_page); return rc; } @@ -1198,9 +1201,7 @@ void iwl3945_rx_queue_reset(struct iwl_priv *priv, struct iwl_rx_queue *rxq) pci_unmap_page(priv->pci_dev, rxq->pool[i].page_dma, PAGE_SIZE << priv->hw_params.rx_page_order, PCI_DMA_FROMDEVICE); - priv->alloc_rxb_page--; - __free_pages(rxq->pool[i].page, - priv->hw_params.rx_page_order); + __iwl_free_pages(priv, rxq->pool[i].page); rxq->pool[i].page = NULL; } list_add_tail(&rxq->pool[i].list, &rxq->rx_used); @@ -1247,10 +1248,8 @@ static void iwl3945_rx_queue_free(struct iwl_priv *priv, struct iwl_rx_queue *rx pci_unmap_page(priv->pci_dev, rxq->pool[i].page_dma, PAGE_SIZE << priv->hw_params.rx_page_order, PCI_DMA_FROMDEVICE); - __free_pages(rxq->pool[i].page, - priv->hw_params.rx_page_order); + __iwl_free_pages(priv, rxq->pool[i].page); rxq->pool[i].page = NULL; - priv->alloc_rxb_page--; } } @@ -1300,47 +1299,6 @@ int iwl3945_calc_db_from_ratio(int sig_ratio) return (int)ratio2dB[sig_ratio]; } -#define PERFECT_RSSI (-20) /* dBm */ -#define WORST_RSSI (-95) /* dBm */ -#define RSSI_RANGE (PERFECT_RSSI - WORST_RSSI) - -/* Calculate an indication of rx signal quality (a percentage, not dBm!). - * See http://www.ces.clemson.edu/linux/signal_quality.shtml for info - * about formulas used below. */ -int iwl3945_calc_sig_qual(int rssi_dbm, int noise_dbm) -{ - int sig_qual; - int degradation = PERFECT_RSSI - rssi_dbm; - - /* If we get a noise measurement, use signal-to-noise ratio (SNR) - * as indicator; formula is (signal dbm - noise dbm). - * SNR at or above 40 is a great signal (100%). - * Below that, scale to fit SNR of 0 - 40 dB within 0 - 100% indicator. - * Weakest usable signal is usually 10 - 15 dB SNR. */ - if (noise_dbm) { - if (rssi_dbm - noise_dbm >= 40) - return 100; - else if (rssi_dbm < noise_dbm) - return 0; - sig_qual = ((rssi_dbm - noise_dbm) * 5) / 2; - - /* Else use just the signal level. - * This formula is a least squares fit of data points collected and - * compared with a reference system that had a percentage (%) display - * for signal quality. */ - } else - sig_qual = (100 * (RSSI_RANGE * RSSI_RANGE) - degradation * - (15 * RSSI_RANGE + 62 * degradation)) / - (RSSI_RANGE * RSSI_RANGE); - - if (sig_qual > 100) - sig_qual = 100; - else if (sig_qual < 1) - sig_qual = 0; - - return sig_qual; -} - /** * iwl3945_rx_handle - Main entry function for receiving responses from uCode * @@ -1688,7 +1646,7 @@ void iwl3945_dump_nic_event_log(struct iwl_priv *priv, bool full_log) } #ifdef CONFIG_IWLWIFI_DEBUG - if (!(iwl_get_debug_level(priv) & IWL_DL_FW_ERRORS)) + if (!(iwl_get_debug_level(priv) & IWL_DL_FW_ERRORS) && !full_log) size = (size > DEFAULT_IWL3945_DUMP_EVENT_LOG_ENTRIES) ? DEFAULT_IWL3945_DUMP_EVENT_LOG_ENTRIES : size; #else @@ -3867,7 +3825,6 @@ static int iwl3945_init_drv(struct iwl_priv *priv) priv->retry_rate = 1; priv->ibss_beacon = NULL; - spin_lock_init(&priv->lock); spin_lock_init(&priv->sta_lock); spin_lock_init(&priv->hcmd_lock); @@ -3936,9 +3893,11 @@ static int iwl3945_setup_mac(struct iwl_priv *priv) /* Tell mac80211 our characteristics */ hw->flags = IEEE80211_HW_SIGNAL_DBM | IEEE80211_HW_NOISE_DBM | - IEEE80211_HW_SPECTRUM_MGMT | - IEEE80211_HW_SUPPORTS_PS | - IEEE80211_HW_SUPPORTS_DYNAMIC_PS; + IEEE80211_HW_SPECTRUM_MGMT; + + if (!priv->cfg->broken_powersave) + hw->flags |= IEEE80211_HW_SUPPORTS_PS | + IEEE80211_HW_SUPPORTS_DYNAMIC_PS; hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | @@ -4057,10 +4016,11 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e * PCI Tx retries from interfering with C3 CPU state */ pci_write_config_byte(pdev, 0x41, 0x00); - /* this spin lock will be used in apm_ops.init and EEPROM access + /* these spin locks will be used in apm_ops.init and EEPROM access * we should init now */ spin_lock_init(&priv->reg_lock); + spin_lock_init(&priv->lock); /*********************** * 4. Read EEPROM diff --git a/drivers/net/wireless/iwmc3200wifi/iwm.h b/drivers/net/wireless/iwmc3200wifi/iwm.h index 5a26bb05a33..842811142be 100644 --- a/drivers/net/wireless/iwmc3200wifi/iwm.h +++ b/drivers/net/wireless/iwmc3200wifi/iwm.h @@ -268,7 +268,7 @@ struct iwm_priv { struct sk_buff_head rx_list; struct list_head rx_tickets; - struct list_head rx_packets[IWM_RX_ID_HASH]; + struct list_head rx_packets[IWM_RX_ID_HASH + 1]; struct workqueue_struct *rx_wq; struct work_struct rx_worker; @@ -349,7 +349,7 @@ int iwm_up(struct iwm_priv *iwm); int iwm_down(struct iwm_priv *iwm); /* TX API */ -u16 iwm_tid_to_queue(u16 tid); +int iwm_tid_to_queue(u16 tid); void iwm_tx_credit_inc(struct iwm_priv *iwm, int id, int total_freed_pages); void iwm_tx_worker(struct work_struct *work); int iwm_xmit_frame(struct sk_buff *skb, struct net_device *netdev); diff --git a/drivers/net/wireless/iwmc3200wifi/netdev.c b/drivers/net/wireless/iwmc3200wifi/netdev.c index e4f0f8705f6..c4c0d23c63e 100644 --- a/drivers/net/wireless/iwmc3200wifi/netdev.c +++ b/drivers/net/wireless/iwmc3200wifi/netdev.c @@ -76,7 +76,7 @@ static int iwm_stop(struct net_device *ndev) */ static const u16 iwm_1d_to_queue[8] = { 1, 0, 0, 1, 2, 2, 3, 3 }; -u16 iwm_tid_to_queue(u16 tid) +int iwm_tid_to_queue(u16 tid) { if (tid > IWM_UMAC_TID_NR - 2) return -EINVAL; diff --git a/drivers/net/wireless/iwmc3200wifi/rx.c b/drivers/net/wireless/iwmc3200wifi/rx.c index 1c57c1f72cb..6d6ed748517 100644 --- a/drivers/net/wireless/iwmc3200wifi/rx.c +++ b/drivers/net/wireless/iwmc3200wifi/rx.c @@ -1126,7 +1126,7 @@ static int iwm_ntf_stop_resume_tx(struct iwm_priv *iwm, u8 *buf, if (!stop) { struct iwm_tx_queue *txq; - u16 queue = iwm_tid_to_queue(bit); + int queue = iwm_tid_to_queue(bit); if (queue < 0) continue; diff --git a/drivers/net/wireless/libertas/mesh.c b/drivers/net/wireless/libertas/mesh.c index 2f91c9b808a..92b7a357a5e 100644 --- a/drivers/net/wireless/libertas/mesh.c +++ b/drivers/net/wireless/libertas/mesh.c @@ -2,6 +2,7 @@ #include <linux/delay.h> #include <linux/etherdevice.h> #include <linux/netdevice.h> +#include <linux/if_ether.h> #include <linux/if_arp.h> #include <linux/kthread.h> #include <linux/kfifo.h> @@ -351,8 +352,7 @@ int lbs_add_mesh(struct lbs_private *priv) mesh_dev->netdev_ops = &mesh_netdev_ops; mesh_dev->ethtool_ops = &lbs_ethtool_ops; - memcpy(mesh_dev->dev_addr, priv->dev->dev_addr, - sizeof(priv->dev->dev_addr)); + memcpy(mesh_dev->dev_addr, priv->dev->dev_addr, ETH_ALEN); SET_NETDEV_DEV(priv->mesh_dev, priv->dev->dev.parent); diff --git a/drivers/net/wireless/libertas/scan.c b/drivers/net/wireless/libertas/scan.c index c6a6c042b82..b0b1c784150 100644 --- a/drivers/net/wireless/libertas/scan.c +++ b/drivers/net/wireless/libertas/scan.c @@ -567,11 +567,8 @@ int lbs_scan_networks(struct lbs_private *priv, int full_scan) chan_count = lbs_scan_create_channel_list(priv, chan_list); netif_stop_queue(priv->dev); - netif_carrier_off(priv->dev); - if (priv->mesh_dev) { + if (priv->mesh_dev) netif_stop_queue(priv->mesh_dev); - netif_carrier_off(priv->mesh_dev); - } /* Prepare to continue an interrupted scan */ lbs_deb_scan("chan_count %d, scan_channel %d\n", @@ -635,16 +632,13 @@ out2: priv->scan_channel = 0; out: - if (priv->connect_status == LBS_CONNECTED) { - netif_carrier_on(priv->dev); - if (!priv->tx_pending_len) - netif_wake_queue(priv->dev); - } - if (priv->mesh_dev && (priv->mesh_connect_status == LBS_CONNECTED)) { - netif_carrier_on(priv->mesh_dev); - if (!priv->tx_pending_len) - netif_wake_queue(priv->mesh_dev); - } + if (priv->connect_status == LBS_CONNECTED && !priv->tx_pending_len) + netif_wake_queue(priv->dev); + + if (priv->mesh_dev && (priv->mesh_connect_status == LBS_CONNECTED) && + !priv->tx_pending_len) + netif_wake_queue(priv->mesh_dev); + kfree(chan_list); lbs_deb_leave_args(LBS_DEB_SCAN, "ret %d", ret); diff --git a/drivers/net/wireless/libertas/wext.c b/drivers/net/wireless/libertas/wext.c index a8eb9e1fcf3..4b1aab593a8 100644 --- a/drivers/net/wireless/libertas/wext.c +++ b/drivers/net/wireless/libertas/wext.c @@ -2025,10 +2025,8 @@ static int lbs_get_essid(struct net_device *dev, struct iw_request_info *info, if (priv->connect_status == LBS_CONNECTED) { memcpy(extra, priv->curbssparams.ssid, priv->curbssparams.ssid_len); - extra[priv->curbssparams.ssid_len] = '\0'; } else { memset(extra, 0, 32); - extra[priv->curbssparams.ssid_len] = '\0'; } /* * If none, we may want to get the one that was set diff --git a/drivers/net/wireless/libertas_tf/main.c b/drivers/net/wireless/libertas_tf/main.c index 019431d2f8a..26a1abd5bb0 100644 --- a/drivers/net/wireless/libertas_tf/main.c +++ b/drivers/net/wireless/libertas_tf/main.c @@ -495,7 +495,6 @@ int lbtf_rx(struct lbtf_private *priv, struct sk_buff *skb) stats.band = IEEE80211_BAND_2GHZ; stats.signal = prxpd->snr; stats.noise = prxpd->nf; - stats.qual = prxpd->snr - prxpd->nf; /* Marvell rate index has a hole at value 4 */ if (prxpd->rx_rate > 4) --prxpd->rx_rate; diff --git a/drivers/net/wireless/orinoco/wext.c b/drivers/net/wireless/orinoco/wext.c index 7698fdd6a3a..31ca241f775 100644 --- a/drivers/net/wireless/orinoco/wext.c +++ b/drivers/net/wireless/orinoco/wext.c @@ -23,7 +23,7 @@ #define MAX_RID_LEN 1024 /* Helper routine to record keys - * Do not call from interrupt context */ + * It is called under orinoco_lock so it may not sleep */ static int orinoco_set_key(struct orinoco_private *priv, int index, enum orinoco_alg alg, const u8 *key, int key_len, const u8 *seq, int seq_len) @@ -32,14 +32,14 @@ static int orinoco_set_key(struct orinoco_private *priv, int index, kzfree(priv->keys[index].seq); if (key_len) { - priv->keys[index].key = kzalloc(key_len, GFP_KERNEL); + priv->keys[index].key = kzalloc(key_len, GFP_ATOMIC); if (!priv->keys[index].key) goto nomem; } else priv->keys[index].key = NULL; if (seq_len) { - priv->keys[index].seq = kzalloc(seq_len, GFP_KERNEL); + priv->keys[index].seq = kzalloc(seq_len, GFP_ATOMIC); if (!priv->keys[index].seq) goto free_key; } else diff --git a/drivers/net/wireless/rt2x00/rt2800.h b/drivers/net/wireless/rt2x00/rt2800.h index c5fe867665e..1a7eae357fe 100644 --- a/drivers/net/wireless/rt2x00/rt2800.h +++ b/drivers/net/wireless/rt2x00/rt2800.h @@ -1323,7 +1323,7 @@ #define PAIRWISE_KEY_ENTRY(__idx) \ ( PAIRWISE_KEY_TABLE_BASE + ((__idx) * sizeof(struct hw_key_entry)) ) #define MAC_IVEIV_ENTRY(__idx) \ - ( MAC_IVEIV_TABLE_BASE + ((__idx) & sizeof(struct mac_iveiv_entry)) ) + ( MAC_IVEIV_TABLE_BASE + ((__idx) * sizeof(struct mac_iveiv_entry)) ) #define MAC_WCID_ATTR_ENTRY(__idx) \ ( MAC_WCID_ATTRIBUTE_BASE + ((__idx) * sizeof(u32)) ) #define SHARED_KEY_ENTRY(__idx) \ diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c index eb1e1d00bec..27bf887f145 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/rt2x00/rt2800lib.c @@ -37,7 +37,7 @@ #include <linux/module.h> #include "rt2x00.h" -#ifdef CONFIG_RT2800USB +#if defined(CONFIG_RT2800USB) || defined(CONFIG_RT2800USB_MODULE) #include "rt2x00usb.h" #endif #include "rt2800lib.h" @@ -1121,7 +1121,7 @@ int rt2800_init_registers(struct rt2x00_dev *rt2x00dev) if (rt2x00_intf_is_usb(rt2x00dev)) { rt2800_register_write(rt2x00dev, USB_DMA_CFG, 0x00000000); -#ifdef CONFIG_RT2800USB +#if defined(CONFIG_RT2800USB) || defined(CONFIG_RT2800USB_MODULE) rt2x00usb_vendor_request_sw(rt2x00dev, USB_DEVICE_MODE, 0, USB_MODE_RESET, REGISTER_TIMEOUT); #endif @@ -2022,6 +2022,12 @@ int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev) u16 eeprom; /* + * Disable powersaving as default on PCI devices. + */ + if (rt2x00_intf_is_pci(rt2x00dev)) + rt2x00dev->hw->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT; + + /* * Initialize all hw fields. */ rt2x00dev->hw->flags = @@ -2074,8 +2080,7 @@ int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev) IEEE80211_HT_CAP_SGI_20 | IEEE80211_HT_CAP_SGI_40 | IEEE80211_HT_CAP_TX_STBC | - IEEE80211_HT_CAP_RX_STBC | - IEEE80211_HT_CAP_PSMP_SUPPORT; + IEEE80211_HT_CAP_RX_STBC; spec->ht.ampdu_factor = 3; spec->ht.ampdu_density = 4; spec->ht.mcs.tx_params = @@ -2140,8 +2145,8 @@ static void rt2800_get_tkip_seq(struct ieee80211_hw *hw, u8 hw_key_idx, rt2800_register_multiread(rt2x00dev, offset, &iveiv_entry, sizeof(iveiv_entry)); - memcpy(&iveiv_entry.iv[0], iv16, sizeof(iv16)); - memcpy(&iveiv_entry.iv[4], iv32, sizeof(iv32)); + memcpy(iv16, &iveiv_entry.iv[0], sizeof(*iv16)); + memcpy(iv32, &iveiv_entry.iv[4], sizeof(*iv32)); } static int rt2800_set_rts_threshold(struct ieee80211_hw *hw, u32 value) diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c index af85d18cdbe..ab95346cf6a 100644 --- a/drivers/net/wireless/rt2x00/rt2800usb.c +++ b/drivers/net/wireless/rt2x00/rt2800usb.c @@ -922,6 +922,7 @@ static struct usb_device_id rt2800usb_device_table[] = { { USB_DEVICE(0x1737, 0x0070), USB_DEVICE_DATA(&rt2800usb_ops) }, { USB_DEVICE(0x1737, 0x0071), USB_DEVICE_DATA(&rt2800usb_ops) }, { USB_DEVICE(0x1737, 0x0077), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x1737, 0x0079), USB_DEVICE_DATA(&rt2800usb_ops) }, /* Logitec */ { USB_DEVICE(0x0789, 0x0162), USB_DEVICE_DATA(&rt2800usb_ops) }, { USB_DEVICE(0x0789, 0x0163), USB_DEVICE_DATA(&rt2800usb_ops) }, diff --git a/drivers/net/wireless/rt2x00/rt61pci.c b/drivers/net/wireless/rt2x00/rt61pci.c index 687e17dc2e9..0ca589306d7 100644 --- a/drivers/net/wireless/rt2x00/rt61pci.c +++ b/drivers/net/wireless/rt2x00/rt61pci.c @@ -2539,6 +2539,11 @@ static int rt61pci_probe_hw_mode(struct rt2x00_dev *rt2x00dev) unsigned int i; /* + * Disable powersaving as default. + */ + rt2x00dev->hw->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT; + + /* * Initialize all hw fields. */ rt2x00dev->hw->flags = diff --git a/drivers/net/wireless/rtl818x/rtl8180_dev.c b/drivers/net/wireless/rtl818x/rtl8180_dev.c index a1a3dd15c66..8a40a143998 100644 --- a/drivers/net/wireless/rtl818x/rtl8180_dev.c +++ b/drivers/net/wireless/rtl818x/rtl8180_dev.c @@ -132,7 +132,6 @@ static void rtl8180_handle_rx(struct ieee80211_hw *dev) rx_status.antenna = (flags2 >> 15) & 1; /* TODO: improve signal/rssi reporting */ - rx_status.qual = flags2 & 0xFF; rx_status.signal = (flags2 >> 8) & 0x7F; /* XXX: is this correct? */ rx_status.rate_idx = (flags >> 20) & 0xF; diff --git a/drivers/net/wireless/wl12xx/wl1251_boot.c b/drivers/net/wireless/wl12xx/wl1251_boot.c index 2e733e7bdfd..28a80867408 100644 --- a/drivers/net/wireless/wl12xx/wl1251_boot.c +++ b/drivers/net/wireless/wl12xx/wl1251_boot.c @@ -256,7 +256,7 @@ int wl1251_boot_run_firmware(struct wl1251 *wl) } } - if (loop >= INIT_LOOP) { + if (loop > INIT_LOOP) { wl1251_error("timeout waiting for the hardware to " "complete initialization"); return -EIO; diff --git a/drivers/net/wireless/wl12xx/wl1271_cmd.c b/drivers/net/wireless/wl12xx/wl1271_cmd.c index 886a9bc39cc..c3385b3d246 100644 --- a/drivers/net/wireless/wl12xx/wl1271_cmd.c +++ b/drivers/net/wireless/wl12xx/wl1271_cmd.c @@ -777,7 +777,7 @@ out: return ret; } -static int wl1271_build_basic_rates(char *rates, u8 band) +static int wl1271_build_basic_rates(u8 *rates, u8 band) { u8 index = 0; @@ -804,7 +804,7 @@ static int wl1271_build_basic_rates(char *rates, u8 band) return index; } -static int wl1271_build_extended_rates(char *rates, u8 band) +static int wl1271_build_extended_rates(u8 *rates, u8 band) { u8 index = 0; diff --git a/drivers/net/wireless/zd1211rw/zd_chip.c b/drivers/net/wireless/zd1211rw/zd_chip.c index dfa1b9bc22c..7ca95c414fa 100644 --- a/drivers/net/wireless/zd1211rw/zd_chip.c +++ b/drivers/net/wireless/zd1211rw/zd_chip.c @@ -1325,151 +1325,11 @@ int zd_chip_set_basic_rates(struct zd_chip *chip, u16 cr_rates) return r; } -static int ofdm_qual_db(u8 status_quality, u8 zd_rate, unsigned int size) -{ - static const u16 constants[] = { - 715, 655, 585, 540, 470, 410, 360, 315, - 270, 235, 205, 175, 150, 125, 105, 85, - 65, 50, 40, 25, 15 - }; - - int i; - u32 x; - - /* It seems that their quality parameter is somehow per signal - * and is now transferred per bit. - */ - switch (zd_rate) { - case ZD_OFDM_RATE_6M: - case ZD_OFDM_RATE_12M: - case ZD_OFDM_RATE_24M: - size *= 2; - break; - case ZD_OFDM_RATE_9M: - case ZD_OFDM_RATE_18M: - case ZD_OFDM_RATE_36M: - case ZD_OFDM_RATE_54M: - size *= 4; - size /= 3; - break; - case ZD_OFDM_RATE_48M: - size *= 3; - size /= 2; - break; - default: - return -EINVAL; - } - - x = (10000 * status_quality)/size; - for (i = 0; i < ARRAY_SIZE(constants); i++) { - if (x > constants[i]) - break; - } - - switch (zd_rate) { - case ZD_OFDM_RATE_6M: - case ZD_OFDM_RATE_9M: - i += 3; - break; - case ZD_OFDM_RATE_12M: - case ZD_OFDM_RATE_18M: - i += 5; - break; - case ZD_OFDM_RATE_24M: - case ZD_OFDM_RATE_36M: - i += 9; - break; - case ZD_OFDM_RATE_48M: - case ZD_OFDM_RATE_54M: - i += 15; - break; - default: - return -EINVAL; - } - - return i; -} - -static int ofdm_qual_percent(u8 status_quality, u8 zd_rate, unsigned int size) -{ - int r; - - r = ofdm_qual_db(status_quality, zd_rate, size); - ZD_ASSERT(r >= 0); - if (r < 0) - r = 0; - - r = (r * 100)/29; - return r <= 100 ? r : 100; -} - -static unsigned int log10times100(unsigned int x) -{ - static const u8 log10[] = { - 0, - 0, 30, 47, 60, 69, 77, 84, 90, 95, 100, - 104, 107, 111, 114, 117, 120, 123, 125, 127, 130, - 132, 134, 136, 138, 139, 141, 143, 144, 146, 147, - 149, 150, 151, 153, 154, 155, 156, 157, 159, 160, - 161, 162, 163, 164, 165, 166, 167, 168, 169, 169, - 170, 171, 172, 173, 174, 174, 175, 176, 177, 177, - 178, 179, 179, 180, 181, 181, 182, 183, 183, 184, - 185, 185, 186, 186, 187, 188, 188, 189, 189, 190, - 190, 191, 191, 192, 192, 193, 193, 194, 194, 195, - 195, 196, 196, 197, 197, 198, 198, 199, 199, 200, - 200, 200, 201, 201, 202, 202, 202, 203, 203, 204, - 204, 204, 205, 205, 206, 206, 206, 207, 207, 207, - 208, 208, 208, 209, 209, 210, 210, 210, 211, 211, - 211, 212, 212, 212, 213, 213, 213, 213, 214, 214, - 214, 215, 215, 215, 216, 216, 216, 217, 217, 217, - 217, 218, 218, 218, 219, 219, 219, 219, 220, 220, - 220, 220, 221, 221, 221, 222, 222, 222, 222, 223, - 223, 223, 223, 224, 224, 224, 224, - }; - - return x < ARRAY_SIZE(log10) ? log10[x] : 225; -} - -enum { - MAX_CCK_EVM_DB = 45, -}; - -static int cck_evm_db(u8 status_quality) -{ - return (20 * log10times100(status_quality)) / 100; -} - -static int cck_snr_db(u8 status_quality) -{ - int r = MAX_CCK_EVM_DB - cck_evm_db(status_quality); - ZD_ASSERT(r >= 0); - return r; -} - -static int cck_qual_percent(u8 status_quality) -{ - int r; - - r = cck_snr_db(status_quality); - r = (100*r)/17; - return r <= 100 ? r : 100; -} - static inline u8 zd_rate_from_ofdm_plcp_header(const void *rx_frame) { return ZD_OFDM | zd_ofdm_plcp_header_rate(rx_frame); } -u8 zd_rx_qual_percent(const void *rx_frame, unsigned int size, - const struct rx_status *status) -{ - return (status->frame_status&ZD_RX_OFDM) ? - ofdm_qual_percent(status->signal_quality_ofdm, - zd_rate_from_ofdm_plcp_header(rx_frame), - size) : - cck_qual_percent(status->signal_quality_cck); -} - /** * zd_rx_rate - report zd-rate * @rx_frame - received frame diff --git a/drivers/net/wireless/zd1211rw/zd_chip.h b/drivers/net/wireless/zd1211rw/zd_chip.h index 9fd8f3508d6..f8bbf7d302a 100644 --- a/drivers/net/wireless/zd1211rw/zd_chip.h +++ b/drivers/net/wireless/zd1211rw/zd_chip.h @@ -929,9 +929,6 @@ static inline int zd_get_beacon_interval(struct zd_chip *chip, u32 *interval) struct rx_status; -u8 zd_rx_qual_percent(const void *rx_frame, unsigned int size, - const struct rx_status *status); - u8 zd_rx_rate(const void *rx_frame, const struct rx_status *status); struct zd_mc_hash { diff --git a/drivers/net/wireless/zd1211rw/zd_mac.c b/drivers/net/wireless/zd1211rw/zd_mac.c index cf51e8f8174..8ebf5c33955 100644 --- a/drivers/net/wireless/zd1211rw/zd_mac.c +++ b/drivers/net/wireless/zd1211rw/zd_mac.c @@ -828,9 +828,6 @@ int zd_mac_rx(struct ieee80211_hw *hw, const u8 *buffer, unsigned int length) stats.freq = zd_channels[_zd_chip_get_channel(&mac->chip) - 1].center_freq; stats.band = IEEE80211_BAND_2GHZ; stats.signal = status->signal_strength; - stats.qual = zd_rx_qual_percent(buffer, - length - sizeof(struct rx_status), - status); rate = zd_rx_rate(buffer, status); diff --git a/drivers/pci/hotplug/shpchp.h b/drivers/pci/hotplug/shpchp.h index bd588eb8e92..8e210cd76e5 100644 --- a/drivers/pci/hotplug/shpchp.h +++ b/drivers/pci/hotplug/shpchp.h @@ -121,7 +121,7 @@ struct controller { #define PCI_DEVICE_ID_AMD_GOLAM_7450 0x7450 #define PCI_DEVICE_ID_AMD_POGO_7458 0x7458 -/* AMD PCIX bridge registers */ +/* AMD PCI-X bridge registers */ #define PCIX_MEM_BASE_LIMIT_OFFSET 0x1C #define PCIX_MISCII_OFFSET 0x48 #define PCIX_MISC_BRIDGE_ERRORS_OFFSET 0x80 diff --git a/drivers/pci/intel-iommu.c b/drivers/pci/intel-iommu.c index e56f9bed6f2..417312528dd 100644 --- a/drivers/pci/intel-iommu.c +++ b/drivers/pci/intel-iommu.c @@ -305,7 +305,7 @@ struct device_domain_info { int segment; /* PCI domain */ u8 bus; /* PCI bus number */ u8 devfn; /* PCI devfn number */ - struct pci_dev *dev; /* it's NULL for PCIE-to-PCI bridge */ + struct pci_dev *dev; /* it's NULL for PCIe-to-PCI bridge */ struct intel_iommu *iommu; /* IOMMU used by this device */ struct dmar_domain *domain; /* pointer to domain */ }; @@ -1604,7 +1604,7 @@ domain_context_mapping(struct dmar_domain *domain, struct pci_dev *pdev, return ret; parent = parent->bus->self; } - if (pci_is_pcie(tmp)) /* this is a PCIE-to-PCI bridge */ + if (pci_is_pcie(tmp)) /* this is a PCIe-to-PCI bridge */ return domain_context_mapping_one(domain, pci_domain_nr(tmp->subordinate), tmp->subordinate->number, 0, @@ -3325,7 +3325,7 @@ static void iommu_detach_dependent_devices(struct intel_iommu *iommu, parent->devfn); parent = parent->bus->self; } - if (pci_is_pcie(tmp)) /* this is a PCIE-to-PCI bridge */ + if (pci_is_pcie(tmp)) /* this is a PCIe-to-PCI bridge */ iommu_detach_dev(iommu, tmp->subordinate->number, 0); else /* this is a legacy PCI bridge */ diff --git a/drivers/pci/intr_remapping.c b/drivers/pci/intr_remapping.c index 8b65a489581..95b849130ad 100644 --- a/drivers/pci/intr_remapping.c +++ b/drivers/pci/intr_remapping.c @@ -528,7 +528,7 @@ int set_msi_sid(struct irte *irte, struct pci_dev *dev) bridge = pci_find_upstream_pcie_bridge(dev); if (bridge) { - if (pci_is_pcie(bridge))/* this is a PCIE-to-PCI/PCIX bridge */ + if (pci_is_pcie(bridge))/* this is a PCIe-to-PCI/PCIX bridge */ set_irte_sid(irte, SVT_VERIFY_BUS, SQ_ALL_16, (bridge->bus->number << 8) | dev->bus->number); else /* this is a legacy PCI bridge */ diff --git a/drivers/pci/pci-acpi.c b/drivers/pci/pci-acpi.c index cc617ddd33d..7e2829538a4 100644 --- a/drivers/pci/pci-acpi.c +++ b/drivers/pci/pci-acpi.c @@ -112,11 +112,7 @@ static bool acpi_pci_can_wakeup(struct pci_dev *dev) static void acpi_pci_propagate_wakeup_enable(struct pci_bus *bus, bool enable) { while (bus->parent) { - struct pci_dev *bridge = bus->self; - int ret; - - ret = acpi_pm_device_sleep_wake(&bridge->dev, enable); - if (!ret || pci_is_pcie(bridge)) + if (!acpi_pm_device_sleep_wake(&bus->self->dev, enable)) return; bus = bus->parent; } @@ -131,9 +127,7 @@ static int acpi_pci_sleep_wake(struct pci_dev *dev, bool enable) if (acpi_pci_can_wakeup(dev)) return acpi_pm_device_sleep_wake(&dev->dev, enable); - if (!pci_is_pcie(dev)) - acpi_pci_propagate_wakeup_enable(dev->bus, enable); - + acpi_pci_propagate_wakeup_enable(dev->bus, enable); return 0; } diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index 0bc27e05901..0906599ebfd 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -1153,11 +1153,11 @@ pci_disable_device(struct pci_dev *dev) /** * pcibios_set_pcie_reset_state - set reset state for device dev - * @dev: the PCI-E device reset + * @dev: the PCIe device reset * @state: Reset state to enter into * * - * Sets the PCI-E reset state for the device. This is the default + * Sets the PCIe reset state for the device. This is the default * implementation. Architecture implementations can override this. */ int __attribute__ ((weak)) pcibios_set_pcie_reset_state(struct pci_dev *dev, @@ -1168,7 +1168,7 @@ int __attribute__ ((weak)) pcibios_set_pcie_reset_state(struct pci_dev *dev, /** * pci_set_pcie_reset_state - set reset state for device dev - * @dev: the PCI-E device reset + * @dev: the PCIe device reset * @state: Reset state to enter into * * @@ -2296,6 +2296,10 @@ static int pci_dev_reset(struct pci_dev *dev, int probe) down(&dev->dev.sem); } + rc = pci_dev_specific_reset(dev, probe); + if (rc != -ENOTTY) + goto done; + rc = pcie_flr(dev, probe); if (rc != -ENOTTY) goto done; @@ -2779,6 +2783,11 @@ int __attribute__ ((weak)) pci_ext_cfg_avail(struct pci_dev *dev) return 1; } +void __weak pci_fixup_cardbus(struct pci_bus *bus) +{ +} +EXPORT_SYMBOL(pci_fixup_cardbus); + static int __init pci_setup(char *str) { while (str) { diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h index 33ed8e0aba1..fbd0e3adbca 100644 --- a/drivers/pci/pci.h +++ b/drivers/pci/pci.h @@ -313,4 +313,12 @@ static inline int pci_resource_alignment(struct pci_dev *dev, extern void pci_enable_acs(struct pci_dev *dev); +struct pci_dev_reset_methods { + u16 vendor; + u16 device; + int (*reset)(struct pci_dev *dev, int probe); +}; + +extern int pci_dev_specific_reset(struct pci_dev *dev, int probe); + #endif /* DRIVERS_PCI_H */ diff --git a/drivers/pci/pcie/aer/Kconfig.debug b/drivers/pci/pcie/aer/Kconfig.debug index b8c925c1f6a..9142949734f 100644 --- a/drivers/pci/pcie/aer/Kconfig.debug +++ b/drivers/pci/pcie/aer/Kconfig.debug @@ -3,14 +3,14 @@ # config PCIEAER_INJECT - tristate "PCIE AER error injector support" + tristate "PCIe AER error injector support" depends on PCIEAER default n help This enables PCI Express Root Port Advanced Error Reporting (AER) software error injector. - Debuging PCIE AER code is quite difficult because it is hard + Debugging PCIe AER code is quite difficult because it is hard to trigger various real hardware errors. Software based error injection can fake almost all kinds of errors with the help of a user space helper tool aer-inject, which can be diff --git a/drivers/pci/pcie/aer/aer_inject.c b/drivers/pci/pcie/aer/aer_inject.c index 7fcd5331b14..797d47809f7 100644 --- a/drivers/pci/pcie/aer/aer_inject.c +++ b/drivers/pci/pcie/aer/aer_inject.c @@ -1,7 +1,7 @@ /* - * PCIE AER software error injection support. + * PCIe AER software error injection support. * - * Debuging PCIE AER code is quite difficult because it is hard to + * Debuging PCIe AER code is quite difficult because it is hard to * trigger various real hardware errors. Software based error * injection can fake almost all kinds of errors with the help of a * user space helper tool aer-inject, which can be gotten from: @@ -484,5 +484,5 @@ static void __exit aer_inject_exit(void) module_init(aer_inject_init); module_exit(aer_inject_exit); -MODULE_DESCRIPTION("PCIE AER software error injector"); +MODULE_DESCRIPTION("PCIe AER software error injector"); MODULE_LICENSE("GPL"); diff --git a/drivers/pci/pcie/aer/aerdrv.c b/drivers/pci/pcie/aer/aerdrv.c index 97a345927b5..21f215f4daa 100644 --- a/drivers/pci/pcie/aer/aerdrv.c +++ b/drivers/pci/pcie/aer/aerdrv.c @@ -155,7 +155,7 @@ static struct aer_rpc *aer_alloc_rpc(struct pcie_device *dev) mutex_init(&rpc->rpc_mutex); init_waitqueue_head(&rpc->wait_release); - /* Use PCIE bus function to store rpc into PCIE device */ + /* Use PCIe bus function to store rpc into PCIe device */ set_service_data(dev, rpc); return rpc; diff --git a/drivers/pci/pcie/aer/aerdrv_acpi.c b/drivers/pci/pcie/aer/aerdrv_acpi.c index 8edb2f300e8..04814087658 100644 --- a/drivers/pci/pcie/aer/aerdrv_acpi.c +++ b/drivers/pci/pcie/aer/aerdrv_acpi.c @@ -24,7 +24,7 @@ * * @return: Zero on success. Nonzero otherwise. * - * Invoked when PCIE bus loads AER service driver. To avoid conflict with + * Invoked when PCIe bus loads AER service driver. To avoid conflict with * BIOS AER support requires BIOS to yield AER control to OS native driver. **/ int aer_osc_setup(struct pcie_device *pciedev) diff --git a/drivers/pci/pcie/aer/aerdrv_core.c b/drivers/pci/pcie/aer/aerdrv_core.c index ae672ca8033..c843a799814 100644 --- a/drivers/pci/pcie/aer/aerdrv_core.c +++ b/drivers/pci/pcie/aer/aerdrv_core.c @@ -587,7 +587,7 @@ static void handle_error_source(struct pcie_device *aerdev, * aer_enable_rootport - enable Root Port's interrupts when receiving messages * @rpc: pointer to a Root Port data structure * - * Invoked when PCIE bus loads AER service driver. + * Invoked when PCIe bus loads AER service driver. */ void aer_enable_rootport(struct aer_rpc *rpc) { @@ -597,7 +597,7 @@ void aer_enable_rootport(struct aer_rpc *rpc) u32 reg32; pos = pci_pcie_cap(pdev); - /* Clear PCIE Capability's Device Status */ + /* Clear PCIe Capability's Device Status */ pci_read_config_word(pdev, pos+PCI_EXP_DEVSTA, ®16); pci_write_config_word(pdev, pos+PCI_EXP_DEVSTA, reg16); @@ -631,7 +631,7 @@ void aer_enable_rootport(struct aer_rpc *rpc) * disable_root_aer - disable Root Port's interrupts when receiving messages * @rpc: pointer to a Root Port data structure * - * Invoked when PCIE bus unloads AER service driver. + * Invoked when PCIe bus unloads AER service driver. */ static void disable_root_aer(struct aer_rpc *rpc) { diff --git a/drivers/pci/pcie/aer/aerdrv_errprint.c b/drivers/pci/pcie/aer/aerdrv_errprint.c index 44acde72294..9d3e4c8d018 100644 --- a/drivers/pci/pcie/aer/aerdrv_errprint.c +++ b/drivers/pci/pcie/aer/aerdrv_errprint.c @@ -184,7 +184,7 @@ void aer_print_error(struct pci_dev *dev, struct aer_err_info *info) if (info->status == 0) { AER_PR(info, dev, - "PCIE Bus Error: severity=%s, type=Unaccessible, " + "PCIe Bus Error: severity=%s, type=Unaccessible, " "id=%04x(Unregistered Agent ID)\n", aer_error_severity_string[info->severity], id); } else { @@ -194,7 +194,7 @@ void aer_print_error(struct pci_dev *dev, struct aer_err_info *info) agent = AER_GET_AGENT(info->severity, info->status); AER_PR(info, dev, - "PCIE Bus Error: severity=%s, type=%s, id=%04x(%s)\n", + "PCIe Bus Error: severity=%s, type=%s, id=%04x(%s)\n", aer_error_severity_string[info->severity], aer_error_layer[layer], id, aer_agent_string[agent]); diff --git a/drivers/pci/pcie/aspm.c b/drivers/pci/pcie/aspm.c index 5a01fc7fbf0..be53d98fa38 100644 --- a/drivers/pci/pcie/aspm.c +++ b/drivers/pci/pcie/aspm.c @@ -1,6 +1,6 @@ /* * File: drivers/pci/pcie/aspm.c - * Enabling PCIE link L0s/L1 state and Clock Power Management + * Enabling PCIe link L0s/L1 state and Clock Power Management * * Copyright (C) 2007 Intel * Copyright (C) Zhang Yanmin (yanmin.zhang@intel.com) @@ -499,7 +499,7 @@ static int pcie_aspm_sanity_check(struct pci_dev *pdev) int pos; u32 reg32; /* - * Some functions in a slot might not all be PCIE functions, + * Some functions in a slot might not all be PCIe functions, * very strange. Disable ASPM for the whole slot */ list_for_each_entry(child, &pdev->subordinate->devices, bus_list) { diff --git a/drivers/pci/pcie/portdrv_pci.c b/drivers/pci/pcie/portdrv_pci.c index a49452e2aed..34d65172a4d 100644 --- a/drivers/pci/pcie/portdrv_pci.c +++ b/drivers/pci/pcie/portdrv_pci.c @@ -24,7 +24,7 @@ */ #define DRIVER_VERSION "v1.0" #define DRIVER_AUTHOR "tom.l.nguyen@intel.com" -#define DRIVER_DESC "PCIE Port Bus Driver" +#define DRIVER_DESC "PCIe Port Bus Driver" MODULE_AUTHOR(DRIVER_AUTHOR); MODULE_DESCRIPTION(DRIVER_DESC); MODULE_LICENSE("GPL"); diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index 7cfa7c38d31..c74694345b6 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c @@ -2629,14 +2629,86 @@ static int __init pci_apply_final_quirks(void) if (!pci_cache_line_size) { printk(KERN_DEBUG "PCI: CLS %u bytes, default %u\n", cls << 2, pci_dfl_cache_line_size << 2); - pci_cache_line_size = cls; + pci_cache_line_size = cls ? cls : pci_dfl_cache_line_size; } return 0; } fs_initcall_sync(pci_apply_final_quirks); + +/* + * Followings are device-specific reset methods which can be used to + * reset a single function if other methods (e.g. FLR, PM D0->D3) are + * not available. + */ +static int reset_intel_generic_dev(struct pci_dev *dev, int probe) +{ + int pos; + + /* only implement PCI_CLASS_SERIAL_USB at present */ + if (dev->class == PCI_CLASS_SERIAL_USB) { + pos = pci_find_capability(dev, PCI_CAP_ID_VNDR); + if (!pos) + return -ENOTTY; + + if (probe) + return 0; + + pci_write_config_byte(dev, pos + 0x4, 1); + msleep(100); + + return 0; + } else { + return -ENOTTY; + } +} + +static int reset_intel_82599_sfp_virtfn(struct pci_dev *dev, int probe) +{ + int pos; + + pos = pci_find_capability(dev, PCI_CAP_ID_EXP); + if (!pos) + return -ENOTTY; + + if (probe) + return 0; + + pci_write_config_word(dev, pos + PCI_EXP_DEVCTL, + PCI_EXP_DEVCTL_BCR_FLR); + msleep(100); + + return 0; +} + +#define PCI_DEVICE_ID_INTEL_82599_SFP_VF 0x10ed + +static const struct pci_dev_reset_methods pci_dev_reset_methods[] = { + { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82599_SFP_VF, + reset_intel_82599_sfp_virtfn }, + { PCI_VENDOR_ID_INTEL, PCI_ANY_ID, + reset_intel_generic_dev }, + { 0 } +}; + +int pci_dev_specific_reset(struct pci_dev *dev, int probe) +{ + const struct pci_dev_reset_methods *i; + + for (i = pci_dev_reset_methods; i->reset; i++) { + if ((i->vendor == dev->vendor || + i->vendor == (u16)PCI_ANY_ID) && + (i->device == dev->device || + i->device == (u16)PCI_ANY_ID)) + return i->reset(dev, probe); + } + + return -ENOTTY; +} + #else void pci_fixup_device(enum pci_fixup_pass pass, struct pci_dev *dev) {} +int pci_dev_specific_reset(struct pci_dev *dev, int probe) { return -ENOTTY; } #endif EXPORT_SYMBOL(pci_fixup_device); diff --git a/drivers/pci/search.c b/drivers/pci/search.c index 6dae8714325..4a471dc4f4b 100644 --- a/drivers/pci/search.c +++ b/drivers/pci/search.c @@ -15,9 +15,9 @@ DECLARE_RWSEM(pci_bus_sem); /* - * find the upstream PCIE-to-PCI bridge of a PCI device + * find the upstream PCIe-to-PCI bridge of a PCI device * if the device is PCIE, return NULL - * if the device isn't connected to a PCIE bridge (that is its parent is a + * if the device isn't connected to a PCIe bridge (that is its parent is a * legacy PCI bridge and the bridge is directly connected to bus 0), return its * parent */ @@ -37,7 +37,7 @@ pci_find_upstream_pcie_bridge(struct pci_dev *pdev) tmp = pdev; continue; } - /* PCI device should connect to a PCIE bridge */ + /* PCI device should connect to a PCIe bridge */ if (pdev->pcie_type != PCI_EXP_TYPE_PCI_BRIDGE) { /* Busted hardware? */ WARN_ON_ONCE(1); diff --git a/drivers/pcmcia/cardbus.c b/drivers/pcmcia/cardbus.c index cdf50f3bc2d..d99f846451a 100644 --- a/drivers/pcmcia/cardbus.c +++ b/drivers/pcmcia/cardbus.c @@ -222,7 +222,7 @@ int __ref cb_alloc(struct pcmcia_socket *s) unsigned int max, pass; s->functions = pci_scan_slot(bus, PCI_DEVFN(0, 0)); -/* pcibios_fixup_bus(bus); */ + pci_fixup_cardbus(bus); max = bus->secondary; for (pass = 0; pass < 2; pass++) diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig index ec4faffe6b0..db32c25e360 100644 --- a/drivers/platform/x86/Kconfig +++ b/drivers/platform/x86/Kconfig @@ -231,8 +231,36 @@ config THINKPAD_ACPI This driver was formerly known as ibm-acpi. + Extra functionality will be available if the rfkill (CONFIG_RFKILL) + and/or ALSA (CONFIG_SND) subsystems are available in the kernel. + Note that if you want ThinkPad-ACPI to be built-in instead of + modular, ALSA and rfkill will also have to be built-in. + If you have an IBM or Lenovo ThinkPad laptop, say Y or M here. +config THINKPAD_ACPI_ALSA_SUPPORT + bool "Console audio control ALSA interface" + depends on THINKPAD_ACPI + depends on SND + depends on SND = y || THINKPAD_ACPI = SND + default y + ---help--- + Enables monitoring of the built-in console audio output control + (headphone and speakers), which is operated by the mute and (in + some ThinkPad models) volume hotkeys. + + If this option is enabled, ThinkPad-ACPI will export an ALSA card + with a single read-only mixer control, which should be used for + on-screen-display feedback purposes by the Desktop Environment. + + Optionally, the driver will also allow software control (the + ALSA mixer will be made read-write). Please refer to the driver + documentation for details. + + All IBM models have both volume and mute control. Newer Lenovo + models only have mute control (the volume hotkeys are just normal + keys and volume control is done through the main HDA mixer). + config THINKPAD_ACPI_DEBUGFACILITIES bool "Maintainer debug facilities" depends on THINKPAD_ACPI diff --git a/drivers/platform/x86/dell-wmi.c b/drivers/platform/x86/dell-wmi.c index 916ccb2b316..1b1dddbd574 100644 --- a/drivers/platform/x86/dell-wmi.c +++ b/drivers/platform/x86/dell-wmi.c @@ -202,8 +202,13 @@ static void dell_wmi_notify(u32 value, void *context) struct acpi_buffer response = { ACPI_ALLOCATE_BUFFER, NULL }; static struct key_entry *key; union acpi_object *obj; + acpi_status status; - wmi_get_event_data(value, &response); + status = wmi_get_event_data(value, &response); + if (status != AE_OK) { + printk(KERN_INFO "dell-wmi: bad event status 0x%x\n", status); + return; + } obj = (union acpi_object *)response.pointer; @@ -323,8 +328,9 @@ static int __init dell_wmi_input_setup(void) static int __init dell_wmi_init(void) { int err; + acpi_status status; - if (wmi_has_guid(DELL_EVENT_GUID)) { + if (!wmi_has_guid(DELL_EVENT_GUID)) { printk(KERN_WARNING "dell-wmi: No known WMI GUID found\n"); return -ENODEV; } @@ -336,14 +342,14 @@ static int __init dell_wmi_init(void) if (err) return err; - err = wmi_install_notify_handler(DELL_EVENT_GUID, + status = wmi_install_notify_handler(DELL_EVENT_GUID, dell_wmi_notify, NULL); - if (err) { + if (ACPI_FAILURE(status)) { input_unregister_device(dell_wmi_input_dev); printk(KERN_ERR "dell-wmi: Unable to register notify handler - %d\n", - err); - return err; + status); + return -ENODEV; } return 0; diff --git a/drivers/platform/x86/hp-wmi.c b/drivers/platform/x86/hp-wmi.c index 8781d8fa7a5..5b648f0c607 100644 --- a/drivers/platform/x86/hp-wmi.c +++ b/drivers/platform/x86/hp-wmi.c @@ -338,8 +338,13 @@ static void hp_wmi_notify(u32 value, void *context) static struct key_entry *key; union acpi_object *obj; int eventcode; + acpi_status status; - wmi_get_event_data(value, &response); + status = wmi_get_event_data(value, &response); + if (status != AE_OK) { + printk(KERN_INFO "hp-wmi: bad event status 0x%x\n", status); + return; + } obj = (union acpi_object *)response.pointer; @@ -581,7 +586,7 @@ static int __init hp_wmi_init(void) if (wmi_has_guid(HPWMI_EVENT_GUID)) { err = wmi_install_notify_handler(HPWMI_EVENT_GUID, hp_wmi_notify, NULL); - if (!err) + if (ACPI_SUCCESS(err)) hp_wmi_input_setup(); } diff --git a/drivers/platform/x86/msi-wmi.c b/drivers/platform/x86/msi-wmi.c index 7f77f908bb0..f5f70d4c691 100644 --- a/drivers/platform/x86/msi-wmi.c +++ b/drivers/platform/x86/msi-wmi.c @@ -149,8 +149,13 @@ static void msi_wmi_notify(u32 value, void *context) static struct key_entry *key; union acpi_object *obj; ktime_t cur; + acpi_status status; - wmi_get_event_data(value, &response); + status = wmi_get_event_data(value, &response); + if (status != AE_OK) { + printk(KERN_INFO DRV_PFX "bad event status 0x%x\n", status); + return; + } obj = (union acpi_object *)response.pointer; @@ -236,7 +241,7 @@ static int __init msi_wmi_init(void) } err = wmi_install_notify_handler(MSIWMI_EVENT_GUID, msi_wmi_notify, NULL); - if (err) + if (ACPI_FAILURE(err)) return -EINVAL; err = msi_wmi_input_setup(); diff --git a/drivers/platform/x86/thinkpad_acpi.c b/drivers/platform/x86/thinkpad_acpi.c index 448c8aeb166..e67e4feb35c 100644 --- a/drivers/platform/x86/thinkpad_acpi.c +++ b/drivers/platform/x86/thinkpad_acpi.c @@ -6384,11 +6384,13 @@ static struct ibm_struct brightness_driver_data = { * and we leave them unchanged. */ +#ifdef CONFIG_THINKPAD_ACPI_ALSA_SUPPORT + #define TPACPI_ALSA_DRVNAME "ThinkPad EC" #define TPACPI_ALSA_SHRTNAME "ThinkPad Console Audio Control" #define TPACPI_ALSA_MIXERNAME TPACPI_ALSA_SHRTNAME -static int alsa_index = SNDRV_DEFAULT_IDX1; +static int alsa_index = ~((1 << (SNDRV_CARDS - 3)) - 1); /* last three slots */ static char *alsa_id = "ThinkPadEC"; static int alsa_enable = SNDRV_DEFAULT_ENABLE1; @@ -6705,10 +6707,11 @@ static int __init volume_create_alsa_mixer(void) rc = snd_card_create(alsa_index, alsa_id, THIS_MODULE, sizeof(struct tpacpi_alsa_data), &card); - if (rc < 0) - return rc; - if (!card) - return -ENOMEM; + if (rc < 0 || !card) { + printk(TPACPI_ERR + "Failed to create ALSA card structures: %d\n", rc); + return 1; + } BUG_ON(!card->private_data); data = card->private_data; @@ -6741,8 +6744,9 @@ static int __init volume_create_alsa_mixer(void) rc = snd_ctl_add(card, ctl_vol); if (rc < 0) { printk(TPACPI_ERR - "Failed to create ALSA volume control\n"); - goto err_out; + "Failed to create ALSA volume control: %d\n", + rc); + goto err_exit; } data->ctl_vol_id = &ctl_vol->id; } @@ -6750,22 +6754,25 @@ static int __init volume_create_alsa_mixer(void) ctl_mute = snd_ctl_new1(&volume_alsa_control_mute, NULL); rc = snd_ctl_add(card, ctl_mute); if (rc < 0) { - printk(TPACPI_ERR "Failed to create ALSA mute control\n"); - goto err_out; + printk(TPACPI_ERR "Failed to create ALSA mute control: %d\n", + rc); + goto err_exit; } data->ctl_mute_id = &ctl_mute->id; snd_card_set_dev(card, &tpacpi_pdev->dev); rc = snd_card_register(card); - -err_out: if (rc < 0) { - snd_card_free(card); - card = NULL; + printk(TPACPI_ERR "Failed to register ALSA card: %d\n", rc); + goto err_exit; } alsa_card = card; - return rc; + return 0; + +err_exit: + snd_card_free(card); + return 1; } #define TPACPI_VOL_Q_MUTEONLY 0x0001 /* Mute-only control available */ @@ -7016,6 +7023,28 @@ static struct ibm_struct volume_driver_data = { .shutdown = volume_shutdown, }; +#else /* !CONFIG_THINKPAD_ACPI_ALSA_SUPPORT */ + +#define alsa_card NULL + +static void inline volume_alsa_notify_change(void) +{ +} + +static int __init volume_init(struct ibm_init_struct *iibm) +{ + printk(TPACPI_INFO + "volume: disabled as there is no ALSA support in this kernel\n"); + + return 1; +} + +static struct ibm_struct volume_driver_data = { + .name = "volume", +}; + +#endif /* CONFIG_THINKPAD_ACPI_ALSA_SUPPORT */ + /************************************************************************* * Fan subdriver */ @@ -8738,6 +8767,7 @@ MODULE_PARM_DESC(hotkey_report_mode, "used for backwards compatibility with userspace, " "see documentation"); +#ifdef CONFIG_THINKPAD_ACPI_ALSA_SUPPORT module_param_named(volume_mode, volume_mode, uint, 0444); MODULE_PARM_DESC(volume_mode, "Selects volume control strategy: " @@ -8760,6 +8790,7 @@ module_param_named(id, alsa_id, charp, 0444); MODULE_PARM_DESC(id, "ALSA id for the ACPI EC Mixer"); module_param_named(enable, alsa_enable, bool, 0444); MODULE_PARM_DESC(enable, "Enable the ALSA interface for the ACPI EC Mixer"); +#endif /* CONFIG_THINKPAD_ACPI_ALSA_SUPPORT */ #define TPACPI_PARAM(feature) \ module_param_call(feature, set_ibm_param, NULL, NULL, 0); \ diff --git a/drivers/platform/x86/wmi.c b/drivers/platform/x86/wmi.c index 9f93d6c0f51..b104302fea0 100644 --- a/drivers/platform/x86/wmi.c +++ b/drivers/platform/x86/wmi.c @@ -492,8 +492,7 @@ wmi_notify_handler handler, void *data) if (!guid || !handler) return AE_BAD_PARAMETER; - find_guid(guid, &block); - if (!block) + if (!find_guid(guid, &block)) return AE_NOT_EXIST; if (block->handler) @@ -521,8 +520,7 @@ acpi_status wmi_remove_notify_handler(const char *guid) if (!guid) return AE_BAD_PARAMETER; - find_guid(guid, &block); - if (!block) + if (!find_guid(guid, &block)) return AE_NOT_EXIST; if (!block->handler) @@ -716,6 +714,22 @@ static int wmi_class_init(void) return ret; } +static bool guid_already_parsed(const char *guid_string) +{ + struct guid_block *gblock; + struct wmi_block *wblock; + struct list_head *p; + + list_for_each(p, &wmi_blocks.list) { + wblock = list_entry(p, struct wmi_block, list); + gblock = &wblock->gblock; + + if (strncmp(gblock->guid, guid_string, 16) == 0) + return true; + } + return false; +} + /* * Parse the _WDG method for the GUID data blocks */ @@ -725,6 +739,7 @@ static __init acpi_status parse_wdg(acpi_handle handle) union acpi_object *obj; struct guid_block *gblock; struct wmi_block *wblock; + char guid_string[37]; acpi_status status; u32 i, total; @@ -747,6 +762,19 @@ static __init acpi_status parse_wdg(acpi_handle handle) memcpy(gblock, obj->buffer.pointer, obj->buffer.length); for (i = 0; i < total; i++) { + /* + Some WMI devices, like those for nVidia hooks, have a + duplicate GUID. It's not clear what we should do in this + case yet, so for now, we'll just ignore the duplicate. + Anyone who wants to add support for that device can come + up with a better workaround for the mess then. + */ + if (guid_already_parsed(gblock[i].guid) == true) { + wmi_gtoa(gblock[i].guid, guid_string); + printk(KERN_INFO PREFIX "Skipping duplicate GUID %s\n", + guid_string); + continue; + } wblock = kzalloc(sizeof(struct wmi_block), GFP_KERNEL); if (!wblock) return AE_NO_MEMORY; |