diff options
Diffstat (limited to 'drivers')
102 files changed, 1469 insertions, 905 deletions
diff --git a/drivers/char/tty_ldisc.c b/drivers/char/tty_ldisc.c index 1733d34..e48af9f 100644 --- a/drivers/char/tty_ldisc.c +++ b/drivers/char/tty_ldisc.c @@ -508,8 +508,9 @@ static void tty_ldisc_restore(struct tty_struct *tty, struct tty_ldisc *old) * be obtained while the delayed work queue halt ensures that no more * data is fed to the ldisc. * - * In order to wait for any existing references to complete see - * tty_ldisc_wait_idle. + * You need to do a 'flush_scheduled_work()' (outside the ldisc_mutex) + * in order to make sure any currently executing ldisc work is also + * flushed. */ static int tty_ldisc_halt(struct tty_struct *tty) @@ -753,11 +754,14 @@ void tty_ldisc_hangup(struct tty_struct *tty) * N_TTY. */ if (tty->driver->flags & TTY_DRIVER_RESET_TERMIOS) { + /* Make sure the old ldisc is quiescent */ + tty_ldisc_halt(tty); + flush_scheduled_work(); + /* Avoid racing set_ldisc or tty_ldisc_release */ mutex_lock(&tty->ldisc_mutex); if (tty->ldisc) { /* Not yet closed */ /* Switch back to N_TTY */ - tty_ldisc_halt(tty); tty_ldisc_reinit(tty); /* At this point we have a closed ldisc and we want to reopen it. We could defer this to the next open but diff --git a/drivers/clocksource/sh_cmt.c b/drivers/clocksource/sh_cmt.c index 2964f5f..6b3e0c2 100644 --- a/drivers/clocksource/sh_cmt.c +++ b/drivers/clocksource/sh_cmt.c @@ -40,6 +40,7 @@ struct sh_cmt_priv { struct platform_device *pdev; unsigned long flags; + unsigned long flags_suspend; unsigned long match_value; unsigned long next_match_value; unsigned long max_match_value; @@ -667,11 +668,38 @@ static int __devexit sh_cmt_remove(struct platform_device *pdev) return -EBUSY; /* cannot unregister clockevent and clocksource */ } +static int sh_cmt_suspend(struct device *dev) +{ + struct platform_device *pdev = to_platform_device(dev); + struct sh_cmt_priv *p = platform_get_drvdata(pdev); + + /* save flag state and stop CMT channel */ + p->flags_suspend = p->flags; + sh_cmt_stop(p, p->flags); + return 0; +} + +static int sh_cmt_resume(struct device *dev) +{ + struct platform_device *pdev = to_platform_device(dev); + struct sh_cmt_priv *p = platform_get_drvdata(pdev); + + /* start CMT channel from saved state */ + sh_cmt_start(p, p->flags_suspend); + return 0; +} + +static struct dev_pm_ops sh_cmt_dev_pm_ops = { + .suspend = sh_cmt_suspend, + .resume = sh_cmt_resume, +}; + static struct platform_driver sh_cmt_device_driver = { .probe = sh_cmt_probe, .remove = __devexit_p(sh_cmt_remove), .driver = { .name = "sh_cmt", + .pm = &sh_cmt_dev_pm_ops, } }; diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c index 33be210..2f631c7 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c @@ -258,31 +258,6 @@ void *drm_mode_object_find(struct drm_device *dev, uint32_t id, uint32_t type) EXPORT_SYMBOL(drm_mode_object_find); /** - * drm_crtc_from_fb - find the CRTC structure associated with an fb - * @dev: DRM device - * @fb: framebuffer in question - * - * LOCKING: - * Caller must hold mode_config lock. - * - * Find CRTC in the mode_config structure that matches @fb. - * - * RETURNS: - * Pointer to the CRTC or NULL if it wasn't found. - */ -struct drm_crtc *drm_crtc_from_fb(struct drm_device *dev, - struct drm_framebuffer *fb) -{ - struct drm_crtc *crtc; - - list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { - if (crtc->fb == fb) - return crtc; - } - return NULL; -} - -/** * drm_framebuffer_init - initialize a framebuffer * @dev: DRM device * @@ -328,11 +303,20 @@ void drm_framebuffer_cleanup(struct drm_framebuffer *fb) { struct drm_device *dev = fb->dev; struct drm_crtc *crtc; + struct drm_mode_set set; + int ret; /* remove from any CRTC */ list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { - if (crtc->fb == fb) - crtc->fb = NULL; + if (crtc->fb == fb) { + /* should turn off the crtc */ + memset(&set, 0, sizeof(struct drm_mode_set)); + set.crtc = crtc; + set.fb = NULL; + ret = crtc->funcs->set_config(&set); + if (ret) + DRM_ERROR("failed to reset crtc %p when fb was deleted\n", crtc); + } } drm_mode_object_put(dev, &fb->base); @@ -1511,7 +1495,7 @@ int drm_mode_setcrtc(struct drm_device *dev, void *data, set.mode = mode; set.connectors = connector_set; set.num_connectors = crtc_req->count_connectors; - set.fb =fb; + set.fb = fb; ret = crtc->funcs->set_config(&set); out: diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c index 80cc6d0..7f2728b 100644 --- a/drivers/gpu/drm/drm_edid.c +++ b/drivers/gpu/drm/drm_edid.c @@ -502,12 +502,40 @@ static int add_detailed_info(struct drm_connector *connector, struct detailed_non_pixel *data = &timing->data.other_data; struct drm_display_mode *newmode; - /* EDID up to and including 1.2 may put monitor info here */ - if (edid->version == 1 && edid->revision < 3) - continue; - - /* Detailed mode timing */ - if (timing->pixel_clock) { + /* X server check is version 1.1 or higher */ + if (edid->version == 1 && edid->revision >= 1 && + !timing->pixel_clock) { + /* Other timing or info */ + switch (data->type) { + case EDID_DETAIL_MONITOR_SERIAL: + break; + case EDID_DETAIL_MONITOR_STRING: + break; + case EDID_DETAIL_MONITOR_RANGE: + /* Get monitor range data */ + break; + case EDID_DETAIL_MONITOR_NAME: + break; + case EDID_DETAIL_MONITOR_CPDATA: + break; + case EDID_DETAIL_STD_MODES: + /* Five modes per detailed section */ + for (j = 0; j < 5; i++) { + struct std_timing *std; + struct drm_display_mode *newmode; + + std = &data->data.timings[j]; + newmode = drm_mode_std(dev, std); + if (newmode) { + drm_mode_probed_add(connector, newmode); + modes++; + } + } + break; + default: + break; + } + } else { newmode = drm_mode_detailed(dev, edid, timing, quirks); if (!newmode) continue; @@ -518,38 +546,6 @@ static int add_detailed_info(struct drm_connector *connector, drm_mode_probed_add(connector, newmode); modes++; - continue; - } - - /* Other timing or info */ - switch (data->type) { - case EDID_DETAIL_MONITOR_SERIAL: - break; - case EDID_DETAIL_MONITOR_STRING: - break; - case EDID_DETAIL_MONITOR_RANGE: - /* Get monitor range data */ - break; - case EDID_DETAIL_MONITOR_NAME: - break; - case EDID_DETAIL_MONITOR_CPDATA: - break; - case EDID_DETAIL_STD_MODES: - /* Five modes per detailed section */ - for (j = 0; j < 5; i++) { - struct std_timing *std; - struct drm_display_mode *newmode; - - std = &data->data.timings[j]; - newmode = drm_mode_std(dev, std); - if (newmode) { - drm_mode_probed_add(connector, newmode); - modes++; - } - } - break; - default: - break; } } diff --git a/drivers/gpu/drm/drm_sysfs.c b/drivers/gpu/drm/drm_sysfs.c index 85ec31b..f7a615b 100644 --- a/drivers/gpu/drm/drm_sysfs.c +++ b/drivers/gpu/drm/drm_sysfs.c @@ -22,44 +22,50 @@ #define to_drm_minor(d) container_of(d, struct drm_minor, kdev) #define to_drm_connector(d) container_of(d, struct drm_connector, kdev) +static struct device_type drm_sysfs_device_minor = { + .name = "drm_minor" +}; + /** - * drm_sysfs_suspend - DRM class suspend hook + * drm_class_suspend - DRM class suspend hook * @dev: Linux device to suspend * @state: power state to enter * * Just figures out what the actual struct drm_device associated with * @dev is and calls its suspend hook, if present. */ -static int drm_sysfs_suspend(struct device *dev, pm_message_t state) +static int drm_class_suspend(struct device *dev, pm_message_t state) { - struct drm_minor *drm_minor = to_drm_minor(dev); - struct drm_device *drm_dev = drm_minor->dev; - - if (drm_minor->type == DRM_MINOR_LEGACY && - !drm_core_check_feature(drm_dev, DRIVER_MODESET) && - drm_dev->driver->suspend) - return drm_dev->driver->suspend(drm_dev, state); - + if (dev->type == &drm_sysfs_device_minor) { + struct drm_minor *drm_minor = to_drm_minor(dev); + struct drm_device *drm_dev = drm_minor->dev; + + if (drm_minor->type == DRM_MINOR_LEGACY && + !drm_core_check_feature(drm_dev, DRIVER_MODESET) && + drm_dev->driver->suspend) + return drm_dev->driver->suspend(drm_dev, state); + } return 0; } /** - * drm_sysfs_resume - DRM class resume hook + * drm_class_resume - DRM class resume hook * @dev: Linux device to resume * * Just figures out what the actual struct drm_device associated with * @dev is and calls its resume hook, if present. */ -static int drm_sysfs_resume(struct device *dev) +static int drm_class_resume(struct device *dev) { - struct drm_minor *drm_minor = to_drm_minor(dev); - struct drm_device *drm_dev = drm_minor->dev; - - if (drm_minor->type == DRM_MINOR_LEGACY && - !drm_core_check_feature(drm_dev, DRIVER_MODESET) && - drm_dev->driver->resume) - return drm_dev->driver->resume(drm_dev); - + if (dev->type == &drm_sysfs_device_minor) { + struct drm_minor *drm_minor = to_drm_minor(dev); + struct drm_device *drm_dev = drm_minor->dev; + + if (drm_minor->type == DRM_MINOR_LEGACY && + !drm_core_check_feature(drm_dev, DRIVER_MODESET) && + drm_dev->driver->resume) + return drm_dev->driver->resume(drm_dev); + } return 0; } @@ -99,8 +105,8 @@ struct class *drm_sysfs_create(struct module *owner, char *name) goto err_out; } - class->suspend = drm_sysfs_suspend; - class->resume = drm_sysfs_resume; + class->suspend = drm_class_suspend; + class->resume = drm_class_resume; err = class_create_file(class, &class_attr_version); if (err) @@ -480,6 +486,7 @@ int drm_sysfs_device_add(struct drm_minor *minor) minor->kdev.class = drm_class; minor->kdev.release = drm_sysfs_device_release; minor->kdev.devt = minor->device; + minor->kdev.type = &drm_sysfs_device_minor; if (minor->type == DRM_MINOR_CONTROL) minor_str = "controlD%d"; else if (minor->type == DRM_MINOR_RENDER) diff --git a/drivers/gpu/drm/radeon/r100.c b/drivers/gpu/drm/radeon/r100.c index f1ba8ff..68e728e 100644 --- a/drivers/gpu/drm/radeon/r100.c +++ b/drivers/gpu/drm/radeon/r100.c @@ -254,6 +254,72 @@ void r100_mc_fini(struct radeon_device *rdev) /* + * Interrupts + */ +int r100_irq_set(struct radeon_device *rdev) +{ + uint32_t tmp = 0; + + if (rdev->irq.sw_int) { + tmp |= RADEON_SW_INT_ENABLE; + } + if (rdev->irq.crtc_vblank_int[0]) { + tmp |= RADEON_CRTC_VBLANK_MASK; + } + if (rdev->irq.crtc_vblank_int[1]) { + tmp |= RADEON_CRTC2_VBLANK_MASK; + } + WREG32(RADEON_GEN_INT_CNTL, tmp); + return 0; +} + +static inline uint32_t r100_irq_ack(struct radeon_device *rdev) +{ + uint32_t irqs = RREG32(RADEON_GEN_INT_STATUS); + uint32_t irq_mask = RADEON_SW_INT_TEST | RADEON_CRTC_VBLANK_STAT | + RADEON_CRTC2_VBLANK_STAT; + + if (irqs) { + WREG32(RADEON_GEN_INT_STATUS, irqs); + } + return irqs & irq_mask; +} + +int r100_irq_process(struct radeon_device *rdev) +{ + uint32_t status; + + status = r100_irq_ack(rdev); + if (!status) { + return IRQ_NONE; + } + while (status) { + /* SW interrupt */ + if (status & RADEON_SW_INT_TEST) { + radeon_fence_process(rdev); + } + /* Vertical blank interrupts */ + if (status & RADEON_CRTC_VBLANK_STAT) { + drm_handle_vblank(rdev->ddev, 0); + } + if (status & RADEON_CRTC2_VBLANK_STAT) { + drm_handle_vblank(rdev->ddev, 1); + } + status = r100_irq_ack(rdev); + } + return IRQ_HANDLED; +} + +u32 r100_get_vblank_counter(struct radeon_device *rdev, int crtc) +{ + if (crtc == 0) + return RREG32(RADEON_CRTC_CRNT_FRAME); + else + return RREG32(RADEON_CRTC2_CRNT_FRAME); +} + + +/* * Fence emission */ void r100_fence_ring_emit(struct radeon_device *rdev, @@ -1025,6 +1091,16 @@ static int r100_packet0_check(struct radeon_cs_parser *p, tmp |= tile_flags; ib[idx] = tmp; break; + case RADEON_RB3D_ZPASS_ADDR: + r = r100_cs_packet_next_reloc(p, &reloc); + if (r) { + DRM_ERROR("No reloc for ib[%d]=0x%04X\n", + idx, reg); + r100_cs_dump_packet(p, pkt); + return r; + } + ib[idx] = ib_chunk->kdata[idx] + ((u32)reloc->lobj.gpu_offset); + break; default: /* FIXME: we don't want to allow anyothers packet */ break; @@ -1556,26 +1632,6 @@ void r100_pll_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v) r100_pll_errata_after_data(rdev); } -uint32_t r100_mm_rreg(struct radeon_device *rdev, uint32_t reg) -{ - if (reg < 0x10000) - return readl(((void __iomem *)rdev->rmmio) + reg); - else { - writel(reg, ((void __iomem *)rdev->rmmio) + RADEON_MM_INDEX); - return readl(((void __iomem *)rdev->rmmio) + RADEON_MM_DATA); - } -} - -void r100_mm_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v) -{ - if (reg < 0x10000) - writel(v, ((void __iomem *)rdev->rmmio) + reg); - else { - writel(reg, ((void __iomem *)rdev->rmmio) + RADEON_MM_INDEX); - writel(v, ((void __iomem *)rdev->rmmio) + RADEON_MM_DATA); - } -} - int r100_init(struct radeon_device *rdev) { return 0; diff --git a/drivers/gpu/drm/radeon/r300.c b/drivers/gpu/drm/radeon/r300.c index 9c8d415..053f4ec 100644 --- a/drivers/gpu/drm/radeon/r300.c +++ b/drivers/gpu/drm/radeon/r300.c @@ -83,8 +83,8 @@ void rv370_pcie_gart_tlb_flush(struct radeon_device *rdev) WREG32_PCIE(RADEON_PCIE_TX_GART_CNTL, tmp | RADEON_PCIE_TX_GART_INVALIDATE_TLB); (void)RREG32_PCIE(RADEON_PCIE_TX_GART_CNTL); WREG32_PCIE(RADEON_PCIE_TX_GART_CNTL, tmp); - mb(); } + mb(); } int rv370_pcie_gart_enable(struct radeon_device *rdev) @@ -448,6 +448,7 @@ void r300_gpu_init(struct radeon_device *rdev) /* rv350,rv370,rv380 */ rdev->num_gb_pipes = 1; } + rdev->num_z_pipes = 1; gb_tile_config = (R300_ENABLE_TILING | R300_TILE_SIZE_16); switch (rdev->num_gb_pipes) { case 2: @@ -486,7 +487,8 @@ void r300_gpu_init(struct radeon_device *rdev) printk(KERN_WARNING "Failed to wait MC idle while " "programming pipes. Bad things might happen.\n"); } - DRM_INFO("radeon: %d pipes initialized.\n", rdev->num_gb_pipes); + DRM_INFO("radeon: %d quad pipes, %d Z pipes initialized.\n", + rdev->num_gb_pipes, rdev->num_z_pipes); } int r300_ga_reset(struct radeon_device *rdev) @@ -593,27 +595,6 @@ void r300_vram_info(struct radeon_device *rdev) /* - * Indirect registers accessor - */ -uint32_t rv370_pcie_rreg(struct radeon_device *rdev, uint32_t reg) -{ - uint32_t r; - - WREG8(RADEON_PCIE_INDEX, ((reg) & 0xff)); - (void)RREG32(RADEON_PCIE_INDEX); - r = RREG32(RADEON_PCIE_DATA); - return r; -} - -void rv370_pcie_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v) -{ - WREG8(RADEON_PCIE_INDEX, ((reg) & 0xff)); - (void)RREG32(RADEON_PCIE_INDEX); - WREG32(RADEON_PCIE_DATA, (v)); - (void)RREG32(RADEON_PCIE_DATA); -} - -/* * PCIE Lanes */ @@ -1403,6 +1384,21 @@ static int r300_packet0_check(struct radeon_cs_parser *p, tmp = (ib_chunk->kdata[idx] >> 22) & 0xF; track->textures[i].txdepth = tmp; break; + case R300_ZB_ZPASS_ADDR: + r = r100_cs_packet_next_reloc(p, &reloc); + if (r) { + DRM_ERROR("No reloc for ib[%d]=0x%04X\n", + idx, reg); + r100_cs_dump_packet(p, pkt); + return r; + } + ib[idx] = ib_chunk->kdata[idx] + ((u32)reloc->lobj.gpu_offset); + break; + case 0x4be8: + /* valid register only on RV530 */ + if (p->rdev->family == CHIP_RV530) + break; + /* fallthrough do not move */ default: printk(KERN_ERR "Forbidden register 0x%04X in cs at %d\n", reg, idx); diff --git a/drivers/gpu/drm/radeon/r420.c b/drivers/gpu/drm/radeon/r420.c index dea497a..97426a6 100644 --- a/drivers/gpu/drm/radeon/r420.c +++ b/drivers/gpu/drm/radeon/r420.c @@ -165,7 +165,18 @@ void r420_pipes_init(struct radeon_device *rdev) printk(KERN_WARNING "Failed to wait GUI idle while " "programming pipes. Bad things might happen.\n"); } - DRM_INFO("radeon: %d pipes initialized.\n", rdev->num_gb_pipes); + + if (rdev->family == CHIP_RV530) { + tmp = RREG32(RV530_GB_PIPE_SELECT2); + if ((tmp & 3) == 3) + rdev->num_z_pipes = 2; + else + rdev->num_z_pipes = 1; + } else + rdev->num_z_pipes = 1; + + DRM_INFO("radeon: %d quad pipes, %d z pipes initialized.\n", + rdev->num_gb_pipes, rdev->num_z_pipes); } void r420_gpu_init(struct radeon_device *rdev) diff --git a/drivers/gpu/drm/radeon/r500_reg.h b/drivers/gpu/drm/radeon/r500_reg.h index 036691b..e1d5e03 100644 --- a/drivers/gpu/drm/radeon/r500_reg.h +++ b/drivers/gpu/drm/radeon/r500_reg.h @@ -350,6 +350,7 @@ #define AVIVO_D1CRTC_BLANK_CONTROL 0x6084 #define AVIVO_D1CRTC_INTERLACE_CONTROL 0x6088 #define AVIVO_D1CRTC_INTERLACE_STATUS 0x608c +#define AVIVO_D1CRTC_FRAME_COUNT 0x60a4 #define AVIVO_D1CRTC_STEREO_CONTROL 0x60c4 /* master controls */ @@ -438,14 +439,15 @@ # define AVIVO_DC_LB_DISP1_END_ADR_SHIFT 4 # define AVIVO_DC_LB_DISP1_END_ADR_MASK 0x7ff -#define R500_DxMODE_INT_MASK 0x6540 -#define R500_D1MODE_INT_MASK (1<<0) -#define R500_D2MODE_INT_MASK (1<<8) - #define AVIVO_D1MODE_DATA_FORMAT 0x6528 # define AVIVO_D1MODE_INTERLEAVE_EN (1 << 0) #define AVIVO_D1MODE_DESKTOP_HEIGHT 0x652C +#define AVIVO_D1MODE_VBLANK_STATUS 0x6534 +# define AVIVO_VBLANK_ACK (1 << 4) #define AVIVO_D1MODE_VLINE_START_END 0x6538 +#define AVIVO_DxMODE_INT_MASK 0x6540 +# define AVIVO_D1MODE_INT_MASK (1 << 0) +# define AVIVO_D2MODE_INT_MASK (1 << 8) #define AVIVO_D1MODE_VIEWPORT_START 0x6580 #define AVIVO_D1MODE_VIEWPORT_SIZE 0x6584 #define AVIVO_D1MODE_EXT_OVERSCAN_LEFT_RIGHT 0x6588 @@ -475,6 +477,7 @@ #define AVIVO_D2CRTC_BLANK_CONTROL 0x6884 #define AVIVO_D2CRTC_INTERLACE_CONTROL 0x6888 #define AVIVO_D2CRTC_INTERLACE_STATUS 0x688c +#define AVIVO_D2CRTC_FRAME_COUNT 0x68a4 #define AVIVO_D2CRTC_STEREO_CONTROL 0x68c4 #define AVIVO_D2GRPH_ENABLE 0x6900 @@ -497,6 +500,7 @@ #define AVIVO_D2CUR_SIZE 0x6c10 #define AVIVO_D2CUR_POSITION 0x6c14 +#define AVIVO_D2MODE_VBLANK_STATUS 0x6d34 #define AVIVO_D2MODE_VLINE_START_END 0x6d38 #define AVIVO_D2MODE_VIEWPORT_START 0x6d80 #define AVIVO_D2MODE_VIEWPORT_SIZE 0x6d84 @@ -748,4 +752,8 @@ # define AVIVO_I2C_EN (1 << 0) # define AVIVO_I2C_RESET (1 << 8) +#define AVIVO_DISP_INTERRUPT_STATUS 0x7edc +# define AVIVO_D1_VBLANK_INTERRUPT (1 << 4) +# define AVIVO_D2_VBLANK_INTERRUPT (1 << 5) + #endif diff --git a/drivers/gpu/drm/radeon/r520.c b/drivers/gpu/drm/radeon/r520.c index 09fb0b6..ebd6b0f 100644 --- a/drivers/gpu/drm/radeon/r520.c +++ b/drivers/gpu/drm/radeon/r520.c @@ -177,7 +177,6 @@ void r520_gpu_init(struct radeon_device *rdev) */ /* workaround for RV530 */ if (rdev->family == CHIP_RV530) { - WREG32(0x4124, 1); WREG32(0x4128, 0xFF); } r420_pipes_init(rdev); diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h index b1d945b..b519fb2 100644 --- a/drivers/gpu/drm/radeon/radeon.h +++ b/drivers/gpu/drm/radeon/radeon.h @@ -242,6 +242,7 @@ int radeon_object_pin(struct radeon_object *robj, uint32_t domain, uint64_t *gpu_addr); void radeon_object_unpin(struct radeon_object *robj); int radeon_object_wait(struct radeon_object *robj); +int radeon_object_busy_domain(struct radeon_object *robj, uint32_t *cur_placement); int radeon_object_evict_vram(struct radeon_device *rdev); int radeon_object_mmap(struct radeon_object *robj, uint64_t *offset); void radeon_object_force_delete(struct radeon_device *rdev); @@ -574,6 +575,7 @@ struct radeon_asic { void (*ring_start)(struct radeon_device *rdev); int (*irq_set)(struct radeon_device *rdev); int (*irq_process)(struct radeon_device *rdev); + u32 (*get_vblank_counter)(struct radeon_device *rdev, int crtc); void (*fence_ring_emit)(struct radeon_device *rdev, struct radeon_fence *fence); int (*cs_parse)(struct radeon_cs_parser *p); int (*copy_blit)(struct radeon_device *rdev, @@ -653,6 +655,7 @@ struct radeon_device { int usec_timeout; enum radeon_pll_errata pll_errata; int num_gb_pipes; + int num_z_pipes; int disp_priority; /* BIOS */ uint8_t *bios; @@ -666,14 +669,11 @@ struct radeon_device { resource_size_t rmmio_base; resource_size_t rmmio_size; void *rmmio; - radeon_rreg_t mm_rreg; - radeon_wreg_t mm_wreg; radeon_rreg_t mc_rreg; radeon_wreg_t mc_wreg; radeon_rreg_t pll_rreg; radeon_wreg_t pll_wreg; - radeon_rreg_t pcie_rreg; - radeon_wreg_t pcie_wreg; + uint32_t pcie_reg_mask; radeon_rreg_t pciep_rreg; radeon_wreg_t pciep_wreg; struct radeon_clock clock; @@ -705,22 +705,42 @@ int radeon_device_init(struct radeon_device *rdev, void radeon_device_fini(struct radeon_device *rdev); int radeon_gpu_wait_for_idle(struct radeon_device *rdev); +static inline uint32_t r100_mm_rreg(struct radeon_device *rdev, uint32_t reg) +{ + if (reg < 0x10000) + return readl(((void __iomem *)rdev->rmmio) + reg); + else { + writel(reg, ((void __iomem *)rdev->rmmio) + RADEON_MM_INDEX); + return readl(((void __iomem *)rdev->rmmio) + RADEON_MM_DATA); + } +} + +static inline void r100_mm_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v) +{ + if (reg < 0x10000) + writel(v, ((void __iomem *)rdev->rmmio) + reg); + else { + writel(reg, ((void __iomem *)rdev->rmmio) + RADEON_MM_INDEX); + writel(v, ((void __iomem *)rdev->rmmio) + RADEON_MM_DATA); + } +} + /* * Registers read & write functions. */ #define RREG8(reg) readb(((void __iomem *)rdev->rmmio) + (reg)) #define WREG8(reg, v) writeb(v, ((void __iomem *)rdev->rmmio) + (reg)) -#define RREG32(reg) rdev->mm_rreg(rdev, (reg)) -#define WREG32(reg, v) rdev->mm_wreg(rdev, (reg), (v)) +#define RREG32(reg) r100_mm_rreg(rdev, (reg)) +#define WREG32(reg, v) r100_mm_wreg(rdev, (reg), (v)) #define REG_SET(FIELD, v) (((v) << FIELD##_SHIFT) & FIELD##_MASK) #define REG_GET(FIELD, v) (((v) << FIELD##_SHIFT) & FIELD##_MASK) #define RREG32_PLL(reg) rdev->pll_rreg(rdev, (reg)) #define WREG32_PLL(reg, v) rdev->pll_wreg(rdev, (reg), (v)) #define RREG32_MC(reg) rdev->mc_rreg(rdev, (reg)) #define WREG32_MC(reg, v) rdev->mc_wreg(rdev, (reg), (v)) -#define RREG32_PCIE(reg) rdev->pcie_rreg(rdev, (reg)) -#define WREG32_PCIE(reg, v) rdev->pcie_wreg(rdev, (reg), (v)) +#define RREG32_PCIE(reg) rv370_pcie_rreg(rdev, (reg)) +#define WREG32_PCIE(reg, v) rv370_pcie_wreg(rdev, (reg), (v)) #define WREG32_P(reg, val, mask) \ do { \ uint32_t tmp_ = RREG32(reg); \ @@ -736,6 +756,24 @@ int radeon_gpu_wait_for_idle(struct radeon_device *rdev); WREG32_PLL(reg, tmp_); \ } while (0) +/* + * Indirect registers accessor + */ +static inline uint32_t rv370_pcie_rreg(struct radeon_device *rdev, uint32_t reg) +{ + uint32_t r; + + WREG32(RADEON_PCIE_INDEX, ((reg) & rdev->pcie_reg_mask)); + r = RREG32(RADEON_PCIE_DATA); + return r; +} + +static inline void rv370_pcie_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v) +{ + WREG32(RADEON_PCIE_INDEX, ((reg) & rdev->pcie_reg_mask)); + WREG32(RADEON_PCIE_DATA, (v)); +} + void r100_pll_errata_after_index(struct radeon_device *rdev); @@ -862,6 +900,7 @@ static inline void radeon_ring_write(struct radeon_device *rdev, uint32_t v) #define radeon_ring_start(rdev) (rdev)->asic->ring_start((rdev)) #define radeon_irq_set(rdev) (rdev)->asic->irq_set((rdev)) #define radeon_irq_process(rdev) (rdev)->asic->irq_process((rdev)) +#define radeon_get_vblank_counter(rdev, crtc) (rdev)->asic->get_vblank_counter((rdev), (crtc)) #define radeon_fence_ring_emit(rdev, fence) (rdev)->asic->fence_ring_emit((rdev), (fence)) #define radeon_copy_blit(rdev, s, d, np, f) (rdev)->asic->copy_blit((rdev), (s), (d), (np), (f)) #define radeon_copy_dma(rdev, s, d, np, f) (rdev)->asic->copy_dma((rdev), (s), (d), (np), (f)) diff --git a/drivers/gpu/drm/radeon/radeon_asic.h b/drivers/gpu/drm/radeon/radeon_asic.h index 9a75876..7ca6c13 100644 --- a/drivers/gpu/drm/radeon/radeon_asic.h +++ b/drivers/gpu/drm/radeon/radeon_asic.h @@ -49,6 +49,7 @@ void r100_vram_info(struct radeon_device *rdev); int r100_gpu_reset(struct radeon_device *rdev); int r100_mc_init(struct radeon_device *rdev); void r100_mc_fini(struct radeon_device *rdev); +u32 r100_get_vblank_counter(struct radeon_device *rdev, int crtc); int r100_wb_init(struct radeon_device *rdev); void r100_wb_fini(struct radeon_device *rdev); int r100_gart_enable(struct radeon_device *rdev); @@ -96,6 +97,7 @@ static struct radeon_asic r100_asic = { .ring_start = &r100_ring_start, .irq_set = &r100_irq_set, .irq_process = &r100_irq_process, + .get_vblank_counter = &r100_get_vblank_counter, .fence_ring_emit = &r100_fence_ring_emit, .cs_parse = &r100_cs_parse, .copy_blit = &r100_copy_blit, @@ -156,6 +158,7 @@ static struct radeon_asic r300_asic = { .ring_start = &r300_ring_start, .irq_set = &r100_irq_set, .irq_process = &r100_irq_process, + .get_vblank_counter = &r100_get_vblank_counter, .fence_ring_emit = &r300_fence_ring_emit, .cs_parse = &r300_cs_parse, .copy_blit = &r100_copy_blit, @@ -196,6 +199,7 @@ static struct radeon_asic r420_asic = { .ring_start = &r300_ring_start, .irq_set = &r100_irq_set, .irq_process = &r100_irq_process, + .get_vblank_counter = &r100_get_vblank_counter, .fence_ring_emit = &r300_fence_ring_emit, .cs_parse = &r300_cs_parse, .copy_blit = &r100_copy_blit, @@ -243,6 +247,7 @@ static struct radeon_asic rs400_asic = { .ring_start = &r300_ring_start, .irq_set = &r100_irq_set, .irq_process = &r100_irq_process, + .get_vblank_counter = &r100_get_vblank_counter, .fence_ring_emit = &r300_fence_ring_emit, .cs_parse = &r300_cs_parse, .copy_blit = &r100_copy_blit, @@ -266,6 +271,8 @@ void rs600_vram_info(struct radeon_device *rdev); int rs600_mc_init(struct radeon_device *rdev); void rs600_mc_fini(struct radeon_device *rdev); int rs600_irq_set(struct radeon_device *rdev); +int rs600_irq_process(struct radeon_device *rdev); +u32 rs600_get_vblank_counter(struct radeon_device *rdev, int crtc); int rs600_gart_enable(struct radeon_device *rdev); void rs600_gart_disable(struct radeon_device *rdev); void rs600_gart_tlb_flush(struct radeon_device *rdev); @@ -291,7 +298,8 @@ static struct radeon_asic rs600_asic = { .cp_disable = &r100_cp_disable, .ring_start = &r300_ring_start, .irq_set = &rs600_irq_set, - .irq_process = &r100_irq_process, + .irq_process = &rs600_irq_process, + .get_vblank_counter = &rs600_get_vblank_counter, .fence_ring_emit = &r300_fence_ring_emit, .cs_parse = &r300_cs_parse, .copy_blit = &r100_copy_blit, @@ -308,6 +316,7 @@ static struct radeon_asic rs600_asic = { /* * rs690,rs740 */ +int rs690_init(struct radeon_device *rdev); void rs690_errata(struct radeon_device *rdev); void rs690_vram_info(struct radeon_device *rdev); int rs690_mc_init(struct radeon_device *rdev); @@ -316,7 +325,7 @@ uint32_t rs690_mc_rreg(struct radeon_device *rdev, uint32_t reg); void rs690_mc_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v); void rs690_bandwidth_update(struct radeon_device *rdev); static struct radeon_asic rs690_asic = { - .init = &r300_init, + .init = &rs690_init, .errata = &rs690_errata, .vram_info = &rs690_vram_info, .gpu_reset = &r300_gpu_reset, @@ -333,7 +342,8 @@ static struct radeon_asic rs690_asic = { .cp_disable = &r100_cp_disable, .ring_start = &r300_ring_start, .irq_set = &rs600_irq_set, - .irq_process = &r100_irq_process, + .irq_process = &rs600_irq_process, + .get_vblank_counter = &rs600_get_vblank_counter, .fence_ring_emit = &r300_fence_ring_emit, .cs_parse = &r300_cs_parse, .copy_blit = &r100_copy_blit, @@ -381,8 +391,9 @@ static struct radeon_asic rv515_asic = { .cp_fini = &r100_cp_fini, .cp_disable = &r100_cp_disable, .ring_start = &rv515_ring_start, - .irq_set = &r100_irq_set, - .irq_process = &r100_irq_process, + .irq_set = &rs600_irq_set, + .irq_process = &rs600_irq_process, + .get_vblank_counter = &rs600_get_vblank_counter, .fence_ring_emit = &r300_fence_ring_emit, .cs_parse = &r300_cs_parse, .copy_blit = &r100_copy_blit, @@ -423,8 +434,9 @@ static struct radeon_asic r520_asic = { .cp_fini = &r100_cp_fini, .cp_disable = &r100_cp_disable, .ring_start = &rv515_ring_start, - .irq_set = &r100_irq_set, - .irq_process = &r100_irq_process, + .irq_set = &rs600_irq_set, + .irq_process = &rs600_irq_process, + .get_vblank_counter = &rs600_get_vblank_counter, .fence_ring_emit = &r300_fence_ring_emit, .cs_parse = &r300_cs_parse, .copy_blit = &r100_copy_blit, diff --git a/drivers/gpu/drm/radeon/radeon_combios.c b/drivers/gpu/drm/radeon/radeon_combios.c index afc4db2..2a027e0 100644 --- a/drivers/gpu/drm/radeon/radeon_combios.c +++ b/drivers/gpu/drm/radeon/radeon_combios.c @@ -685,23 +685,15 @@ static const uint32_t default_tvdac_adj[CHIP_LAST] = { 0x00780000, /* rs480 */ }; -static struct radeon_encoder_tv_dac - *radeon_legacy_get_tv_dac_info_from_table(struct radeon_device *rdev) +static void radeon_legacy_get_tv_dac_info_from_table(struct radeon_device *rdev, + struct radeon_encoder_tv_dac *tv_dac) { - struct radeon_encoder_tv_dac *tv_dac = NULL; - - tv_dac = kzalloc(sizeof(struct radeon_encoder_tv_dac), GFP_KERNEL); - - if (!tv_dac) - return NULL; - tv_dac->ps2_tvdac_adj = default_tvdac_adj[rdev->family]; if ((rdev->flags & RADEON_IS_MOBILITY) && (rdev->family == CHIP_RV250)) tv_dac->ps2_tvdac_adj = 0x00880000; tv_dac->pal_tvdac_adj = tv_dac->ps2_tvdac_adj; tv_dac->ntsc_tvdac_adj = tv_dac->ps2_tvdac_adj; - - return tv_dac; + return; } struct radeon_encoder_tv_dac *radeon_combios_get_tv_dac_info(struct @@ -713,19 +705,18 @@ struct radeon_encoder_tv_dac *radeon_combios_get_tv_dac_info(struct uint16_t dac_info; uint8_t rev, bg, dac; struct radeon_encoder_tv_dac *tv_dac = NULL; + int found = 0; + + tv_dac = kzalloc(sizeof(struct radeon_encoder_tv_dac), GFP_KERNEL); + if (!tv_dac) + return NULL; if (rdev->bios == NULL) - return radeon_legacy_get_tv_dac_info_from_table(rdev); + goto out; /* first check TV table */ dac_info = combios_get_table_offset(dev, COMBIOS_TV_INFO_TABLE); if (dac_info) { - tv_dac = - kzalloc(sizeof(struct radeon_encoder_tv_dac), GFP_KERNEL); - - if (!tv_dac) - return NULL; - rev = RBIOS8(dac_info + 0x3); if (rev > 4) { bg = RBIOS8(dac_info + 0xc) & 0xf; @@ -739,6 +730,7 @@ struct radeon_encoder_tv_dac *radeon_combios_get_tv_dac_info(struct bg = RBIOS8(dac_info + 0x10) & 0xf; dac = RBIOS8(dac_info + 0x11) & 0xf; tv_dac->ntsc_tvdac_adj = (bg << 16) | (dac << 20); + found = 1; } else if (rev > 1) { bg = RBIOS8(dac_info + 0xc) & 0xf; dac = (RBIOS8(dac_info + 0xc) >> 4) & 0xf; @@ -751,22 +743,15 @@ struct radeon_encoder_tv_dac *radeon_combios_get_tv_dac_info(struct bg = RBIOS8(dac_info + 0xe) & 0xf; dac = (RBIOS8(dac_info + 0xe) >> 4) & 0xf; tv_dac->ntsc_tvdac_adj = (bg << 16) | (dac << 20); + found = 1; } - tv_dac->tv_std = radeon_combios_get_tv_info(encoder); - - } else { + } + if (!found) { /* then check CRT table */ dac_info = combios_get_table_offset(dev, COMBIOS_CRT_INFO_TABLE); if (dac_info) { - tv_dac = - kzalloc(sizeof(struct radeon_encoder_tv_dac), - GFP_KERNEL); - - if (!tv_dac) - return NULL; - rev = RBIOS8(dac_info) & 0x3; if (rev < 2) { bg = RBIOS8(dac_info + 0x3) & 0xf; @@ -775,6 +760,7 @@ struct radeon_encoder_tv_dac *radeon_combios_get_tv_dac_info(struct (bg << 16) | (dac << 20); tv_dac->pal_tvdac_adj = tv_dac->ps2_tvdac_adj; tv_dac->ntsc_tvdac_adj = tv_dac->ps2_tvdac_adj; + found = 1; } else { bg = RBIOS8(dac_info + 0x4) & 0xf; dac = RBIOS8(dac_info + 0x5) & 0xf; @@ -782,13 +768,17 @@ struct radeon_encoder_tv_dac *radeon_combios_get_tv_dac_info(struct (bg << 16) | (dac << 20); tv_dac->pal_tvdac_adj = tv_dac->ps2_tvdac_adj; tv_dac->ntsc_tvdac_adj = tv_dac->ps2_tvdac_adj; + found = 1; } } else { DRM_INFO("No TV DAC info found in BIOS\n"); - return radeon_legacy_get_tv_dac_info_from_table(rdev); } } +out: + if (!found) /* fallback to defaults */ + radeon_legacy_get_tv_dac_info_from_table(rdev, tv_dac); + return tv_dac; } diff --git a/drivers/gpu/drm/radeon/radeon_cp.c b/drivers/gpu/drm/radeon/radeon_cp.c index d835682..7a52c46 100644 --- a/drivers/gpu/drm/radeon/radeon_cp.c +++ b/drivers/gpu/drm/radeon/radeon_cp.c @@ -406,6 +406,15 @@ static void radeon_init_pipes(drm_radeon_private_t *dev_priv) { uint32_t gb_tile_config, gb_pipe_sel = 0; + if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV530) { + uint32_t z_pipe_sel = RADEON_READ(RV530_GB_PIPE_SELECT2); + if ((z_pipe_sel & 3) == 3) + dev_priv->num_z_pipes = 2; + else + dev_priv->num_z_pipes = 1; + } else + dev_priv->num_z_pipes = 1; + /* RS4xx/RS6xx/R4xx/R5xx */ if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_R420) { gb_pipe_sel = RADEON_READ(R400_GB_PIPE_SELECT); diff --git a/drivers/gpu/drm/radeon/radeon_device.c b/drivers/gpu/drm/radeon/radeon_device.c index 9ff6dcb..7693f7c 100644 --- a/drivers/gpu/drm/radeon/radeon_device.c +++ b/drivers/gpu/drm/radeon/radeon_device.c @@ -225,25 +225,18 @@ void radeon_invalid_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v) void radeon_register_accessor_init(struct radeon_device *rdev) { - rdev->mm_rreg = &r100_mm_rreg; - rdev->mm_wreg = &r100_mm_wreg; rdev->mc_rreg = &radeon_invalid_rreg; rdev->mc_wreg = &radeon_invalid_wreg; rdev->pll_rreg = &radeon_invalid_rreg; rdev->pll_wreg = &radeon_invalid_wreg; - rdev->pcie_rreg = &radeon_invalid_rreg; - rdev->pcie_wreg = &radeon_invalid_wreg; rdev->pciep_rreg = &radeon_invalid_rreg; rdev->pciep_wreg = &radeon_invalid_wreg; /* Don't change order as we are overridding accessor. */ if (rdev->family < CHIP_RV515) { - rdev->pcie_rreg = &rv370_pcie_rreg; - rdev->pcie_wreg = &rv370_pcie_wreg; - } - if (rdev->family >= CHIP_RV515) { - rdev->pcie_rreg = &rv515_pcie_rreg; - rdev->pcie_wreg = &rv515_pcie_wreg; + rdev->pcie_reg_mask = 0xff; + } else { + rdev->pcie_reg_mask = 0x7ff; } /* FIXME: not sure here */ if (rdev->family <= CHIP_R580) { diff --git a/drivers/gpu/drm/radeon/radeon_drv.h b/drivers/gpu/drm/radeon/radeon_drv.h index 3933f82..6fa32da 100644 --- a/drivers/gpu/drm/radeon/radeon_drv.h +++ b/drivers/gpu/drm/radeon/radeon_drv.h @@ -100,9 +100,10 @@ * 1.28- Add support for VBL on CRTC2 * 1.29- R500 3D cmd buffer support * 1.30- Add support for occlusion queries + * 1.31- Add support for num Z pipes from GET_PARAM */ #define DRIVER_MAJOR 1 -#define DRIVER_MINOR 30 +#define DRIVER_MINOR 31 #define DRIVER_PATCHLEVEL 0 /* @@ -329,6 +330,7 @@ typedef struct drm_radeon_private { resource_size_t fb_aper_offset; int num_gb_pipes; + int num_z_pipes; int track_flush; drm_local_map_t *mmio; @@ -689,6 +691,7 @@ extern void r600_page_table_cleanup(struct drm_device *dev, struct drm_ati_pciga /* pipe config regs */ #define R400_GB_PIPE_SELECT 0x402c +#define RV530_GB_PIPE_SELECT2 0x4124 #define R500_DYN_SCLK_PWMEM_PIPE 0x000d /* PLL */ #define R300_GB_TILE_CONFIG 0x4018 # define R300_ENABLE_TILING (1 << 0) diff --git a/drivers/gpu/drm/radeon/radeon_fb.c b/drivers/gpu/drm/radeon/radeon_fb.c index 3206c0a..ec383ed 100644 --- a/drivers/gpu/drm/radeon/radeon_fb.c +++ b/drivers/gpu/drm/radeon/radeon_fb.c @@ -574,6 +574,8 @@ int radeonfb_create(struct radeon_device *rdev, goto out_unref; } + memset_io(fbptr, 0, aligned_size); + strcpy(info->fix.id, "radeondrmfb"); info->fix.type = FB_TYPE_PACKED_PIXELS; info->fix.visual = FB_VISUAL_TRUECOLOR; diff --git a/drivers/gpu/drm/radeon/radeon_gem.c b/drivers/gpu/drm/radeon/radeon_gem.c index cded518..d880edf 100644 --- a/drivers/gpu/drm/radeon/radeon_gem.c +++ b/drivers/gpu/drm/radeon/radeon_gem.c @@ -262,8 +262,34 @@ int radeon_gem_mmap_ioctl(struct drm_device *dev, void *data, int radeon_gem_busy_ioctl(struct drm_device *dev, void *data, struct drm_file *filp) { - /* FIXME: implement */ - return 0; + struct drm_radeon_gem_busy *args = data; + struct drm_gem_object *gobj; + struct radeon_object *robj; + int r; + uint32_t cur_placement; + + gobj = drm_gem_object_lookup(dev, filp, args->handle); + if (gobj == NULL) { + return -EINVAL; + } + robj = gobj->driver_private; + r = radeon_object_busy_domain(robj, &cur_placement); + switch (cur_placement) { + case TTM_PL_VRAM: + args->domain = RADEON_GEM_DOMAIN_VRAM; + break; + case TTM_PL_TT: + args->domain = RADEON_GEM_DOMAIN_GTT; + break; + case TTM_PL_SYSTEM: + args->domain = RADEON_GEM_DOMAIN_CPU; + default: + break; + } + mutex_lock(&dev->struct_mutex); + drm_gem_object_unreference(gobj); + mutex_unlock(&dev->struct_mutex); + return r; } int radeon_gem_wait_idle_ioctl(struct drm_device *dev, void *data, diff --git a/drivers/gpu/drm/radeon/radeon_irq_kms.c b/drivers/gpu/drm/radeon/radeon_irq_kms.c index 491d569..9805e4b 100644 --- a/drivers/gpu/drm/radeon/radeon_irq_kms.c +++ b/drivers/gpu/drm/radeon/radeon_irq_kms.c @@ -32,60 +32,6 @@ #include "radeon.h" #include "atom.h" -static inline uint32_t r100_irq_ack(struct radeon_device *rdev) -{ - uint32_t irqs = RREG32(RADEON_GEN_INT_STATUS); - uint32_t irq_mask = RADEON_SW_INT_TEST; - - if (irqs) { - WREG32(RADEON_GEN_INT_STATUS, irqs); - } - return irqs & irq_mask; -} - -int r100_irq_set(struct radeon_device *rdev) -{ - uint32_t tmp = 0; - - if (rdev->irq.sw_int) { - tmp |= RADEON_SW_INT_ENABLE; - } - /* Todo go through CRTC and enable vblank int or not */ - WREG32(RADEON_GEN_INT_CNTL, tmp); - return 0; -} - -int r100_irq_process(struct radeon_device *rdev) -{ - uint32_t status; - - status = r100_irq_ack(rdev); - if (!status) { - return IRQ_NONE; - } - while (status) { - /* SW interrupt */ - if (status & RADEON_SW_INT_TEST) { - radeon_fence_process(rdev); - } - status = r100_irq_ack(rdev); - } - return IRQ_HANDLED; -} - -int rs600_irq_set(struct radeon_device *rdev) -{ - uint32_t tmp = 0; - - if (rdev->irq.sw_int) { - tmp |= RADEON_SW_INT_ENABLE; - } - WREG32(RADEON_GEN_INT_CNTL, tmp); - /* Todo go through CRTC and enable vblank int or not */ - WREG32(R500_DxMODE_INT_MASK, 0); - return 0; -} - irqreturn_t radeon_driver_irq_handler_kms(DRM_IRQ_ARGS) { struct drm_device *dev = (struct drm_device *) arg; diff --git a/drivers/gpu/drm/radeon/radeon_kms.c b/drivers/gpu/drm/radeon/radeon_kms.c index 3357110..dce09ad 100644 --- a/drivers/gpu/drm/radeon/radeon_kms.c +++ b/drivers/gpu/drm/radeon/radeon_kms.c @@ -95,6 +95,9 @@ int radeon_info_ioctl(struct drm_device *dev, void *data, struct drm_file *filp) case RADEON_INFO_NUM_GB_PIPES: value = rdev->num_gb_pipes; break; + case RADEON_INFO_NUM_Z_PIPES: + value = rdev->num_z_pipes; + break; default: DRM_DEBUG("Invalid request %d\n", info->request); return -EINVAL; @@ -141,19 +144,42 @@ void radeon_driver_preclose_kms(struct drm_device *dev, */ u32 radeon_get_vblank_counter_kms(struct drm_device *dev, int crtc) { - /* FIXME: implement */ - return 0; + struct radeon_device *rdev = dev->dev_private; + + if (crtc < 0 || crtc > 1) { + DRM_ERROR("Invalid crtc %d\n", crtc); + return -EINVAL; + } + + return radeon_get_vblank_counter(rdev, crtc); } int radeon_enable_vblank_kms(struct drm_device *dev, int crtc) { - /* FIXME: implement */ - return 0; + struct radeon_device *rdev = dev->dev_private; + + if (crtc < 0 || crtc > 1) { + DRM_ERROR("Invalid crtc %d\n", crtc); + return -EINVAL; + } + + rdev->irq.crtc_vblank_int[crtc] = true; + + return radeon_irq_set(rdev); } void radeon_disable_vblank_kms(struct drm_device *dev, int crtc) { - /* FIXME: implement */ + struct radeon_device *rdev = dev->dev_private; + + if (crtc < 0 || crtc > 1) { + DRM_ERROR("Invalid crtc %d\n", crtc); + return; + } + + rdev->irq.crtc_vblank_int[crtc] = false; + + radeon_irq_set(rdev); } @@ -295,5 +321,6 @@ struct drm_ioctl_desc radeon_ioctls_kms[] = { DRM_IOCTL_DEF(DRM_RADEON_INFO, radeon_info_ioctl, DRM_AUTH), DRM_IOCTL_DEF(DRM_RADEON_GEM_SET_TILING, radeon_gem_set_tiling_ioctl, DRM_AUTH), DRM_IOCTL_DEF(DRM_RADEON_GEM_GET_TILING, radeon_gem_get_tiling_ioctl, DRM_AUTH), + DRM_IOCTL_DEF(DRM_RADEON_GEM_BUSY, radeon_gem_busy_ioctl, DRM_AUTH), }; int radeon_max_kms_ioctl = DRM_ARRAY_SIZE(radeon_ioctls_kms); diff --git a/drivers/gpu/drm/radeon/radeon_legacy_crtc.c b/drivers/gpu/drm/radeon/radeon_legacy_crtc.c index 7d06dc9..0da72f1 100644 --- a/drivers/gpu/drm/radeon/radeon_legacy_crtc.c +++ b/drivers/gpu/drm/radeon/radeon_legacy_crtc.c @@ -310,10 +310,13 @@ void radeon_crtc_dpms(struct drm_crtc *crtc, int mode) RADEON_CRTC_DISP_REQ_EN_B)); WREG32_P(RADEON_CRTC_EXT_CNTL, 0, ~mask); } + drm_vblank_post_modeset(dev, radeon_crtc->crtc_id); + radeon_crtc_load_lut(crtc); break; case DRM_MODE_DPMS_STANDBY: case DRM_MODE_DPMS_SUSPEND: case DRM_MODE_DPMS_OFF: + drm_vblank_pre_modeset(dev, radeon_crtc->crtc_id); if (radeon_crtc->crtc_id) WREG32_P(RADEON_CRTC2_GEN_CNTL, mask, ~mask); else { @@ -323,10 +326,6 @@ void radeon_crtc_dpms(struct drm_crtc *crtc, int mode) } break; } - - if (mode != DRM_MODE_DPMS_OFF) { - radeon_crtc_load_lut(crtc); - } } /* properly set crtc bpp when using atombios */ diff --git a/drivers/gpu/drm/radeon/radeon_legacy_encoders.c b/drivers/gpu/drm/radeon/radeon_legacy_encoders.c index 34d0f58..9322675 100644 --- a/drivers/gpu/drm/radeon/radeon_legacy_encoders.c +++ b/drivers/gpu/drm/radeon/radeon_legacy_encoders.c @@ -1066,6 +1066,7 @@ radeon_add_legacy_encoder(struct drm_device *dev, uint32_t encoder_id, uint32_t switch (radeon_encoder->encoder_id) { case ENCODER_OBJECT_ID_INTERNAL_LVDS: + encoder->possible_crtcs = 0x1; drm_encoder_init(dev, encoder, &radeon_legacy_lvds_enc_funcs, DRM_MODE_ENCODER_LVDS); drm_encoder_helper_add(encoder, &radeon_legacy_lvds_helper_funcs); if (rdev->is_atom_bios) diff --git a/drivers/gpu/drm/radeon/radeon_object.c b/drivers/gpu/drm/radeon/radeon_object.c index e98cae3..b85fb83 100644 --- a/drivers/gpu/drm/radeon/radeon_object.c +++ b/drivers/gpu/drm/radeon/radeon_object.c @@ -316,6 +316,25 @@ int radeon_object_wait(struct radeon_object *robj) return r; } +int radeon_object_busy_domain(struct radeon_object *robj, uint32_t *cur_placement) +{ + int r = 0; + + r = radeon_object_reserve(robj, true); + if (unlikely(r != 0)) { + DRM_ERROR("radeon: failed to reserve object for waiting.\n"); + return r; + } + spin_lock(&robj->tobj.lock); + *cur_placement = robj->tobj.mem.mem_type; + if (robj->tobj.sync_obj) { + r = ttm_bo_wait(&robj->tobj, true, true, true); + } + spin_unlock(&robj->tobj.lock); + radeon_object_unreserve(robj); + return r; +} + int radeon_object_evict_vram(struct radeon_device *rdev) { if (rdev->flags & RADEON_IS_IGP) { diff --git a/drivers/gpu/drm/radeon/radeon_reg.h b/drivers/gpu/drm/radeon/radeon_reg.h index e1b6185..4df43f6 100644 --- a/drivers/gpu/drm/radeon/radeon_reg.h +++ b/drivers/gpu/drm/radeon/radeon_reg.h @@ -982,12 +982,15 @@ # define RS400_TMDS2_PLLRST (1 << 1) #define RADEON_GEN_INT_CNTL 0x0040 +# define RADEON_CRTC_VBLANK_MASK (1 << 0) +# define RADEON_CRTC2_VBLANK_MASK (1 << 9) # define RADEON_SW_INT_ENABLE (1 << 25) #define RADEON_GEN_INT_STATUS 0x0044 -# define RADEON_VSYNC_INT_AK (1 << 2) -# define RADEON_VSYNC_INT (1 << 2) -# define RADEON_VSYNC2_INT_AK (1 << 6) -# define RADEON_VSYNC2_INT (1 << 6) +# define AVIVO_DISPLAY_INT_STATUS (1 << 0) +# define RADEON_CRTC_VBLANK_STAT (1 << 0) +# define RADEON_CRTC_VBLANK_STAT_ACK (1 << 0) +# define RADEON_CRTC2_VBLANK_STAT (1 << 9) +# define RADEON_CRTC2_VBLANK_STAT_ACK (1 << 9) # define RADEON_SW_INT_FIRE (1 << 26) # define RADEON_SW_INT_TEST (1 << 25) # define RADEON_SW_INT_TEST_ACK (1 << 25) @@ -2334,6 +2337,9 @@ # define RADEON_RE_WIDTH_SHIFT 0 # define RADEON_RE_HEIGHT_SHIFT 16 +#define RADEON_RB3D_ZPASS_DATA 0x3290 +#define RADEON_RB3D_ZPASS_ADDR 0x3294 + #define RADEON_SE_CNTL 0x1c4c # define RADEON_FFACE_CULL_CW (0 << 0) # define RADEON_FFACE_CULL_CCW (1 << 0) @@ -3568,4 +3574,6 @@ #define RADEON_SCRATCH_REG4 0x15f0 #define RADEON_SCRATCH_REG5 0x15f4 +#define RV530_GB_PIPE_SELECT2 0x4124 + #endif diff --git a/drivers/gpu/drm/radeon/radeon_state.c b/drivers/gpu/drm/radeon/radeon_state.c index 46645f3..2882f40 100644 --- a/drivers/gpu/drm/radeon/radeon_state.c +++ b/drivers/gpu/drm/radeon/radeon_state.c @@ -3081,6 +3081,9 @@ static int radeon_cp_getparam(struct drm_device *dev, void *data, struct drm_fil case RADEON_PARAM_NUM_GB_PIPES: value = dev_priv->num_gb_pipes; break; + case RADEON_PARAM_NUM_Z_PIPES: + value = dev_priv->num_z_pipes; + break; default: DRM_DEBUG("Invalid parameter %d\n", param->param); return -EINVAL; diff --git a/drivers/gpu/drm/radeon/rs600.c b/drivers/gpu/drm/radeon/rs600.c index bbea6dee..7e8ce98 100644 --- a/drivers/gpu/drm/radeon/rs600.c +++ b/drivers/gpu/drm/radeon/rs600.c @@ -240,6 +240,88 @@ void rs600_mc_fini(struct radeon_device *rdev) /* + * Interrupts + */ +int rs600_irq_set(struct radeon_device *rdev) +{ + uint32_t tmp = 0; + uint32_t mode_int = 0; + + if (rdev->irq.sw_int) { + tmp |= RADEON_SW_INT_ENABLE; + } + if (rdev->irq.crtc_vblank_int[0]) { + tmp |= AVIVO_DISPLAY_INT_STATUS; + mode_int |= AVIVO_D1MODE_INT_MASK; + } + if (rdev->irq.crtc_vblank_int[1]) { + tmp |= AVIVO_DISPLAY_INT_STATUS; + mode_int |= AVIVO_D2MODE_INT_MASK; + } + WREG32(RADEON_GEN_INT_CNTL, tmp); + WREG32(AVIVO_DxMODE_INT_MASK, mode_int); + return 0; +} + +static inline uint32_t rs600_irq_ack(struct radeon_device *rdev, u32 *r500_disp_int) +{ + uint32_t irqs = RREG32(RADEON_GEN_INT_STATUS); + uint32_t irq_mask = RADEON_SW_INT_TEST; + + if (irqs & AVIVO_DISPLAY_INT_STATUS) { + *r500_disp_int = RREG32(AVIVO_DISP_INTERRUPT_STATUS); + if (*r500_disp_int & AVIVO_D1_VBLANK_INTERRUPT) { + WREG32(AVIVO_D1MODE_VBLANK_STATUS, AVIVO_VBLANK_ACK); + } + if (*r500_disp_int & AVIVO_D2_VBLANK_INTERRUPT) { + WREG32(AVIVO_D2MODE_VBLANK_STATUS, AVIVO_VBLANK_ACK); + } + } else { + *r500_disp_int = 0; + } + + if (irqs) { + WREG32(RADEON_GEN_INT_STATUS, irqs); + } + return irqs & irq_mask; +} + +int rs600_irq_process(struct radeon_device *rdev) +{ + uint32_t status; + uint32_t r500_disp_int; + + status = rs600_irq_ack(rdev, &r500_disp_int); + if (!status && !r500_disp_int) { + return IRQ_NONE; + } + while (status || r500_disp_int) { + /* SW interrupt */ + if (status & RADEON_SW_INT_TEST) { + radeon_fence_process(rdev); + } + /* Vertical blank interrupts */ + if (r500_disp_int & AVIVO_D1_VBLANK_INTERRUPT) { + drm_handle_vblank(rdev->ddev, 0); + } + if (r500_disp_int & AVIVO_D2_VBLANK_INTERRUPT) { + drm_handle_vblank(rdev->ddev, 1); + } + status = rs600_irq_ack(rdev, &r500_disp_int); + } + return IRQ_HANDLED; +} + +u32 rs600_get_vblank_counter(struct radeon_device *rdev, int crtc) +{ + if (crtc == 0) + return RREG32(AVIVO_D1CRTC_FRAME_COUNT); + else + return RREG32(AVIVO_D2CRTC_FRAME_COUNT); +} + + +/* * Global GPU functions */ void rs600_disable_vga(struct radeon_device *rdev) diff --git a/drivers/gpu/drm/radeon/rs690.c b/drivers/gpu/drm/radeon/rs690.c index 839595b..bc6b7c5 100644 --- a/drivers/gpu/drm/radeon/rs690.c +++ b/drivers/gpu/drm/radeon/rs690.c @@ -652,3 +652,68 @@ void rs690_mc_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v) WREG32(RS690_MC_DATA, v); WREG32(RS690_MC_INDEX, RS690_MC_INDEX_WR_ACK); } + +static const unsigned rs690_reg_safe_bm[219] = { + 0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF, + 0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF, + 0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF, + 0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF, + 0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF, + 0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF, + 0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF, + 0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF, + 0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF, + 0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF, + 0x17FF1FFF,0xFFFFFFFC,0xFFFFFFFF,0xFF30FFBF, + 0xFFFFFFF8,0xC3E6FFFF,0xFFFFF6DF,0xFFFFFFFF, + 0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF, + 0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF, + 0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFF03F, + 0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF, + 0xFFFFFFFF,0xFFFFEFCE,0xF00EBFFF,0x007C0000, + 0xF0000078,0xFF000009,0xFFFFFFFF,0xFFFFFFFF, + 0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF, + 0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF, + 0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF, + 0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF, + 0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF, + 0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF, + 0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF, + 0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF, + 0xFFFFF7FF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF, + 0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF, + 0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF, + 0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF, + 0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF, + 0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF, + 0xFFFFFC78,0xFFFFFFFF,0xFFFFFFFE,0xFFFFFFFF, + 0x38FF8F50,0xFFF88082,0xF000000C,0xFAE009FF, + 0x0000FFFF,0xFFFFFFFF,0xFFFFFFFF,0x00000000, + 0x00000000,0x0000C100,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0xFFFF0000,0xFFFFFFFF,0xFF80FFFF, + 0x00000000,0x00000000,0x00000000,0x00000000, + 0x0003FC01,0xFFFFFFF8,0xFE800B19,0xFFFFFFFF, + 0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF, + 0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF, + 0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF, + 0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF, + 0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF, + 0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF, + 0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF, + 0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF, + 0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF, + 0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF, + 0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF, + 0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF, + 0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF, + 0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF, + 0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF, +}; + +int rs690_init(struct radeon_device *rdev) +{ + rdev->config.r300.reg_safe_bm = rs690_reg_safe_bm; + rdev->config.r300.reg_safe_bm_size = ARRAY_SIZE(rs690_reg_safe_bm); + return 0; +} diff --git a/drivers/gpu/drm/radeon/rv515.c b/drivers/gpu/drm/radeon/rv515.c index fd8f3ca..31a7f66 100644 --- a/drivers/gpu/drm/radeon/rv515.c +++ b/drivers/gpu/drm/radeon/rv515.c @@ -400,25 +400,6 @@ void rv515_mc_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v) WREG32(MC_IND_INDEX, 0); } -uint32_t rv515_pcie_rreg(struct radeon_device *rdev, uint32_t reg) -{ - uint32_t r; - - WREG32(PCIE_INDEX, ((reg) & 0x7ff)); - (void)RREG32(PCIE_INDEX); - r = RREG32(PCIE_DATA); - return r; -} - -void rv515_pcie_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v) -{ - WREG32(PCIE_INDEX, ((reg) & 0x7ff)); - (void)RREG32(PCIE_INDEX); - WREG32(PCIE_DATA, (v)); - (void)RREG32(PCIE_DATA); -} - - /* * Debugfs info */ diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c index d258b02..827da08 100644 --- a/drivers/i2c/busses/i2c-omap.c +++ b/drivers/i2c/busses/i2c-omap.c @@ -674,7 +674,14 @@ omap_i2c_isr(int this_irq, void *dev_id) err = 0; complete: - omap_i2c_write_reg(dev, OMAP_I2C_STAT_REG, stat); + /* + * Ack the stat in one go, but [R/X]DR and [R/X]RDY should be + * acked after the data operation is complete. + * Ref: TRM SWPU114Q Figure 18-31 + */ + omap_i2c_write_reg(dev, OMAP_I2C_STAT_REG, stat & + ~(OMAP_I2C_STAT_RRDY | OMAP_I2C_STAT_RDR | + OMAP_I2C_STAT_XRDY | OMAP_I2C_STAT_XDR)); if (stat & OMAP_I2C_STAT_NACK) { err |= OMAP_I2C_STAT_NACK; @@ -687,6 +694,9 @@ complete: } if (stat & (OMAP_I2C_STAT_ARDY | OMAP_I2C_STAT_NACK | OMAP_I2C_STAT_AL)) { + omap_i2c_ack_stat(dev, stat & + (OMAP_I2C_STAT_RRDY | OMAP_I2C_STAT_RDR | + OMAP_I2C_STAT_XRDY | OMAP_I2C_STAT_XDR)); omap_i2c_complete_cmd(dev, err); return IRQ_HANDLED; } @@ -774,7 +784,7 @@ complete: * memory to the I2C interface. */ - if (cpu_is_omap34xx()) { + if (dev->rev <= OMAP_I2C_REV_ON_3430) { while (!(stat & OMAP_I2C_STAT_XUDF)) { if (stat & (OMAP_I2C_STAT_NACK | OMAP_I2C_STAT_AL)) { omap_i2c_ack_stat(dev, stat & (OMAP_I2C_STAT_XRDY | OMAP_I2C_STAT_XDR)); diff --git a/drivers/i2c/busses/i2c-stu300.c b/drivers/i2c/busses/i2c-stu300.c index 182e711..d2728a2 100644 --- a/drivers/i2c/busses/i2c-stu300.c +++ b/drivers/i2c/busses/i2c-stu300.c @@ -117,7 +117,8 @@ enum stu300_error { STU300_ERROR_NONE = 0, STU300_ERROR_ACKNOWLEDGE_FAILURE, STU300_ERROR_BUS_ERROR, - STU300_ERROR_ARBITRATION_LOST + STU300_ERROR_ARBITRATION_LOST, + STU300_ERROR_UNKNOWN }; /* timeout waiting for the controller to respond */ @@ -127,7 +128,7 @@ enum stu300_error { * The number of address send athemps tried before giving up. * If the first one failes it seems like 5 to 8 attempts are required. */ -#define NUM_ADDR_RESEND_ATTEMPTS 10 +#define NUM_ADDR_RESEND_ATTEMPTS 12 /* I2C clock speed, in Hz 0-400kHz*/ static unsigned int scl_frequency = 100000; @@ -149,6 +150,7 @@ module_param(scl_frequency, uint, 0644); * @msg_index: index of current message * @msg_len: length of current message */ + struct stu300_dev { struct platform_device *pdev; struct i2c_adapter adapter; @@ -188,6 +190,27 @@ static inline u32 stu300_r8(void __iomem *address) return readl(address) & 0x000000FFU; } +static void stu300_irq_enable(struct stu300_dev *dev) +{ + u32 val; + val = stu300_r8(dev->virtbase + I2C_CR); + val |= I2C_CR_INTERRUPT_ENABLE; + /* Twice paranoia (possible HW glitch) */ + stu300_wr8(val, dev->virtbase + I2C_CR); + stu300_wr8(val, dev->virtbase + I2C_CR); +} + +static void stu300_irq_disable(struct stu300_dev *dev) +{ + u32 val; + val = stu300_r8(dev->virtbase + I2C_CR); + val &= ~I2C_CR_INTERRUPT_ENABLE; + /* Twice paranoia (possible HW glitch) */ + stu300_wr8(val, dev->virtbase + I2C_CR); + stu300_wr8(val, dev->virtbase + I2C_CR); +} + + /* * Tells whether a certain event or events occurred in * response to a command. The events represent states in @@ -196,9 +219,10 @@ static inline u32 stu300_r8(void __iomem *address) * documentation and can only be treated as abstract state * machine states. * - * @ret 0 = event has not occurred, any other value means - * the event occurred. + * @ret 0 = event has not occurred or unknown error, any + * other value means the correct event occurred or an error. */ + static int stu300_event_occurred(struct stu300_dev *dev, enum stu300_event mr_event) { u32 status1; @@ -206,11 +230,28 @@ static int stu300_event_occurred(struct stu300_dev *dev, /* What event happened? */ status1 = stu300_r8(dev->virtbase + I2C_SR1); + if (!(status1 & I2C_SR1_EVF_IND)) /* No event at all */ return 0; + status2 = stu300_r8(dev->virtbase + I2C_SR2); + /* Block any multiple interrupts */ + stu300_irq_disable(dev); + + /* Check for errors first */ + if (status2 & I2C_SR2_AF_IND) { + dev->cmd_err = STU300_ERROR_ACKNOWLEDGE_FAILURE; + return 1; + } else if (status2 & I2C_SR2_BERR_IND) { + dev->cmd_err = STU300_ERROR_BUS_ERROR; + return 1; + } else if (status2 & I2C_SR2_ARLO_IND) { + dev->cmd_err = STU300_ERROR_ARBITRATION_LOST; + return 1; + } + switch (mr_event) { case STU300_EVENT_1: if (status1 & I2C_SR1_ADSL_IND) @@ -221,10 +262,6 @@ static int stu300_event_occurred(struct stu300_dev *dev, case STU300_EVENT_7: case STU300_EVENT_8: if (status1 & I2C_SR1_BTF_IND) { - if (status2 & I2C_SR2_AF_IND) - dev->cmd_err = STU300_ERROR_ACKNOWLEDGE_FAILURE; - else if (status2 & I2C_SR2_BERR_IND) - dev->cmd_err = STU300_ERROR_BUS_ERROR; return 1; } break; @@ -240,8 +277,6 @@ static int stu300_event_occurred(struct stu300_dev *dev, case STU300_EVENT_6: if (status2 & I2C_SR2_ENDAD_IND) { /* First check for any errors */ - if (status2 & I2C_SR2_AF_IND) - dev->cmd_err = STU300_ERROR_ACKNOWLEDGE_FAILURE; return 1; } break; @@ -252,8 +287,15 @@ static int stu300_event_occurred(struct stu300_dev *dev, default: break; } - if (status2 & I2C_SR2_ARLO_IND) - dev->cmd_err = STU300_ERROR_ARBITRATION_LOST; + /* If we get here, we're on thin ice. + * Here we are in a status where we have + * gotten a response that does not match + * what we requested. + */ + dev->cmd_err = STU300_ERROR_UNKNOWN; + dev_err(&dev->pdev->dev, + "Unhandled interrupt! %d sr1: 0x%x sr2: 0x%x\n", + mr_event, status1, status2); return 0; } @@ -262,21 +304,20 @@ static irqreturn_t stu300_irh(int irq, void *data) struct stu300_dev *dev = data; int res; + /* Just make sure that the block is clocked */ + clk_enable(dev->clk); + /* See if this was what we were waiting for */ spin_lock(&dev->cmd_issue_lock); - if (dev->cmd_event != STU300_EVENT_NONE) { - res = stu300_event_occurred(dev, dev->cmd_event); - if (res || dev->cmd_err != STU300_ERROR_NONE) { - u32 val; - - complete(&dev->cmd_complete); - /* Block any multiple interrupts */ - val = stu300_r8(dev->virtbase + I2C_CR); - val &= ~I2C_CR_INTERRUPT_ENABLE; - stu300_wr8(val, dev->virtbase + I2C_CR); - } - } + + res = stu300_event_occurred(dev, dev->cmd_event); + if (res || dev->cmd_err != STU300_ERROR_NONE) + complete(&dev->cmd_complete); + spin_unlock(&dev->cmd_issue_lock); + + clk_disable(dev->clk); + return IRQ_HANDLED; } @@ -308,7 +349,6 @@ static int stu300_start_and_await_event(struct stu300_dev *dev, stu300_wr8(cr_value, dev->virtbase + I2C_CR); ret = wait_for_completion_interruptible_timeout(&dev->cmd_complete, STU300_TIMEOUT); - if (ret < 0) { dev_err(&dev->pdev->dev, "wait_for_completion_interruptible_timeout() " @@ -342,7 +382,6 @@ static int stu300_await_event(struct stu300_dev *dev, enum stu300_event mr_event) { int ret; - u32 val; if (unlikely(irqs_disabled())) { /* TODO: implement polling for this case if need be. */ @@ -354,36 +393,18 @@ static int stu300_await_event(struct stu300_dev *dev, /* Is it already here? */ spin_lock_irq(&dev->cmd_issue_lock); dev->cmd_err = STU300_ERROR_NONE; - if (stu300_event_occurred(dev, mr_event)) { - spin_unlock_irq(&dev->cmd_issue_lock); - goto exit_await_check_err; - } - init_completion(&dev->cmd_complete); - dev->cmd_err = STU300_ERROR_NONE; dev->cmd_event = mr_event; - /* Turn on the I2C interrupt for current operation */ - val = stu300_r8(dev->virtbase + I2C_CR); - val |= I2C_CR_INTERRUPT_ENABLE; - stu300_wr8(val, dev->virtbase + I2C_CR); - - /* Twice paranoia (possible HW glitch) */ - stu300_wr8(val, dev->virtbase + I2C_CR); + init_completion(&dev->cmd_complete); - /* Check again: is it already here? */ - if (unlikely(stu300_event_occurred(dev, mr_event))) { - /* Disable IRQ again. */ - val &= ~I2C_CR_INTERRUPT_ENABLE; - stu300_wr8(val, dev->virtbase + I2C_CR); - spin_unlock_irq(&dev->cmd_issue_lock); - goto exit_await_check_err; - } + /* Turn on the I2C interrupt for current operation */ + stu300_irq_enable(dev); /* Unlock the command block and wait for the event to occur */ spin_unlock_irq(&dev->cmd_issue_lock); + ret = wait_for_completion_interruptible_timeout(&dev->cmd_complete, STU300_TIMEOUT); - if (ret < 0) { dev_err(&dev->pdev->dev, "wait_for_completion_interruptible_timeout()" @@ -401,7 +422,6 @@ static int stu300_await_event(struct stu300_dev *dev, return -ETIMEDOUT; } - exit_await_check_err: if (dev->cmd_err != STU300_ERROR_NONE) { if (mr_event != STU300_EVENT_6) { dev_err(&dev->pdev->dev, "controller " @@ -457,18 +477,19 @@ struct stu300_clkset { }; static const struct stu300_clkset stu300_clktable[] = { - { 0, 0xFFU }, - { 2500000, I2C_OAR2_FR_25_10MHZ }, - { 10000000, I2C_OAR2_FR_10_1667MHZ }, - { 16670000, I2C_OAR2_FR_1667_2667MHZ }, - { 26670000, I2C_OAR2_FR_2667_40MHZ }, - { 40000000, I2C_OAR2_FR_40_5333MHZ }, - { 53330000, I2C_OAR2_FR_5333_66MHZ }, - { 66000000, I2C_OAR2_FR_66_80MHZ }, - { 80000000, I2C_OAR2_FR_80_100MHZ }, + { 0, 0xFFU }, + { 2500000, I2C_OAR2_FR_25_10MHZ }, + { 10000000, I2C_OAR2_FR_10_1667MHZ }, + { 16670000, I2C_OAR2_FR_1667_2667MHZ }, + { 26670000, I2C_OAR2_FR_2667_40MHZ }, + { 40000000, I2C_OAR2_FR_40_5333MHZ }, + { 53330000, I2C_OAR2_FR_5333_66MHZ }, + { 66000000, I2C_OAR2_FR_66_80MHZ }, + { 80000000, I2C_OAR2_FR_80_100MHZ }, { 100000000, 0xFFU }, }; + static int stu300_set_clk(struct stu300_dev *dev, unsigned long clkrate) { @@ -494,10 +515,10 @@ static int stu300_set_clk(struct stu300_dev *dev, unsigned long clkrate) if (dev->speed > 100000) /* Fast Mode I2C */ - val = ((clkrate/dev->speed)-9)/3; + val = ((clkrate/dev->speed) - 9)/3 + 1; else /* Standard Mode I2C */ - val = ((clkrate/dev->speed)-7)/2; + val = ((clkrate/dev->speed) - 7)/2 + 1; /* According to spec the divider must be > 2 */ if (val < 0x002) { @@ -557,6 +578,7 @@ static int stu300_init_hw(struct stu300_dev *dev) */ clkrate = clk_get_rate(dev->clk); ret = stu300_set_clk(dev, clkrate); + if (ret) return ret; /* @@ -641,7 +663,6 @@ static int stu300_xfer_msg(struct i2c_adapter *adap, int attempts = 0; struct stu300_dev *dev = i2c_get_adapdata(adap); - clk_enable(dev->clk); /* Remove this if (0) to trace each and every message. */ @@ -715,14 +736,15 @@ static int stu300_xfer_msg(struct i2c_adapter *adap, if (attempts < NUM_ADDR_RESEND_ATTEMPTS && attempts > 0) { dev_dbg(&dev->pdev->dev, "managed to get address " - "through after %d attempts\n", attempts); + "through after %d attempts\n", attempts); } else if (attempts == NUM_ADDR_RESEND_ATTEMPTS) { dev_dbg(&dev->pdev->dev, "I give up, tried %d times " - "to resend address.\n", - NUM_ADDR_RESEND_ATTEMPTS); + "to resend address.\n", + NUM_ADDR_RESEND_ATTEMPTS); goto exit_disable; } + if (msg->flags & I2C_M_RD) { /* READ: we read the actual bytes one at a time */ for (i = 0; i < msg->len; i++) { @@ -804,8 +826,10 @@ static int stu300_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, { int ret = -1; int i; + struct stu300_dev *dev = i2c_get_adapdata(adap); dev->msg_len = num; + for (i = 0; i < num; i++) { /* * Another driver appears to send stop for each message, @@ -817,6 +841,7 @@ static int stu300_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, dev->msg_index = i; ret = stu300_xfer_msg(adap, &msgs[i], (i == (num - 1))); + if (ret != 0) { num = ret; break; @@ -845,6 +870,7 @@ stu300_probe(struct platform_device *pdev) struct resource *res; int bus_nr; int ret = 0; + char clk_name[] = "I2C0"; dev = kzalloc(sizeof(struct stu300_dev), GFP_KERNEL); if (!dev) { @@ -854,7 +880,8 @@ stu300_probe(struct platform_device *pdev) } bus_nr = pdev->id; - dev->clk = clk_get(&pdev->dev, NULL); + clk_name[3] += (char)bus_nr; + dev->clk = clk_get(&pdev->dev, clk_name); if (IS_ERR(dev->clk)) { ret = PTR_ERR(dev->clk); dev_err(&pdev->dev, "could not retrieve i2c bus clock\n"); diff --git a/drivers/input/joydev.c b/drivers/input/joydev.c index 4cfd084f..9a1d55b 100644 --- a/drivers/input/joydev.c +++ b/drivers/input/joydev.c @@ -456,8 +456,11 @@ static int joydev_ioctl_common(struct joydev *joydev, unsigned int cmd, void __user *argp) { struct input_dev *dev = joydev->handle.dev; + size_t len; int i, j; + const char *name; + /* Process fixed-sized commands. */ switch (cmd) { case JS_SET_CAL: @@ -499,9 +502,22 @@ static int joydev_ioctl_common(struct joydev *joydev, return copy_to_user(argp, joydev->corr, sizeof(joydev->corr[0]) * joydev->nabs) ? -EFAULT : 0; - case JSIOCSAXMAP: - if (copy_from_user(joydev->abspam, argp, - sizeof(__u8) * (ABS_MAX + 1))) + } + + /* + * Process variable-sized commands (the axis and button map commands + * are considered variable-sized to decouple them from the values of + * ABS_MAX and KEY_MAX). + */ + switch (cmd & ~IOCSIZE_MASK) { + + case (JSIOCSAXMAP & ~IOCSIZE_MASK): + len = min_t(size_t, _IOC_SIZE(cmd), sizeof(joydev->abspam)); + /* + * FIXME: we should not copy into our axis map before + * validating the data. + */ + if (copy_from_user(joydev->abspam, argp, len)) return -EFAULT; for (i = 0; i < joydev->nabs; i++) { @@ -511,13 +527,17 @@ static int joydev_ioctl_common(struct joydev *joydev, } return 0; - case JSIOCGAXMAP: - return copy_to_user(argp, joydev->abspam, - sizeof(__u8) * (ABS_MAX + 1)) ? -EFAULT : 0; - - case JSIOCSBTNMAP: - if (copy_from_user(joydev->keypam, argp, - sizeof(__u16) * (KEY_MAX - BTN_MISC + 1))) + case (JSIOCGAXMAP & ~IOCSIZE_MASK): + len = min_t(size_t, _IOC_SIZE(cmd), sizeof(joydev->abspam)); + return copy_to_user(argp, joydev->abspam, len) ? -EFAULT : 0; + + case (JSIOCSBTNMAP & ~IOCSIZE_MASK): + len = min_t(size_t, _IOC_SIZE(cmd), sizeof(joydev->keypam)); + /* + * FIXME: we should not copy into our keymap before + * validating the data. + */ + if (copy_from_user(joydev->keypam, argp, len)) return -EFAULT; for (i = 0; i < joydev->nkey; i++) { @@ -529,25 +549,19 @@ static int joydev_ioctl_common(struct joydev *joydev, return 0; - case JSIOCGBTNMAP: - return copy_to_user(argp, joydev->keypam, - sizeof(__u16) * (KEY_MAX - BTN_MISC + 1)) ? -EFAULT : 0; + case (JSIOCGBTNMAP & ~IOCSIZE_MASK): + len = min_t(size_t, _IOC_SIZE(cmd), sizeof(joydev->keypam)); + return copy_to_user(argp, joydev->keypam, len) ? -EFAULT : 0; - default: - if ((cmd & ~IOCSIZE_MASK) == JSIOCGNAME(0)) { - int len; - const char *name = dev->name; - - if (!name) - return 0; - len = strlen(name) + 1; - if (len > _IOC_SIZE(cmd)) - len = _IOC_SIZE(cmd); - if (copy_to_user(argp, name, len)) - return -EFAULT; - return len; - } + case JSIOCGNAME(0): + name = dev->name; + if (!name) + return 0; + + len = min_t(size_t, _IOC_SIZE(cmd), strlen(name) + 1); + return copy_to_user(argp, name, len) ? -EFAULT : len; } + return -EINVAL; } diff --git a/drivers/input/joystick/iforce/iforce-main.c b/drivers/input/joystick/iforce/iforce-main.c index baabf83..f6c688c 100644 --- a/drivers/input/joystick/iforce/iforce-main.c +++ b/drivers/input/joystick/iforce/iforce-main.c @@ -74,6 +74,7 @@ static struct iforce_device iforce_device[] = { { 0x05ef, 0x8884, "AVB Mag Turbo Force", btn_avb_wheel, abs_wheel, ff_iforce }, { 0x05ef, 0x8888, "AVB Top Shot Force Feedback Racing Wheel", btn_avb_tw, abs_wheel, ff_iforce }, //? { 0x061c, 0xc0a4, "ACT LABS Force RS", btn_wheel, abs_wheel, ff_iforce }, //? + { 0x061c, 0xc084, "ACT LABS Force RS", btn_wheel, abs_wheel, ff_iforce }, { 0x06f8, 0x0001, "Guillemot Race Leader Force Feedback", btn_wheel, abs_wheel, ff_iforce }, //? { 0x06f8, 0x0004, "Guillemot Force Feedback Racing Wheel", btn_wheel, abs_wheel, ff_iforce }, //? { 0x06f8, 0x0004, "Gullemot Jet Leader 3D", btn_joystick, abs_joystick, ff_iforce }, //? diff --git a/drivers/input/joystick/iforce/iforce-usb.c b/drivers/input/joystick/iforce/iforce-usb.c index f83185a..9f289d8 100644 --- a/drivers/input/joystick/iforce/iforce-usb.c +++ b/drivers/input/joystick/iforce/iforce-usb.c @@ -223,6 +223,7 @@ static struct usb_device_id iforce_usb_ids [] = { { USB_DEVICE(0x05ef, 0x8884) }, /* AVB Mag Turbo Force */ { USB_DEVICE(0x05ef, 0x8888) }, /* AVB Top Shot FFB Racing Wheel */ { USB_DEVICE(0x061c, 0xc0a4) }, /* ACT LABS Force RS */ + { USB_DEVICE(0x061c, 0xc084) }, /* ACT LABS Force RS */ { USB_DEVICE(0x06f8, 0x0001) }, /* Guillemot Race Leader Force Feedback */ { USB_DEVICE(0x06f8, 0x0004) }, /* Guillemot Force Feedback Racing Wheel */ { USB_DEVICE(0x06f8, 0xa302) }, /* Guillemot Jet Leader 3D */ diff --git a/drivers/input/tablet/wacom_sys.c b/drivers/input/tablet/wacom_sys.c index a9d5031..ea30c98 100644 --- a/drivers/input/tablet/wacom_sys.c +++ b/drivers/input/tablet/wacom_sys.c @@ -388,6 +388,32 @@ static int wacom_parse_hid(struct usb_interface *intf, struct hid_descriptor *hi return result; } +static int wacom_query_tablet_data(struct usb_interface *intf) +{ + unsigned char *rep_data; + int limit = 0; + int error; + + rep_data = kmalloc(2, GFP_KERNEL); + if (!rep_data) + return -ENOMEM; + + do { + rep_data[0] = 2; + rep_data[1] = 2; + error = usb_set_report(intf, WAC_HID_FEATURE_REPORT, + 2, rep_data, 2); + if (error >= 0) + error = usb_get_report(intf, + WAC_HID_FEATURE_REPORT, 2, + rep_data, 2); + } while ((error < 0 || rep_data[1] != 2) && limit++ < 5); + + kfree(rep_data); + + return error < 0 ? error : 0; +} + static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *id) { struct usb_device *dev = interface_to_usbdev(intf); @@ -398,7 +424,6 @@ static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *i struct wacom_features *features; struct input_dev *input_dev; int error = -ENOMEM; - char rep_data[2], limit = 0; struct hid_descriptor *hid_desc; wacom = kzalloc(sizeof(struct wacom), GFP_KERNEL); @@ -489,20 +514,10 @@ static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *i /* * Ask the tablet to report tablet data if it is not a Tablet PC. - * Repeat until it succeeds + * Note that if query fails it is not a hard failure. */ - if (wacom_wac->features->type != TABLETPC) { - do { - rep_data[0] = 2; - rep_data[1] = 2; - error = usb_set_report(intf, WAC_HID_FEATURE_REPORT, - 2, rep_data, 2); - if (error >= 0) - error = usb_get_report(intf, - WAC_HID_FEATURE_REPORT, 2, - rep_data, 2); - } while ((error < 0 || rep_data[1] != 2) && limit++ < 5); - } + if (wacom_wac->features->type != TABLETPC) + wacom_query_tablet_data(intf); usb_set_intfdata(intf, wacom); return 0; diff --git a/drivers/input/touchscreen/ucb1400_ts.c b/drivers/input/touchscreen/ucb1400_ts.c index 6954f55..3a7a582 100644 --- a/drivers/input/touchscreen/ucb1400_ts.c +++ b/drivers/input/touchscreen/ucb1400_ts.c @@ -170,11 +170,11 @@ static void ucb1400_handle_pending_irq(struct ucb1400_ts *ucb) ucb1400_reg_write(ucb->ac97, UCB_IE_CLEAR, isr); ucb1400_reg_write(ucb->ac97, UCB_IE_CLEAR, 0); - if (isr & UCB_IE_TSPX) { + if (isr & UCB_IE_TSPX) ucb1400_ts_irq_disable(ucb->ac97); - enable_irq(ucb->irq); - } else - printk(KERN_ERR "ucb1400: unexpected IE_STATUS = %#x\n", isr); + else + dev_dbg(&ucb->ts_idev->dev, "ucb1400: unexpected IE_STATUS = %#x\n", isr); + enable_irq(ucb->irq); } static int ucb1400_ts_thread(void *_ucb) @@ -345,6 +345,7 @@ static int ucb1400_ts_detect_irq(struct ucb1400_ts *ucb) static int ucb1400_ts_probe(struct platform_device *dev) { int error, x_res, y_res; + u16 fcsr; struct ucb1400_ts *ucb = dev->dev.platform_data; ucb->ts_idev = input_allocate_device(); @@ -382,6 +383,14 @@ static int ucb1400_ts_probe(struct platform_device *dev) ucb->ts_idev->evbit[0] = BIT_MASK(EV_ABS) | BIT_MASK(EV_KEY); ucb->ts_idev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH); + /* + * Enable ADC filter to prevent horrible jitter on Colibri. + * This also further reduces jitter on boards where ADCSYNC + * pin is connected. + */ + fcsr = ucb1400_reg_read(ucb->ac97, UCB_FCSR); + ucb1400_reg_write(ucb->ac97, UCB_FCSR, fcsr | UCB_FCSR_AVE); + ucb1400_adc_enable(ucb->ac97); x_res = ucb1400_ts_read_xres(ucb); y_res = ucb1400_ts_read_yres(ucb); diff --git a/drivers/md/dm-log-userspace-transfer.c b/drivers/md/dm-log-userspace-transfer.c index 0ca1ee7..8ce74d9 100644 --- a/drivers/md/dm-log-userspace-transfer.c +++ b/drivers/md/dm-log-userspace-transfer.c @@ -108,7 +108,7 @@ static int fill_pkg(struct cn_msg *msg, struct dm_ulog_request *tfr) *(pkg->data_size) = 0; } else if (tfr->data_size > *(pkg->data_size)) { DMERR("Insufficient space to receive package [%u] " - "(%u vs %lu)", tfr->request_type, + "(%u vs %zu)", tfr->request_type, tfr->data_size, *(pkg->data_size)); *(pkg->data_size) = 0; diff --git a/drivers/md/md.c b/drivers/md/md.c index 103f2d3..9dd8720 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -4364,6 +4364,7 @@ static int do_md_stop(mddev_t * mddev, int mode, int is_open) if (mode == 1) set_disk_ro(disk, 1); clear_bit(MD_RECOVERY_FROZEN, &mddev->recovery); + err = 0; } out: mutex_unlock(&mddev->open_mutex); diff --git a/drivers/mtd/nand/orion_nand.c b/drivers/mtd/nand/orion_nand.c index 7ad9722..0d9d4bc 100644 --- a/drivers/mtd/nand/orion_nand.c +++ b/drivers/mtd/nand/orion_nand.c @@ -61,7 +61,7 @@ static void orion_nand_read_buf(struct mtd_info *mtd, uint8_t *buf, int len) buf64 = (uint64_t *)buf; while (i < len/8) { uint64_t x; - asm ("ldrd\t%0, [%1]" : "=r" (x) : "r" (io_base)); + asm volatile ("ldrd\t%0, [%1]" : "=&r" (x) : "r" (io_base)); buf64[i++] = x; } i *= 8; diff --git a/drivers/net/3c59x.c b/drivers/net/3c59x.c index c204168..4567588 100644 --- a/drivers/net/3c59x.c +++ b/drivers/net/3c59x.c @@ -235,6 +235,7 @@ enum vortex_chips { CH_3C900B_FL, CH_3C905_1, CH_3C905_2, + CH_3C905B_TX, CH_3C905B_1, CH_3C905B_2, @@ -307,6 +308,8 @@ static struct vortex_chip_info { PCI_USES_MASTER, IS_BOOMERANG|HAS_MII|EEPROM_RESET, 64, }, {"3c905 Boomerang 100baseT4", PCI_USES_MASTER, IS_BOOMERANG|HAS_MII|EEPROM_RESET, 64, }, + {"3C905B-TX Fast Etherlink XL PCI", + PCI_USES_MASTER, IS_CYCLONE|HAS_NWAY|HAS_HWCKSM|EXTRA_PREAMBLE, 128, }, {"3c905B Cyclone 100baseTx", PCI_USES_MASTER, IS_CYCLONE|HAS_NWAY|HAS_HWCKSM|EXTRA_PREAMBLE, 128, }, @@ -389,6 +392,7 @@ static struct pci_device_id vortex_pci_tbl[] = { { 0x10B7, 0x900A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3C900B_FL }, { 0x10B7, 0x9050, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3C905_1 }, { 0x10B7, 0x9051, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3C905_2 }, + { 0x10B7, 0x9054, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3C905B_TX }, { 0x10B7, 0x9055, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3C905B_1 }, { 0x10B7, 0x9058, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3C905B_2 }, diff --git a/drivers/net/8139cp.c b/drivers/net/8139cp.c index 50efde1..d0dbbf3 100644 --- a/drivers/net/8139cp.c +++ b/drivers/net/8139cp.c @@ -515,7 +515,7 @@ rx_status_loop: dma_addr_t mapping; struct sk_buff *skb, *new_skb; struct cp_desc *desc; - unsigned buflen; + const unsigned buflen = cp->rx_buf_sz; skb = cp->rx_skb[rx_tail]; BUG_ON(!skb); @@ -549,8 +549,7 @@ rx_status_loop: pr_debug("%s: rx slot %d status 0x%x len %d\n", dev->name, rx_tail, status, len); - buflen = cp->rx_buf_sz + NET_IP_ALIGN; - new_skb = netdev_alloc_skb(dev, buflen); + new_skb = netdev_alloc_skb(dev, buflen + NET_IP_ALIGN); if (!new_skb) { dev->stats.rx_dropped++; goto rx_next; diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index 5f6509a..5ce7cba 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -1727,12 +1727,14 @@ config KS8842 tristate "Micrel KSZ8842" depends on HAS_IOMEM help - This platform driver is for Micrel KSZ8842 chip. + This platform driver is for Micrel KSZ8842 / KS8842 + 2-port ethernet switch chip (managed, VLAN, QoS). config KS8851 tristate "Micrel KS8851 SPI" depends on SPI select MII + select CRC32 help SPI driver for Micrel KS8851 SPI attached network chip. diff --git a/drivers/net/arm/w90p910_ether.c b/drivers/net/arm/w90p910_ether.c index 616fb79..ddd231c 100644 --- a/drivers/net/arm/w90p910_ether.c +++ b/drivers/net/arm/w90p910_ether.c @@ -1080,7 +1080,7 @@ static struct platform_driver w90p910_ether_driver = { .probe = w90p910_ether_probe, .remove = __devexit_p(w90p910_ether_remove), .driver = { - .name = "w90p910-emc", + .name = "nuc900-emc", .owner = THIS_MODULE, }, }; @@ -1101,5 +1101,5 @@ module_exit(w90p910_ether_exit); MODULE_AUTHOR("Wan ZongShun <mcuos.com@gmail.com>"); MODULE_DESCRIPTION("w90p910 MAC driver!"); MODULE_LICENSE("GPL"); -MODULE_ALIAS("platform:w90p910-emc"); +MODULE_ALIAS("platform:nuc900-emc"); diff --git a/drivers/net/atl1c/atl1c_ethtool.c b/drivers/net/atl1c/atl1c_ethtool.c index 607007d..00d11b4 100644 --- a/drivers/net/atl1c/atl1c_ethtool.c +++ b/drivers/net/atl1c/atl1c_ethtool.c @@ -232,11 +232,11 @@ static void atl1c_get_drvinfo(struct net_device *netdev, { struct atl1c_adapter *adapter = netdev_priv(netdev); - strncpy(drvinfo->driver, atl1c_driver_name, sizeof(drvinfo->driver)); - strncpy(drvinfo->version, atl1c_driver_version, + strlcpy(drvinfo->driver, atl1c_driver_name, sizeof(drvinfo->driver)); + strlcpy(drvinfo->version, atl1c_driver_version, sizeof(drvinfo->version)); - strncpy(drvinfo->fw_version, "N/A", sizeof(drvinfo->fw_version)); - strncpy(drvinfo->bus_info, pci_name(adapter->pdev), + strlcpy(drvinfo->fw_version, "N/A", sizeof(drvinfo->fw_version)); + strlcpy(drvinfo->bus_info, pci_name(adapter->pdev), sizeof(drvinfo->bus_info)); drvinfo->n_stats = 0; drvinfo->testinfo_len = 0; diff --git a/drivers/net/atlx/atl1.c b/drivers/net/atlx/atl1.c index 94d7325..8bca12f 100644 --- a/drivers/net/atlx/atl1.c +++ b/drivers/net/atlx/atl1.c @@ -3378,11 +3378,11 @@ static void atl1_get_drvinfo(struct net_device *netdev, { struct atl1_adapter *adapter = netdev_priv(netdev); - strncpy(drvinfo->driver, ATLX_DRIVER_NAME, sizeof(drvinfo->driver)); - strncpy(drvinfo->version, ATLX_DRIVER_VERSION, + strlcpy(drvinfo->driver, ATLX_DRIVER_NAME, sizeof(drvinfo->driver)); + strlcpy(drvinfo->version, ATLX_DRIVER_VERSION, sizeof(drvinfo->version)); - strncpy(drvinfo->fw_version, "N/A", sizeof(drvinfo->fw_version)); - strncpy(drvinfo->bus_info, pci_name(adapter->pdev), + strlcpy(drvinfo->fw_version, "N/A", sizeof(drvinfo->fw_version)); + strlcpy(drvinfo->bus_info, pci_name(adapter->pdev), sizeof(drvinfo->bus_info)); drvinfo->eedump_len = ATL1_EEDUMP_LEN; } diff --git a/drivers/net/b44.c b/drivers/net/b44.c index 36d4d37..bafca67 100644 --- a/drivers/net/b44.c +++ b/drivers/net/b44.c @@ -952,9 +952,10 @@ static int b44_start_xmit(struct sk_buff *skb, struct net_device *dev) int rc = NETDEV_TX_OK; dma_addr_t mapping; u32 len, entry, ctrl; + unsigned long flags; len = skb->len; - spin_lock_irq(&bp->lock); + spin_lock_irqsave(&bp->lock, flags); /* This is a hard error, log it. */ if (unlikely(TX_BUFFS_AVAIL(bp) < 1)) { @@ -1027,7 +1028,7 @@ static int b44_start_xmit(struct sk_buff *skb, struct net_device *dev) dev->trans_start = jiffies; out_unlock: - spin_unlock_irq(&bp->lock); + spin_unlock_irqrestore(&bp->lock, flags); return rc; diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c index b70cc99..06b9011 100644 --- a/drivers/net/bnx2.c +++ b/drivers/net/bnx2.c @@ -399,9 +399,11 @@ static int bnx2_unregister_cnic(struct net_device *dev) struct bnx2_napi *bnapi = &bp->bnx2_napi[0]; struct cnic_eth_dev *cp = &bp->cnic_eth_dev; + mutex_lock(&bp->cnic_lock); cp->drv_state = 0; bnapi->cnic_present = 0; rcu_assign_pointer(bp->cnic_ops, NULL); + mutex_unlock(&bp->cnic_lock); synchronize_rcu(); return 0; } @@ -429,13 +431,13 @@ bnx2_cnic_stop(struct bnx2 *bp) struct cnic_ops *c_ops; struct cnic_ctl_info info; - rcu_read_lock(); - c_ops = rcu_dereference(bp->cnic_ops); + mutex_lock(&bp->cnic_lock); + c_ops = bp->cnic_ops; if (c_ops) { info.cmd = CNIC_CTL_STOP_CMD; c_ops->cnic_ctl(bp->cnic_data, &info); } - rcu_read_unlock(); + mutex_unlock(&bp->cnic_lock); } static void @@ -444,8 +446,8 @@ bnx2_cnic_start(struct bnx2 *bp) struct cnic_ops *c_ops; struct cnic_ctl_info info; - rcu_read_lock(); - c_ops = rcu_dereference(bp->cnic_ops); + mutex_lock(&bp->cnic_lock); + c_ops = bp->cnic_ops; if (c_ops) { if (!(bp->flags & BNX2_FLAG_USING_MSIX)) { struct bnx2_napi *bnapi = &bp->bnx2_napi[0]; @@ -455,7 +457,7 @@ bnx2_cnic_start(struct bnx2 *bp) info.cmd = CNIC_CTL_START_CMD; c_ops->cnic_ctl(bp->cnic_data, &info); } - rcu_read_unlock(); + mutex_unlock(&bp->cnic_lock); } #else @@ -7663,6 +7665,9 @@ bnx2_init_board(struct pci_dev *pdev, struct net_device *dev) spin_lock_init(&bp->phy_lock); spin_lock_init(&bp->indirect_lock); +#ifdef BCM_CNIC + mutex_init(&bp->cnic_lock); +#endif INIT_WORK(&bp->reset_task, bnx2_reset_task); dev->base_addr = dev->mem_start = pci_resource_start(pdev, 0); diff --git a/drivers/net/bnx2.h b/drivers/net/bnx2.h index f1edfaa..a4f12fd 100644 --- a/drivers/net/bnx2.h +++ b/drivers/net/bnx2.h @@ -6902,6 +6902,7 @@ struct bnx2 { u32 idle_chk_status_idx; #ifdef BCM_CNIC + struct mutex cnic_lock; struct cnic_eth_dev cnic_eth_dev; #endif diff --git a/drivers/net/can/dev.c b/drivers/net/can/dev.c index 9e4283a..e1a4f82 100644 --- a/drivers/net/can/dev.c +++ b/drivers/net/can/dev.c @@ -611,11 +611,18 @@ nla_put_failure: return -EMSGSIZE; } +static int can_newlink(struct net_device *dev, + struct nlattr *tb[], struct nlattr *data[]) +{ + return -EOPNOTSUPP; +} + static struct rtnl_link_ops can_link_ops __read_mostly = { .kind = "can", .maxtype = IFLA_CAN_MAX, .policy = can_policy, .setup = can_setup, + .newlink = can_newlink, .changelink = can_changelink, .fill_info = can_fill_info, .fill_xstats = can_fill_xstats, diff --git a/drivers/net/cnic.c b/drivers/net/cnic.c index 4869d77..74c3429 100644 --- a/drivers/net/cnic.c +++ b/drivers/net/cnic.c @@ -138,6 +138,16 @@ static struct cnic_dev *cnic_from_netdev(struct net_device *netdev) return NULL; } +static inline void ulp_get(struct cnic_ulp_ops *ulp_ops) +{ + atomic_inc(&ulp_ops->ref_count); +} + +static inline void ulp_put(struct cnic_ulp_ops *ulp_ops) +{ + atomic_dec(&ulp_ops->ref_count); +} + static void cnic_ctx_wr(struct cnic_dev *dev, u32 cid_addr, u32 off, u32 val) { struct cnic_local *cp = dev->cnic_priv; @@ -358,6 +368,7 @@ int cnic_register_driver(int ulp_type, struct cnic_ulp_ops *ulp_ops) } read_unlock(&cnic_dev_lock); + atomic_set(&ulp_ops->ref_count, 0); rcu_assign_pointer(cnic_ulp_tbl[ulp_type], ulp_ops); mutex_unlock(&cnic_lock); @@ -379,6 +390,8 @@ int cnic_register_driver(int ulp_type, struct cnic_ulp_ops *ulp_ops) int cnic_unregister_driver(int ulp_type) { struct cnic_dev *dev; + struct cnic_ulp_ops *ulp_ops; + int i = 0; if (ulp_type >= MAX_CNIC_ULP_TYPE) { printk(KERN_ERR PFX "cnic_unregister_driver: Bad type %d\n", @@ -386,7 +399,8 @@ int cnic_unregister_driver(int ulp_type) return -EINVAL; } mutex_lock(&cnic_lock); - if (!cnic_ulp_tbl[ulp_type]) { + ulp_ops = cnic_ulp_tbl[ulp_type]; + if (!ulp_ops) { printk(KERN_ERR PFX "cnic_unregister_driver: Type %d has not " "been registered\n", ulp_type); goto out_unlock; @@ -411,6 +425,14 @@ int cnic_unregister_driver(int ulp_type) mutex_unlock(&cnic_lock); synchronize_rcu(); + while ((atomic_read(&ulp_ops->ref_count) != 0) && (i < 20)) { + msleep(100); + i++; + } + + if (atomic_read(&ulp_ops->ref_count) != 0) + printk(KERN_WARNING PFX "%s: Failed waiting for ref count to go" + " to zero.\n", dev->netdev->name); return 0; out_unlock: @@ -466,6 +488,7 @@ EXPORT_SYMBOL(cnic_register_driver); static int cnic_unregister_device(struct cnic_dev *dev, int ulp_type) { struct cnic_local *cp = dev->cnic_priv; + int i = 0; if (ulp_type >= MAX_CNIC_ULP_TYPE) { printk(KERN_ERR PFX "cnic_unregister_device: Bad type %d\n", @@ -486,6 +509,15 @@ static int cnic_unregister_device(struct cnic_dev *dev, int ulp_type) synchronize_rcu(); + while (test_bit(ULP_F_CALL_PENDING, &cp->ulp_flags[ulp_type]) && + i < 20) { + msleep(100); + i++; + } + if (test_bit(ULP_F_CALL_PENDING, &cp->ulp_flags[ulp_type])) + printk(KERN_WARNING PFX "%s: Failed waiting for ULP up call" + " to complete.\n", dev->netdev->name); + return 0; } EXPORT_SYMBOL(cnic_unregister_driver); @@ -1076,18 +1108,23 @@ static void cnic_ulp_stop(struct cnic_dev *dev) if (cp->cnic_uinfo) cnic_send_nlmsg(cp, ISCSI_KEVENT_IF_DOWN, NULL); - rcu_read_lock(); for (if_type = 0; if_type < MAX_CNIC_ULP_TYPE; if_type++) { struct cnic_ulp_ops *ulp_ops; - ulp_ops = rcu_dereference(cp->ulp_ops[if_type]); - if (!ulp_ops) + mutex_lock(&cnic_lock); + ulp_ops = cp->ulp_ops[if_type]; + if (!ulp_ops) { + mutex_unlock(&cnic_lock); continue; + } + set_bit(ULP_F_CALL_PENDING, &cp->ulp_flags[if_type]); + mutex_unlock(&cnic_lock); if (test_and_clear_bit(ULP_F_START, &cp->ulp_flags[if_type])) ulp_ops->cnic_stop(cp->ulp_handle[if_type]); + + clear_bit(ULP_F_CALL_PENDING, &cp->ulp_flags[if_type]); } - rcu_read_unlock(); } static void cnic_ulp_start(struct cnic_dev *dev) @@ -1095,18 +1132,23 @@ static void cnic_ulp_start(struct cnic_dev *dev) struct cnic_local *cp = dev->cnic_priv; int if_type; - rcu_read_lock(); for (if_type = 0; if_type < MAX_CNIC_ULP_TYPE; if_type++) { struct cnic_ulp_ops *ulp_ops; - ulp_ops = rcu_dereference(cp->ulp_ops[if_type]); - if (!ulp_ops || !ulp_ops->cnic_start) + mutex_lock(&cnic_lock); + ulp_ops = cp->ulp_ops[if_type]; + if (!ulp_ops || !ulp_ops->cnic_start) { + mutex_unlock(&cnic_lock); continue; + } + set_bit(ULP_F_CALL_PENDING, &cp->ulp_flags[if_type]); + mutex_unlock(&cnic_lock); if (!test_and_set_bit(ULP_F_START, &cp->ulp_flags[if_type])) ulp_ops->cnic_start(cp->ulp_handle[if_type]); + + clear_bit(ULP_F_CALL_PENDING, &cp->ulp_flags[if_type]); } - rcu_read_unlock(); } static int cnic_ctl(void *data, struct cnic_ctl_info *info) @@ -1116,22 +1158,18 @@ static int cnic_ctl(void *data, struct cnic_ctl_info *info) switch (info->cmd) { case CNIC_CTL_STOP_CMD: cnic_hold(dev); - mutex_lock(&cnic_lock); cnic_ulp_stop(dev); cnic_stop_hw(dev); - mutex_unlock(&cnic_lock); cnic_put(dev); break; case CNIC_CTL_START_CMD: cnic_hold(dev); - mutex_lock(&cnic_lock); if (!cnic_start_hw(dev)) cnic_ulp_start(dev); - mutex_unlock(&cnic_lock); cnic_put(dev); break; default: @@ -1145,19 +1183,23 @@ static void cnic_ulp_init(struct cnic_dev *dev) int i; struct cnic_local *cp = dev->cnic_priv; - rcu_read_lock(); for (i = 0; i < MAX_CNIC_ULP_TYPE_EXT; i++) { struct cnic_ulp_ops *ulp_ops; - ulp_ops = rcu_dereference(cnic_ulp_tbl[i]); - if (!ulp_ops || !ulp_ops->cnic_init) + mutex_lock(&cnic_lock); + ulp_ops = cnic_ulp_tbl[i]; + if (!ulp_ops || !ulp_ops->cnic_init) { + mutex_unlock(&cnic_lock); continue; + } + ulp_get(ulp_ops); + mutex_unlock(&cnic_lock); if (!test_and_set_bit(ULP_F_INIT, &cp->ulp_flags[i])) ulp_ops->cnic_init(dev); + ulp_put(ulp_ops); } - rcu_read_unlock(); } static void cnic_ulp_exit(struct cnic_dev *dev) @@ -1165,19 +1207,23 @@ static void cnic_ulp_exit(struct cnic_dev *dev) int i; struct cnic_local *cp = dev->cnic_priv; - rcu_read_lock(); for (i = 0; i < MAX_CNIC_ULP_TYPE_EXT; i++) { struct cnic_ulp_ops *ulp_ops; - ulp_ops = rcu_dereference(cnic_ulp_tbl[i]); - if (!ulp_ops || !ulp_ops->cnic_exit) + mutex_lock(&cnic_lock); + ulp_ops = cnic_ulp_tbl[i]; + if (!ulp_ops || !ulp_ops->cnic_exit) { + mutex_unlock(&cnic_lock); continue; + } + ulp_get(ulp_ops); + mutex_unlock(&cnic_lock); if (test_and_clear_bit(ULP_F_INIT, &cp->ulp_flags[i])) ulp_ops->cnic_exit(dev); + ulp_put(ulp_ops); } - rcu_read_unlock(); } static int cnic_cm_offload_pg(struct cnic_sock *csk) @@ -2393,21 +2439,45 @@ static int cnic_start_bnx2_hw(struct cnic_dev *dev) return 0; } -static int cnic_start_hw(struct cnic_dev *dev) +static int cnic_register_netdev(struct cnic_dev *dev) { struct cnic_local *cp = dev->cnic_priv; struct cnic_eth_dev *ethdev = cp->ethdev; int err; - if (test_bit(CNIC_F_CNIC_UP, &dev->flags)) - return -EALREADY; + if (!ethdev) + return -ENODEV; + + if (ethdev->drv_state & CNIC_DRV_STATE_REGD) + return 0; err = ethdev->drv_register_cnic(dev->netdev, cp->cnic_ops, dev); - if (err) { + if (err) printk(KERN_ERR PFX "%s: register_cnic failed\n", dev->netdev->name); - goto err2; - } + + return err; +} + +static void cnic_unregister_netdev(struct cnic_dev *dev) +{ + struct cnic_local *cp = dev->cnic_priv; + struct cnic_eth_dev *ethdev = cp->ethdev; + + if (!ethdev) + return; + + ethdev->drv_unregister_cnic(dev->netdev); +} + +static int cnic_start_hw(struct cnic_dev *dev) +{ + struct cnic_local *cp = dev->cnic_priv; + struct cnic_eth_dev *ethdev = cp->ethdev; + int err; + + if (test_bit(CNIC_F_CNIC_UP, &dev->flags)) + return -EALREADY; dev->regview = ethdev->io_base; cp->chip_id = ethdev->chip_id; @@ -2438,18 +2508,13 @@ static int cnic_start_hw(struct cnic_dev *dev) return 0; err1: - ethdev->drv_unregister_cnic(dev->netdev); cp->free_resc(dev); pci_dev_put(dev->pcidev); -err2: return err; } static void cnic_stop_bnx2_hw(struct cnic_dev *dev) { - struct cnic_local *cp = dev->cnic_priv; - struct cnic_eth_dev *ethdev = cp->ethdev; - cnic_disable_bnx2_int_sync(dev); cnic_reg_wr_ind(dev, BNX2_CP_SCRATCH + 0x20, 0); @@ -2461,8 +2526,6 @@ static void cnic_stop_bnx2_hw(struct cnic_dev *dev) cnic_setup_5709_context(dev, 0); cnic_free_irq(dev); - ethdev->drv_unregister_cnic(dev->netdev); - cnic_free_resc(dev); } @@ -2543,7 +2606,7 @@ static struct cnic_dev *init_bnx2_cnic(struct net_device *dev) probe = symbol_get(bnx2_cnic_probe); if (probe) { ethdev = (*probe)(dev); - symbol_put_addr(probe); + symbol_put(bnx2_cnic_probe); } if (!ethdev) return NULL; @@ -2646,10 +2709,12 @@ static int cnic_netdev_event(struct notifier_block *this, unsigned long event, else if (event == NETDEV_UNREGISTER) cnic_ulp_exit(dev); else if (event == NETDEV_UP) { - mutex_lock(&cnic_lock); + if (cnic_register_netdev(dev) != 0) { + cnic_put(dev); + goto done; + } if (!cnic_start_hw(dev)) cnic_ulp_start(dev); - mutex_unlock(&cnic_lock); } rcu_read_lock(); @@ -2668,10 +2733,9 @@ static int cnic_netdev_event(struct notifier_block *this, unsigned long event, rcu_read_unlock(); if (event == NETDEV_GOING_DOWN) { - mutex_lock(&cnic_lock); cnic_ulp_stop(dev); cnic_stop_hw(dev); - mutex_unlock(&cnic_lock); + cnic_unregister_netdev(dev); } else if (event == NETDEV_UNREGISTER) { write_lock(&cnic_dev_lock); list_del_init(&dev->list); @@ -2703,6 +2767,7 @@ static void cnic_release(void) } cnic_ulp_exit(dev); + cnic_unregister_netdev(dev); list_del_init(&dev->list); cnic_free_dev(dev); } diff --git a/drivers/net/cnic.h b/drivers/net/cnic.h index 5192d4a..a94b302 100644 --- a/drivers/net/cnic.h +++ b/drivers/net/cnic.h @@ -176,6 +176,7 @@ struct cnic_local { unsigned long ulp_flags[MAX_CNIC_ULP_TYPE]; #define ULP_F_INIT 0 #define ULP_F_START 1 +#define ULP_F_CALL_PENDING 2 struct cnic_ulp_ops *ulp_ops[MAX_CNIC_ULP_TYPE]; /* protected by ulp_lock */ diff --git a/drivers/net/cnic_if.h b/drivers/net/cnic_if.h index d1bce27..a492357 100644 --- a/drivers/net/cnic_if.h +++ b/drivers/net/cnic_if.h @@ -290,6 +290,7 @@ struct cnic_ulp_ops { void (*iscsi_nl_send_msg)(struct cnic_dev *dev, u32 msg_type, char *data, u16 data_size); struct module *owner; + atomic_t ref_count; }; extern int cnic_register_driver(int ulp_type, struct cnic_ulp_ops *ulp_ops); diff --git a/drivers/net/e100.c b/drivers/net/e100.c index 41b648a..3a6735d 100644 --- a/drivers/net/e100.c +++ b/drivers/net/e100.c @@ -1899,7 +1899,7 @@ static int e100_rx_indicate(struct nic *nic, struct rx *rx, nic->ru_running = RU_SUSPENDED; pci_dma_sync_single_for_device(nic->pdev, rx->dma_addr, sizeof(struct rfd), - PCI_DMA_BIDIRECTIONAL); + PCI_DMA_FROMDEVICE); return -ENODATA; } diff --git a/drivers/net/e1000e/ich8lan.c b/drivers/net/e1000e/ich8lan.c index d56c747..99df2ab 100644 --- a/drivers/net/e1000e/ich8lan.c +++ b/drivers/net/e1000e/ich8lan.c @@ -338,10 +338,7 @@ static s32 e1000_init_nvm_params_ich8lan(struct e1000_hw *hw) { struct e1000_nvm_info *nvm = &hw->nvm; struct e1000_dev_spec_ich8lan *dev_spec = &hw->dev_spec.ich8lan; - union ich8_hws_flash_status hsfsts; - u32 gfpreg; - u32 sector_base_addr; - u32 sector_end_addr; + u32 gfpreg, sector_base_addr, sector_end_addr; u16 i; /* Can't read flash registers if the register set isn't mapped. */ @@ -375,20 +372,6 @@ static s32 e1000_init_nvm_params_ich8lan(struct e1000_hw *hw) /* Adjust to word count */ nvm->flash_bank_size /= sizeof(u16); - /* - * Make sure the flash bank size does not overwrite the 4k - * sector ranges. We may have 64k allotted to us but we only care - * about the first 2 4k sectors. Therefore, if we have anything less - * than 64k set in the HSFSTS register, we will reduce the bank size - * down to 4k and let the rest remain unused. If berasesz == 3, then - * we are working in 64k mode. Otherwise we are not. - */ - if (nvm->flash_bank_size > E1000_ICH8_SHADOW_RAM_WORDS) { - hsfsts.regval = er16flash(ICH_FLASH_HSFSTS); - if (hsfsts.hsf_status.berasesz != 3) - nvm->flash_bank_size = E1000_ICH8_SHADOW_RAM_WORDS; - } - nvm->word_size = E1000_ICH8_SHADOW_RAM_WORDS; /* Clear shadow ram */ @@ -594,8 +577,8 @@ static DEFINE_MUTEX(nvm_mutex); **/ static s32 e1000_acquire_swflag_ich8lan(struct e1000_hw *hw) { - u32 extcnf_ctrl; - u32 timeout = PHY_CFG_TIMEOUT; + u32 extcnf_ctrl, timeout = PHY_CFG_TIMEOUT; + s32 ret_val = 0; might_sleep(); @@ -603,28 +586,46 @@ static s32 e1000_acquire_swflag_ich8lan(struct e1000_hw *hw) while (timeout) { extcnf_ctrl = er32(EXTCNF_CTRL); + if (!(extcnf_ctrl & E1000_EXTCNF_CTRL_SWFLAG)) + break; - if (!(extcnf_ctrl & E1000_EXTCNF_CTRL_SWFLAG)) { - extcnf_ctrl |= E1000_EXTCNF_CTRL_SWFLAG; - ew32(EXTCNF_CTRL, extcnf_ctrl); + mdelay(1); + timeout--; + } + + if (!timeout) { + hw_dbg(hw, "SW/FW/HW has locked the resource for too long.\n"); + ret_val = -E1000_ERR_CONFIG; + goto out; + } + + timeout = PHY_CFG_TIMEOUT * 2; + + extcnf_ctrl |= E1000_EXTCNF_CTRL_SWFLAG; + ew32(EXTCNF_CTRL, extcnf_ctrl); + + while (timeout) { + extcnf_ctrl = er32(EXTCNF_CTRL); + if (extcnf_ctrl & E1000_EXTCNF_CTRL_SWFLAG) + break; - extcnf_ctrl = er32(EXTCNF_CTRL); - if (extcnf_ctrl & E1000_EXTCNF_CTRL_SWFLAG) - break; - } mdelay(1); timeout--; } if (!timeout) { - hw_dbg(hw, "FW or HW has locked the resource for too long.\n"); + hw_dbg(hw, "Failed to acquire the semaphore.\n"); extcnf_ctrl &= ~E1000_EXTCNF_CTRL_SWFLAG; ew32(EXTCNF_CTRL, extcnf_ctrl); - mutex_unlock(&nvm_mutex); - return -E1000_ERR_CONFIG; + ret_val = -E1000_ERR_CONFIG; + goto out; } - return 0; +out: + if (ret_val) + mutex_unlock(&nvm_mutex); + + return ret_val; } /** @@ -1306,7 +1307,7 @@ static s32 e1000_read_nvm_ich8lan(struct e1000_hw *hw, u16 offset, u16 words, struct e1000_nvm_info *nvm = &hw->nvm; struct e1000_dev_spec_ich8lan *dev_spec = &hw->dev_spec.ich8lan; u32 act_offset; - s32 ret_val; + s32 ret_val = 0; u32 bank = 0; u16 i, word; @@ -1321,12 +1322,15 @@ static s32 e1000_read_nvm_ich8lan(struct e1000_hw *hw, u16 offset, u16 words, goto out; ret_val = e1000_valid_nvm_bank_detect_ich8lan(hw, &bank); - if (ret_val) - goto release; + if (ret_val) { + hw_dbg(hw, "Could not detect valid bank, assuming bank 0\n"); + bank = 0; + } act_offset = (bank) ? nvm->flash_bank_size : 0; act_offset += offset; + ret_val = 0; for (i = 0; i < words; i++) { if ((dev_spec->shadow_ram) && (dev_spec->shadow_ram[offset+i].modified)) { @@ -1341,7 +1345,6 @@ static s32 e1000_read_nvm_ich8lan(struct e1000_hw *hw, u16 offset, u16 words, } } -release: e1000_release_swflag_ich8lan(hw); out: @@ -1592,7 +1595,6 @@ static s32 e1000_write_nvm_ich8lan(struct e1000_hw *hw, u16 offset, u16 words, { struct e1000_nvm_info *nvm = &hw->nvm; struct e1000_dev_spec_ich8lan *dev_spec = &hw->dev_spec.ich8lan; - s32 ret_val; u16 i; if ((offset >= nvm->word_size) || (words > nvm->word_size - offset) || @@ -1601,17 +1603,11 @@ static s32 e1000_write_nvm_ich8lan(struct e1000_hw *hw, u16 offset, u16 words, return -E1000_ERR_NVM; } - ret_val = e1000_acquire_swflag_ich8lan(hw); - if (ret_val) - return ret_val; - for (i = 0; i < words; i++) { dev_spec->shadow_ram[offset+i].modified = 1; dev_spec->shadow_ram[offset+i].value = data[i]; } - e1000_release_swflag_ich8lan(hw); - return 0; } @@ -1652,8 +1648,8 @@ static s32 e1000_update_nvm_checksum_ich8lan(struct e1000_hw *hw) */ ret_val = e1000_valid_nvm_bank_detect_ich8lan(hw, &bank); if (ret_val) { - e1000_release_swflag_ich8lan(hw); - goto out; + hw_dbg(hw, "Could not detect valid bank, assuming bank 0\n"); + bank = 0; } if (bank == 0) { @@ -2039,12 +2035,8 @@ static s32 e1000_erase_flash_bank_ich8lan(struct e1000_hw *hw, u32 bank) iteration = 1; break; case 2: - if (hw->mac.type == e1000_ich9lan) { - sector_size = ICH_FLASH_SEG_SIZE_8K; - iteration = flash_bank_size / ICH_FLASH_SEG_SIZE_8K; - } else { - return -E1000_ERR_NVM; - } + sector_size = ICH_FLASH_SEG_SIZE_8K; + iteration = 1; break; case 3: sector_size = ICH_FLASH_SEG_SIZE_64K; @@ -2056,7 +2048,7 @@ static s32 e1000_erase_flash_bank_ich8lan(struct e1000_hw *hw, u32 bank) /* Start with the base address, then add the sector offset. */ flash_linear_addr = hw->nvm.flash_base_addr; - flash_linear_addr += (bank) ? (sector_size * iteration) : 0; + flash_linear_addr += (bank) ? flash_bank_size : 0; for (j = 0; j < iteration ; j++) { do { diff --git a/drivers/net/e1000e/netdev.c b/drivers/net/e1000e/netdev.c index 63415bb..fa92a68 100644 --- a/drivers/net/e1000e/netdev.c +++ b/drivers/net/e1000e/netdev.c @@ -4538,8 +4538,7 @@ static int __e1000_shutdown(struct pci_dev *pdev, bool *enable_wake) /* Allow time for pending master requests to run */ e1000e_disable_pcie_master(&adapter->hw); - if ((adapter->flags2 & FLAG2_HAS_PHY_WAKEUP) && - !(hw->mac.ops.check_mng_mode(hw))) { + if (adapter->flags2 & FLAG2_HAS_PHY_WAKEUP) { /* enable wakeup by the PHY */ retval = e1000_init_phy_wakeup(adapter, wufc); if (retval) @@ -4557,7 +4556,8 @@ static int __e1000_shutdown(struct pci_dev *pdev, bool *enable_wake) *enable_wake = !!wufc; /* make sure adapter isn't asleep if manageability is enabled */ - if (adapter->flags & FLAG_MNG_PT_ENABLED) + if ((adapter->flags & FLAG_MNG_PT_ENABLED) || + (hw->mac.ops.check_mng_mode(hw))) *enable_wake = true; if (adapter->hw.phy.type == e1000_phy_igp_3) @@ -4670,14 +4670,6 @@ static int e1000_resume(struct pci_dev *pdev) return err; } - /* AER (Advanced Error Reporting) hooks */ - err = pci_enable_pcie_error_reporting(pdev); - if (err) { - dev_err(&pdev->dev, "pci_enable_pcie_error_reporting failed " - "0x%x\n", err); - /* non-fatal, continue */ - } - pci_set_master(pdev); pci_enable_wake(pdev, PCI_D3hot, 0); @@ -4990,6 +4982,14 @@ static int __devinit e1000_probe(struct pci_dev *pdev, if (err) goto err_pci_reg; + /* AER (Advanced Error Reporting) hooks */ + err = pci_enable_pcie_error_reporting(pdev); + if (err) { + dev_err(&pdev->dev, "pci_enable_pcie_error_reporting failed " + "0x%x\n", err); + /* non-fatal, continue */ + } + pci_set_master(pdev); /* PCI config space info */ err = pci_save_state(pdev); diff --git a/drivers/net/fec.c b/drivers/net/fec.c index d4b9807..c9fd82d 100644 --- a/drivers/net/fec.c +++ b/drivers/net/fec.c @@ -285,6 +285,7 @@ fec_enet_start_xmit(struct sk_buff *skb, struct net_device *dev) { struct fec_enet_private *fep = netdev_priv(dev); struct bufdesc *bdp; + void *bufaddr; unsigned short status; unsigned long flags; @@ -312,7 +313,7 @@ fec_enet_start_xmit(struct sk_buff *skb, struct net_device *dev) status &= ~BD_ENET_TX_STATS; /* Set buffer length and buffer pointer */ - bdp->cbd_bufaddr = __pa(skb->data); + bufaddr = skb->data; bdp->cbd_datlen = skb->len; /* @@ -320,11 +321,11 @@ fec_enet_start_xmit(struct sk_buff *skb, struct net_device *dev) * 4-byte boundaries. Use bounce buffers to copy data * and get it aligned. Ugh. */ - if (bdp->cbd_bufaddr & FEC_ALIGNMENT) { + if (((unsigned long) bufaddr) & FEC_ALIGNMENT) { unsigned int index; index = bdp - fep->tx_bd_base; memcpy(fep->tx_bounce[index], (void *)skb->data, skb->len); - bdp->cbd_bufaddr = __pa(fep->tx_bounce[index]); + bufaddr = fep->tx_bounce[index]; } /* Save skb pointer */ @@ -336,7 +337,7 @@ fec_enet_start_xmit(struct sk_buff *skb, struct net_device *dev) /* Push the data cache so the CPM does not get stale memory * data. */ - bdp->cbd_bufaddr = dma_map_single(&dev->dev, skb->data, + bdp->cbd_bufaddr = dma_map_single(&dev->dev, bufaddr, FEC_ENET_TX_FRSIZE, DMA_TO_DEVICE); /* Send it on its way. Tell FEC it's ready, interrupt when done, diff --git a/drivers/net/fec_mpc52xx.c b/drivers/net/fec_mpc52xx.c index cc78633..c40113f 100644 --- a/drivers/net/fec_mpc52xx.c +++ b/drivers/net/fec_mpc52xx.c @@ -309,6 +309,7 @@ static int mpc52xx_fec_start_xmit(struct sk_buff *skb, struct net_device *dev) { struct mpc52xx_fec_priv *priv = netdev_priv(dev); struct bcom_fec_bd *bd; + unsigned long flags; if (bcom_queue_full(priv->tx_dmatsk)) { if (net_ratelimit()) @@ -316,7 +317,7 @@ static int mpc52xx_fec_start_xmit(struct sk_buff *skb, struct net_device *dev) return NETDEV_TX_BUSY; } - spin_lock_irq(&priv->lock); + spin_lock_irqsave(&priv->lock, flags); dev->trans_start = jiffies; bd = (struct bcom_fec_bd *) @@ -332,7 +333,7 @@ static int mpc52xx_fec_start_xmit(struct sk_buff *skb, struct net_device *dev) netif_stop_queue(dev); } - spin_unlock_irq(&priv->lock); + spin_unlock_irqrestore(&priv->lock, flags); return NETDEV_TX_OK; } diff --git a/drivers/net/gianfar.c b/drivers/net/gianfar.c index f8ffcbf..e212f2c 100644 --- a/drivers/net/gianfar.c +++ b/drivers/net/gianfar.c @@ -936,6 +936,7 @@ int startup_gfar(struct net_device *dev) struct gfar __iomem *regs = priv->regs; int err = 0; u32 rctrl = 0; + u32 tctrl = 0; u32 attrs = 0; gfar_write(®s->imask, IMASK_INIT_CLEAR); @@ -1111,11 +1112,19 @@ int startup_gfar(struct net_device *dev) rctrl |= RCTRL_PADDING(priv->padding); } + /* keep vlan related bits if it's enabled */ + if (priv->vlgrp) { + rctrl |= RCTRL_VLEX | RCTRL_PRSDEP_INIT; + tctrl |= TCTRL_VLINS; + } + /* Init rctrl based on our settings */ gfar_write(&priv->regs->rctrl, rctrl); if (dev->features & NETIF_F_IP_CSUM) - gfar_write(&priv->regs->tctrl, TCTRL_INIT_CSUM); + tctrl |= TCTRL_INIT_CSUM; + + gfar_write(&priv->regs->tctrl, tctrl); /* Set the extraction length and index */ attrs = ATTRELI_EL(priv->rx_stash_size) | @@ -1450,7 +1459,6 @@ static void gfar_vlan_rx_register(struct net_device *dev, /* Enable VLAN tag extraction */ tempval = gfar_read(&priv->regs->rctrl); - tempval |= RCTRL_VLEX; tempval |= (RCTRL_VLEX | RCTRL_PRSDEP_INIT); gfar_write(&priv->regs->rctrl, tempval); } else { diff --git a/drivers/net/ibm_newemac/core.c b/drivers/net/ibm_newemac/core.c index beb8421..f0f8908 100644 --- a/drivers/net/ibm_newemac/core.c +++ b/drivers/net/ibm_newemac/core.c @@ -1305,6 +1305,8 @@ static int emac_close(struct net_device *ndev) free_irq(dev->emac_irq, dev); + netif_carrier_off(ndev); + return 0; } diff --git a/drivers/net/irda/pxaficp_ir.c b/drivers/net/irda/pxaficp_ir.c index 3376a4f..77d10ed 100644 --- a/drivers/net/irda/pxaficp_ir.c +++ b/drivers/net/irda/pxaficp_ir.c @@ -803,9 +803,6 @@ static const struct net_device_ops pxa_irda_netdev_ops = { .ndo_stop = pxa_irda_stop, .ndo_start_xmit = pxa_irda_hard_xmit, .ndo_do_ioctl = pxa_irda_ioctl, - .ndo_change_mtu = eth_change_mtu, - .ndo_validate_addr = eth_validate_addr, - .ndo_set_mac_address = eth_mac_addr, }; static int pxa_irda_probe(struct platform_device *pdev) @@ -830,6 +827,7 @@ static int pxa_irda_probe(struct platform_device *pdev) if (!dev) goto err_mem_3; + SET_NETDEV_DEV(dev, &pdev->dev); si = netdev_priv(dev); si->dev = &pdev->dev; si->pdata = pdev->dev.platform_data; diff --git a/drivers/net/irda/w83977af_ir.c b/drivers/net/irda/w83977af_ir.c index d088383..fe4f2b2 100644 --- a/drivers/net/irda/w83977af_ir.c +++ b/drivers/net/irda/w83977af_ir.c @@ -115,7 +115,7 @@ static int __init w83977af_init(void) IRDA_DEBUG(0, "%s()\n", __func__ ); - for (i=0; (io[i] < 2000) && (i < ARRAY_SIZE(dev_self)); i++) { + for (i=0; i < ARRAY_SIZE(dev_self) && io[i] < 2000; i++) { if (w83977af_open(i, io[i], irq[i], dma[i]) == 0) return 0; } diff --git a/drivers/net/ixgbe/ixgbe.h b/drivers/net/ixgbe/ixgbe.h index e11d83d..2c4dc82 100644 --- a/drivers/net/ixgbe/ixgbe.h +++ b/drivers/net/ixgbe/ixgbe.h @@ -136,6 +136,8 @@ struct ixgbe_ring { u8 queue_index; /* needed for multiqueue queue management */ +#define IXGBE_RING_RX_PS_ENABLED (u8)(1) + u8 flags; /* per ring feature flags */ u16 head; u16 tail; diff --git a/drivers/net/ixgbe/ixgbe_ethtool.c b/drivers/net/ixgbe/ixgbe_ethtool.c index 79144e9..dff8dfa 100644 --- a/drivers/net/ixgbe/ixgbe_ethtool.c +++ b/drivers/net/ixgbe/ixgbe_ethtool.c @@ -1948,6 +1948,7 @@ static int ixgbe_set_coalesce(struct net_device *netdev, struct ethtool_coalesce *ec) { struct ixgbe_adapter *adapter = netdev_priv(netdev); + struct ixgbe_q_vector *q_vector; int i; if (ec->tx_max_coalesced_frames_irq) @@ -1982,14 +1983,24 @@ static int ixgbe_set_coalesce(struct net_device *netdev, adapter->itr_setting = 0; } - for (i = 0; i < adapter->num_msix_vectors - NON_Q_VECTORS; i++) { - struct ixgbe_q_vector *q_vector = adapter->q_vector[i]; - if (q_vector->txr_count && !q_vector->rxr_count) - /* tx vector gets half the rate */ - q_vector->eitr = (adapter->eitr_param >> 1); - else - /* rx only or mixed */ - q_vector->eitr = adapter->eitr_param; + /* MSI/MSIx Interrupt Mode */ + if (adapter->flags & + (IXGBE_FLAG_MSIX_ENABLED | IXGBE_FLAG_MSI_ENABLED)) { + int num_vectors = adapter->num_msix_vectors - NON_Q_VECTORS; + for (i = 0; i < num_vectors; i++) { + q_vector = adapter->q_vector[i]; + if (q_vector->txr_count && !q_vector->rxr_count) + /* tx vector gets half the rate */ + q_vector->eitr = (adapter->eitr_param >> 1); + else + /* rx only or mixed */ + q_vector->eitr = adapter->eitr_param; + ixgbe_write_eitr(q_vector); + } + /* Legacy Interrupt Mode */ + } else { + q_vector = adapter->q_vector[0]; + q_vector->eitr = adapter->eitr_param; ixgbe_write_eitr(q_vector); } diff --git a/drivers/net/ixgbe/ixgbe_fcoe.c b/drivers/net/ixgbe/ixgbe_fcoe.c index fa9f24e..28cf104 100644 --- a/drivers/net/ixgbe/ixgbe_fcoe.c +++ b/drivers/net/ixgbe/ixgbe_fcoe.c @@ -336,7 +336,7 @@ int ixgbe_fcoe_ddp(struct ixgbe_adapter *adapter, /* return 0 to bypass going to ULD for DDPed data */ if (fcstat == IXGBE_RXDADV_STAT_FCSTAT_DDP) rc = 0; - else + else if (ddp->len) rc = ddp->len; } diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c index 110c65a..77b0381 100644 --- a/drivers/net/ixgbe/ixgbe_main.c +++ b/drivers/net/ixgbe/ixgbe_main.c @@ -492,12 +492,12 @@ static void ixgbe_receive_skb(struct ixgbe_q_vector *q_vector, skb_record_rx_queue(skb, ring->queue_index); if (!(adapter->flags & IXGBE_FLAG_IN_NETPOLL)) { - if (adapter->vlgrp && is_vlan && (tag != 0)) + if (adapter->vlgrp && is_vlan && (tag & VLAN_VID_MASK)) vlan_gro_receive(napi, adapter->vlgrp, tag, skb); else napi_gro_receive(napi, skb); } else { - if (adapter->vlgrp && is_vlan && (tag != 0)) + if (adapter->vlgrp && is_vlan && (tag & VLAN_VID_MASK)) vlan_hwaccel_rx(skb, adapter->vlgrp, tag); else netif_rx(skb); @@ -585,7 +585,7 @@ static void ixgbe_alloc_rx_buffers(struct ixgbe_adapter *adapter, rx_desc = IXGBE_RX_DESC_ADV(*rx_ring, i); if (!bi->page_dma && - (adapter->flags & IXGBE_FLAG_RX_PS_ENABLED)) { + (rx_ring->flags & IXGBE_RING_RX_PS_ENABLED)) { if (!bi->page) { bi->page = alloc_page(GFP_ATOMIC); if (!bi->page) { @@ -629,7 +629,7 @@ static void ixgbe_alloc_rx_buffers(struct ixgbe_adapter *adapter, } /* Refresh the desc even if buffer_addrs didn't change because * each write-back erases this info. */ - if (adapter->flags & IXGBE_FLAG_RX_PS_ENABLED) { + if (rx_ring->flags & IXGBE_RING_RX_PS_ENABLED) { rx_desc->read.pkt_addr = cpu_to_le64(bi->page_dma); rx_desc->read.hdr_addr = cpu_to_le64(bi->dma); } else { @@ -726,7 +726,7 @@ static bool ixgbe_clean_rx_irq(struct ixgbe_q_vector *q_vector, break; (*work_done)++; - if (adapter->flags & IXGBE_FLAG_RX_PS_ENABLED) { + if (rx_ring->flags & IXGBE_RING_RX_PS_ENABLED) { hdr_info = le16_to_cpu(ixgbe_get_hdr_info(rx_desc)); len = (hdr_info & IXGBE_RXDADV_HDRBUFLEN_MASK) >> IXGBE_RXDADV_HDRBUFLEN_SHIFT; @@ -798,7 +798,7 @@ static bool ixgbe_clean_rx_irq(struct ixgbe_q_vector *q_vector, rx_ring->stats.packets++; rx_ring->stats.bytes += skb->len; } else { - if (adapter->flags & IXGBE_FLAG_RX_PS_ENABLED) { + if (rx_ring->flags & IXGBE_RING_RX_PS_ENABLED) { rx_buffer_info->skb = next_buffer->skb; rx_buffer_info->dma = next_buffer->dma; next_buffer->skb = skb; @@ -1898,46 +1898,19 @@ static void ixgbe_configure_tx(struct ixgbe_adapter *adapter) #define IXGBE_SRRCTL_BSIZEHDRSIZE_SHIFT 2 -static void ixgbe_configure_srrctl(struct ixgbe_adapter *adapter, int index) +static void ixgbe_configure_srrctl(struct ixgbe_adapter *adapter, + struct ixgbe_ring *rx_ring) { - struct ixgbe_ring *rx_ring; u32 srrctl; - int queue0 = 0; - unsigned long mask; + int index; struct ixgbe_ring_feature *feature = adapter->ring_feature; - if (adapter->hw.mac.type == ixgbe_mac_82599EB) { - if (adapter->flags & IXGBE_FLAG_DCB_ENABLED) { - int dcb_i = feature[RING_F_DCB].indices; - if (dcb_i == 8) - queue0 = index >> 4; - else if (dcb_i == 4) - queue0 = index >> 5; - else - dev_err(&adapter->pdev->dev, "Invalid DCB " - "configuration\n"); -#ifdef IXGBE_FCOE - if (adapter->flags & IXGBE_FLAG_FCOE_ENABLED) { - struct ixgbe_ring_feature *f; - - rx_ring = &adapter->rx_ring[queue0]; - f = &adapter->ring_feature[RING_F_FCOE]; - if ((queue0 == 0) && (index > rx_ring->reg_idx)) - queue0 = f->mask + index - - rx_ring->reg_idx - 1; - } -#endif /* IXGBE_FCOE */ - } else { - queue0 = index; - } - } else { + index = rx_ring->reg_idx; + if (adapter->hw.mac.type == ixgbe_mac_82598EB) { + unsigned long mask; mask = (unsigned long) feature[RING_F_RSS].mask; - queue0 = index & mask; index = index & mask; } - - rx_ring = &adapter->rx_ring[queue0]; - srrctl = IXGBE_READ_REG(&adapter->hw, IXGBE_SRRCTL(index)); srrctl &= ~IXGBE_SRRCTL_BSIZEHDR_MASK; @@ -1946,7 +1919,7 @@ static void ixgbe_configure_srrctl(struct ixgbe_adapter *adapter, int index) srrctl |= (IXGBE_RX_HDR_SIZE << IXGBE_SRRCTL_BSIZEHDRSIZE_SHIFT) & IXGBE_SRRCTL_BSIZEHDR_MASK; - if (adapter->flags & IXGBE_FLAG_RX_PS_ENABLED) { + if (rx_ring->flags & IXGBE_RING_RX_PS_ENABLED) { #if (PAGE_SIZE / 2) > IXGBE_MAX_RXBUFFER srrctl |= IXGBE_MAX_RXBUFFER >> IXGBE_SRRCTL_BSIZEPKT_SHIFT; #else @@ -2002,6 +1975,7 @@ static void ixgbe_configure_rx(struct ixgbe_adapter *adapter) { u64 rdba; struct ixgbe_hw *hw = &adapter->hw; + struct ixgbe_ring *rx_ring; struct net_device *netdev = adapter->netdev; int max_frame = netdev->mtu + ETH_HLEN + ETH_FCS_LEN; int i, j; @@ -2018,11 +1992,6 @@ static void ixgbe_configure_rx(struct ixgbe_adapter *adapter) /* Decide whether to use packet split mode or not */ adapter->flags |= IXGBE_FLAG_RX_PS_ENABLED; -#ifdef IXGBE_FCOE - if (adapter->flags & IXGBE_FLAG_FCOE_ENABLED) - adapter->flags &= ~IXGBE_FLAG_RX_PS_ENABLED; -#endif /* IXGBE_FCOE */ - /* Set the RX buffer length according to the mode */ if (adapter->flags & IXGBE_FLAG_RX_PS_ENABLED) { rx_buf_len = IXGBE_RX_HDR_SIZE; @@ -2070,29 +2039,35 @@ static void ixgbe_configure_rx(struct ixgbe_adapter *adapter) * the Base and Length of the Rx Descriptor Ring */ for (i = 0; i < adapter->num_rx_queues; i++) { - rdba = adapter->rx_ring[i].dma; - j = adapter->rx_ring[i].reg_idx; + rx_ring = &adapter->rx_ring[i]; + rdba = rx_ring->dma; + j = rx_ring->reg_idx; IXGBE_WRITE_REG(hw, IXGBE_RDBAL(j), (rdba & DMA_BIT_MASK(32))); IXGBE_WRITE_REG(hw, IXGBE_RDBAH(j), (rdba >> 32)); IXGBE_WRITE_REG(hw, IXGBE_RDLEN(j), rdlen); IXGBE_WRITE_REG(hw, IXGBE_RDH(j), 0); IXGBE_WRITE_REG(hw, IXGBE_RDT(j), 0); - adapter->rx_ring[i].head = IXGBE_RDH(j); - adapter->rx_ring[i].tail = IXGBE_RDT(j); - adapter->rx_ring[i].rx_buf_len = rx_buf_len; + rx_ring->head = IXGBE_RDH(j); + rx_ring->tail = IXGBE_RDT(j); + rx_ring->rx_buf_len = rx_buf_len; + + if (adapter->flags & IXGBE_FLAG_RX_PS_ENABLED) + rx_ring->flags |= IXGBE_RING_RX_PS_ENABLED; #ifdef IXGBE_FCOE if (adapter->flags & IXGBE_FLAG_FCOE_ENABLED) { struct ixgbe_ring_feature *f; f = &adapter->ring_feature[RING_F_FCOE]; - if ((rx_buf_len < IXGBE_FCOE_JUMBO_FRAME_SIZE) && - (i >= f->mask) && (i < f->mask + f->indices)) - adapter->rx_ring[i].rx_buf_len = - IXGBE_FCOE_JUMBO_FRAME_SIZE; + if ((i >= f->mask) && (i < f->mask + f->indices)) { + rx_ring->flags &= ~IXGBE_RING_RX_PS_ENABLED; + if (rx_buf_len < IXGBE_FCOE_JUMBO_FRAME_SIZE) + rx_ring->rx_buf_len = + IXGBE_FCOE_JUMBO_FRAME_SIZE; + } } #endif /* IXGBE_FCOE */ - ixgbe_configure_srrctl(adapter, j); + ixgbe_configure_srrctl(adapter, rx_ring); } if (hw->mac.type == ixgbe_mac_82598EB) { @@ -2168,7 +2143,8 @@ static void ixgbe_configure_rx(struct ixgbe_adapter *adapter) if (adapter->flags2 & IXGBE_FLAG2_RSC_ENABLED) { /* Enable 82599 HW-RSC */ for (i = 0; i < adapter->num_rx_queues; i++) { - j = adapter->rx_ring[i].reg_idx; + rx_ring = &adapter->rx_ring[i]; + j = rx_ring->reg_idx; rscctrl = IXGBE_READ_REG(hw, IXGBE_RSCCTL(j)); rscctrl |= IXGBE_RSCCTL_RSCEN; /* @@ -2176,7 +2152,7 @@ static void ixgbe_configure_rx(struct ixgbe_adapter *adapter) * total size of max desc * buf_len is not greater * than 65535 */ - if (adapter->flags & IXGBE_FLAG_RX_PS_ENABLED) { + if (rx_ring->flags & IXGBE_RING_RX_PS_ENABLED) { #if (MAX_SKB_FRAGS > 16) rscctrl |= IXGBE_RSCCTL_MAXDESC_16; #elif (MAX_SKB_FRAGS > 8) diff --git a/drivers/net/ixp2000/ixpdev.c b/drivers/net/ixp2000/ixpdev.c index 2a0174b..92fb823 100644 --- a/drivers/net/ixp2000/ixpdev.c +++ b/drivers/net/ixp2000/ixpdev.c @@ -41,6 +41,7 @@ static int ixpdev_xmit(struct sk_buff *skb, struct net_device *dev) struct ixpdev_priv *ip = netdev_priv(dev); struct ixpdev_tx_desc *desc; int entry; + unsigned long flags; if (unlikely(skb->len > PAGE_SIZE)) { /* @@@ Count drops. */ @@ -63,11 +64,11 @@ static int ixpdev_xmit(struct sk_buff *skb, struct net_device *dev) dev->trans_start = jiffies; - local_irq_disable(); + local_irq_save(flags); ip->tx_queue_entries++; if (ip->tx_queue_entries == TX_BUF_COUNT_PER_CHAN) netif_stop_queue(dev); - local_irq_enable(); + local_irq_restore(flags); return 0; } diff --git a/drivers/net/macb.c b/drivers/net/macb.c index 5b5c253..e3601cf3 100644 --- a/drivers/net/macb.c +++ b/drivers/net/macb.c @@ -620,6 +620,7 @@ static int macb_start_xmit(struct sk_buff *skb, struct net_device *dev) dma_addr_t mapping; unsigned int len, entry; u32 ctrl; + unsigned long flags; #ifdef DEBUG int i; @@ -635,12 +636,12 @@ static int macb_start_xmit(struct sk_buff *skb, struct net_device *dev) #endif len = skb->len; - spin_lock_irq(&bp->lock); + spin_lock_irqsave(&bp->lock, flags); /* This is a hard error, log it. */ if (TX_BUFFS_AVAIL(bp) < 1) { netif_stop_queue(dev); - spin_unlock_irq(&bp->lock); + spin_unlock_irqrestore(&bp->lock, flags); dev_err(&bp->pdev->dev, "BUG! Tx Ring full when queue awake!\n"); dev_dbg(&bp->pdev->dev, "tx_head = %u, tx_tail = %u\n", @@ -674,7 +675,7 @@ static int macb_start_xmit(struct sk_buff *skb, struct net_device *dev) if (TX_BUFFS_AVAIL(bp) < 1) netif_stop_queue(dev); - spin_unlock_irq(&bp->lock); + spin_unlock_irqrestore(&bp->lock, flags); dev->trans_start = jiffies; diff --git a/drivers/net/mlx4/en_rx.c b/drivers/net/mlx4/en_rx.c index 91bdfdf..3ac0404 100644 --- a/drivers/net/mlx4/en_rx.c +++ b/drivers/net/mlx4/en_rx.c @@ -506,8 +506,9 @@ static int mlx4_en_complete_rx_desc(struct mlx4_en_priv *priv, PCI_DMA_FROMDEVICE); } /* Adjust size of last fragment to match actual length */ - skb_frags_rx[nr - 1].size = length - - priv->frag_info[nr - 1].frag_prefix_size; + if (nr > 0) + skb_frags_rx[nr - 1].size = length - + priv->frag_info[nr - 1].frag_prefix_size; return nr; fail: diff --git a/drivers/net/mlx4/en_tx.c b/drivers/net/mlx4/en_tx.c index 5a88b3f5..6220840 100644 --- a/drivers/net/mlx4/en_tx.c +++ b/drivers/net/mlx4/en_tx.c @@ -437,6 +437,7 @@ static inline void mlx4_en_xmit_poll(struct mlx4_en_priv *priv, int tx_ind) { struct mlx4_en_cq *cq = &priv->tx_cq[tx_ind]; struct mlx4_en_tx_ring *ring = &priv->tx_ring[tx_ind]; + unsigned long flags; /* If we don't have a pending timer, set one up to catch our recent post in case the interface becomes idle */ @@ -445,9 +446,9 @@ static inline void mlx4_en_xmit_poll(struct mlx4_en_priv *priv, int tx_ind) /* Poll the CQ every mlx4_en_TX_MODER_POLL packets */ if ((++ring->poll_cnt & (MLX4_EN_TX_POLL_MODER - 1)) == 0) - if (spin_trylock_irq(&ring->comp_lock)) { + if (spin_trylock_irqsave(&ring->comp_lock, flags)) { mlx4_en_process_tx_cq(priv->dev, cq); - spin_unlock_irq(&ring->comp_lock); + spin_unlock_irqrestore(&ring->comp_lock, flags); } } diff --git a/drivers/net/netxen/netxen_nic.h b/drivers/net/netxen/netxen_nic.h index f86e050..a9c1fcc 100644 --- a/drivers/net/netxen/netxen_nic.h +++ b/drivers/net/netxen/netxen_nic.h @@ -1254,7 +1254,7 @@ struct netxen_adapter { u8 mc_enabled; u8 max_mc_count; u8 rss_supported; - u8 resv2; + u8 link_changed; u32 resv3; u8 has_link_events; diff --git a/drivers/net/netxen/netxen_nic_init.c b/drivers/net/netxen/netxen_nic_init.c index 7acf204..5d3343e 100644 --- a/drivers/net/netxen/netxen_nic_init.c +++ b/drivers/net/netxen/netxen_nic_init.c @@ -184,13 +184,6 @@ void netxen_free_sw_resources(struct netxen_adapter *adapter) kfree(recv_ctx->rds_rings); skip_rds: - if (recv_ctx->sds_rings == NULL) - goto skip_sds; - - for(ring = 0; ring < adapter->max_sds_rings; ring++) - recv_ctx->sds_rings[ring].consumer = 0; - -skip_sds: if (adapter->tx_ring == NULL) return; diff --git a/drivers/net/netxen/netxen_nic_main.c b/drivers/net/netxen/netxen_nic_main.c index 3cd8cfc..28f270f 100644 --- a/drivers/net/netxen/netxen_nic_main.c +++ b/drivers/net/netxen/netxen_nic_main.c @@ -94,10 +94,6 @@ static struct pci_device_id netxen_pci_tbl[] __devinitdata = { MODULE_DEVICE_TABLE(pci, netxen_pci_tbl); -static struct workqueue_struct *netxen_workq; -#define SCHEDULE_WORK(tp) queue_work(netxen_workq, tp) -#define FLUSH_SCHEDULED_WORK() flush_workqueue(netxen_workq) - static void netxen_watchdog(unsigned long); static uint32_t crb_cmd_producer[4] = { @@ -171,6 +167,8 @@ netxen_free_sds_rings(struct netxen_recv_context *recv_ctx) { if (recv_ctx->sds_rings != NULL) kfree(recv_ctx->sds_rings); + + recv_ctx->sds_rings = NULL; } static int @@ -193,6 +191,21 @@ netxen_napi_add(struct netxen_adapter *adapter, struct net_device *netdev) } static void +netxen_napi_del(struct netxen_adapter *adapter) +{ + int ring; + struct nx_host_sds_ring *sds_ring; + struct netxen_recv_context *recv_ctx = &adapter->recv_ctx; + + for (ring = 0; ring < adapter->max_sds_rings; ring++) { + sds_ring = &recv_ctx->sds_rings[ring]; + netif_napi_del(&sds_ring->napi); + } + + netxen_free_sds_rings(&adapter->recv_ctx); +} + +static void netxen_napi_enable(struct netxen_adapter *adapter) { int ring; @@ -260,7 +273,7 @@ nx_update_dma_mask(struct netxen_adapter *adapter) change = 0; shift = NXRD32(adapter, CRB_DMA_SHIFT); - if (shift >= 32) + if (shift > 32) return 0; if (NX_IS_REVISION_P3(adapter->ahw.revision_id) && (shift > 9)) @@ -272,7 +285,7 @@ nx_update_dma_mask(struct netxen_adapter *adapter) old_mask = pdev->dma_mask; old_cmask = pdev->dev.coherent_dma_mask; - mask = (1ULL<<(32+shift)) - 1; + mask = DMA_BIT_MASK(32+shift); err = pci_set_dma_mask(pdev, mask); if (err) @@ -880,7 +893,6 @@ netxen_nic_down(struct netxen_adapter *adapter, struct net_device *netdev) spin_unlock(&adapter->tx_clean_lock); del_timer_sync(&adapter->watchdog_timer); - FLUSH_SCHEDULED_WORK(); } @@ -894,10 +906,12 @@ netxen_nic_attach(struct netxen_adapter *adapter) struct nx_host_tx_ring *tx_ring; err = netxen_init_firmware(adapter); - if (err != 0) { - printk(KERN_ERR "Failed to init firmware\n"); - return -EIO; - } + if (err) + return err; + + err = netxen_napi_add(adapter, netdev); + if (err) + return err; if (adapter->fw_major < 4) adapter->max_rds_rings = 3; @@ -961,6 +975,7 @@ netxen_nic_detach(struct netxen_adapter *adapter) netxen_free_hw_resources(adapter); netxen_release_rx_buffers(adapter); netxen_nic_free_irq(adapter); + netxen_napi_del(adapter); netxen_free_sw_resources(adapter); adapter->is_up = 0; @@ -1105,9 +1120,6 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) netdev->irq = adapter->msix_entries[0].vector; - if (netxen_napi_add(adapter, netdev)) - goto err_out_disable_msi; - init_timer(&adapter->watchdog_timer); adapter->watchdog_timer.function = &netxen_watchdog; adapter->watchdog_timer.data = (unsigned long)adapter; @@ -1177,6 +1189,9 @@ static void __devexit netxen_nic_remove(struct pci_dev *pdev) unregister_netdev(netdev); + cancel_work_sync(&adapter->watchdog_task); + cancel_work_sync(&adapter->tx_timeout_task); + if (adapter->is_up == NETXEN_ADAPTER_UP_MAGIC) { netxen_nic_detach(adapter); } @@ -1185,7 +1200,6 @@ static void __devexit netxen_nic_remove(struct pci_dev *pdev) netxen_free_adapter_offload(adapter); netxen_teardown_intr(adapter); - netxen_free_sds_rings(&adapter->recv_ctx); netxen_cleanup_pci_map(adapter); @@ -1211,6 +1225,9 @@ netxen_nic_suspend(struct pci_dev *pdev, pm_message_t state) if (netif_running(netdev)) netxen_nic_down(adapter, netdev); + cancel_work_sync(&adapter->watchdog_task); + cancel_work_sync(&adapter->tx_timeout_task); + if (adapter->is_up == NETXEN_ADAPTER_UP_MAGIC) netxen_nic_detach(adapter); @@ -1549,11 +1566,6 @@ static int netxen_nic_check_temp(struct netxen_adapter *adapter) "%s: Device temperature %d degrees C exceeds" " maximum allowed. Hardware has been shut down.\n", netdev->name, temp_val); - - netif_device_detach(netdev); - netxen_nic_down(adapter, netdev); - netxen_nic_detach(adapter); - rv = 1; } else if (temp_state == NX_TEMP_WARN) { if (adapter->temp == NX_TEMP_NORMAL) { @@ -1587,10 +1599,7 @@ void netxen_advert_link_change(struct netxen_adapter *adapter, int linkup) netif_carrier_off(netdev); netif_stop_queue(netdev); } - - if (!adapter->has_link_events) - netxen_nic_set_link_parameters(adapter); - + adapter->link_changed = !adapter->has_link_events; } else if (!adapter->ahw.linkup && linkup) { printk(KERN_INFO "%s: %s NIC Link is up\n", netxen_nic_driver_name, netdev->name); @@ -1599,9 +1608,7 @@ void netxen_advert_link_change(struct netxen_adapter *adapter, int linkup) netif_carrier_on(netdev); netif_wake_queue(netdev); } - - if (!adapter->has_link_events) - netxen_nic_set_link_parameters(adapter); + adapter->link_changed = !adapter->has_link_events; } } @@ -1628,11 +1635,36 @@ static void netxen_nic_handle_phy_intr(struct netxen_adapter *adapter) netxen_advert_link_change(adapter, linkup); } +static void netxen_nic_thermal_shutdown(struct netxen_adapter *adapter) +{ + struct net_device *netdev = adapter->netdev; + + netif_device_detach(netdev); + netxen_nic_down(adapter, netdev); + netxen_nic_detach(adapter); +} + static void netxen_watchdog(unsigned long v) { struct netxen_adapter *adapter = (struct netxen_adapter *)v; - SCHEDULE_WORK(&adapter->watchdog_task); + if (netxen_nic_check_temp(adapter)) + goto do_sched; + + if (!adapter->has_link_events) { + netxen_nic_handle_phy_intr(adapter); + + if (adapter->link_changed) + goto do_sched; + } + + if (netif_running(adapter->netdev)) + mod_timer(&adapter->watchdog_timer, jiffies + 2 * HZ); + + return; + +do_sched: + schedule_work(&adapter->watchdog_task); } void netxen_watchdog_task(struct work_struct *work) @@ -1640,11 +1672,13 @@ void netxen_watchdog_task(struct work_struct *work) struct netxen_adapter *adapter = container_of(work, struct netxen_adapter, watchdog_task); - if (netxen_nic_check_temp(adapter)) + if (adapter->temp == NX_TEMP_PANIC) { + netxen_nic_thermal_shutdown(adapter); return; + } - if (!adapter->has_link_events) - netxen_nic_handle_phy_intr(adapter); + if (adapter->link_changed) + netxen_nic_set_link_parameters(adapter); if (netif_running(adapter->netdev)) mod_timer(&adapter->watchdog_timer, jiffies + 2 * HZ); @@ -1652,9 +1686,8 @@ void netxen_watchdog_task(struct work_struct *work) static void netxen_tx_timeout(struct net_device *netdev) { - struct netxen_adapter *adapter = (struct netxen_adapter *) - netdev_priv(netdev); - SCHEDULE_WORK(&adapter->tx_timeout_task); + struct netxen_adapter *adapter = netdev_priv(netdev); + schedule_work(&adapter->tx_timeout_task); } static void netxen_tx_timeout_task(struct work_struct *work) @@ -1811,9 +1844,6 @@ static int __init netxen_init_module(void) { printk(KERN_INFO "%s\n", netxen_nic_driver_string); - if ((netxen_workq = create_singlethread_workqueue("netxen")) == NULL) - return -ENOMEM; - return pci_register_driver(&netxen_driver); } @@ -1822,7 +1852,6 @@ module_init(netxen_init_module); static void __exit netxen_exit_module(void) { pci_unregister_driver(&netxen_driver); - destroy_workqueue(netxen_workq); } module_exit(netxen_exit_module); diff --git a/drivers/net/pcnet32.c b/drivers/net/pcnet32.c index a646a44..23e1a07 100644 --- a/drivers/net/pcnet32.c +++ b/drivers/net/pcnet32.c @@ -1839,7 +1839,7 @@ pcnet32_probe1(unsigned long ioaddr, int shared, struct pci_dev *pdev) lp->chip_version = chip_version; lp->msg_enable = pcnet32_debug; if ((cards_found >= MAX_UNITS) - || (options[cards_found] > sizeof(options_mapping))) + || (options[cards_found] >= sizeof(options_mapping))) lp->options = PCNET32_PORT_ASEL; else lp->options = options_mapping[options[cards_found]]; diff --git a/drivers/net/smc91x.c b/drivers/net/smc91x.c index 1c70e99..9da1fa1 100644 --- a/drivers/net/smc91x.c +++ b/drivers/net/smc91x.c @@ -196,21 +196,23 @@ static void PRINT_PKT(u_char *buf, int length) /* this enables an interrupt in the interrupt mask register */ #define SMC_ENABLE_INT(lp, x) do { \ unsigned char mask; \ - spin_lock_irq(&lp->lock); \ + unsigned long smc_enable_flags; \ + spin_lock_irqsave(&lp->lock, smc_enable_flags); \ mask = SMC_GET_INT_MASK(lp); \ mask |= (x); \ SMC_SET_INT_MASK(lp, mask); \ - spin_unlock_irq(&lp->lock); \ + spin_unlock_irqrestore(&lp->lock, smc_enable_flags); \ } while (0) /* this disables an interrupt from the interrupt mask register */ #define SMC_DISABLE_INT(lp, x) do { \ unsigned char mask; \ - spin_lock_irq(&lp->lock); \ + unsigned long smc_disable_flags; \ + spin_lock_irqsave(&lp->lock, smc_disable_flags); \ mask = SMC_GET_INT_MASK(lp); \ mask &= ~(x); \ SMC_SET_INT_MASK(lp, mask); \ - spin_unlock_irq(&lp->lock); \ + spin_unlock_irqrestore(&lp->lock, smc_disable_flags); \ } while (0) /* @@ -520,21 +522,21 @@ static inline void smc_rcv(struct net_device *dev) * any other concurrent access and C would always interrupt B. But life * isn't that easy in a SMP world... */ -#define smc_special_trylock(lock) \ +#define smc_special_trylock(lock, flags) \ ({ \ int __ret; \ - local_irq_disable(); \ + local_irq_save(flags); \ __ret = spin_trylock(lock); \ if (!__ret) \ - local_irq_enable(); \ + local_irq_restore(flags); \ __ret; \ }) -#define smc_special_lock(lock) spin_lock_irq(lock) -#define smc_special_unlock(lock) spin_unlock_irq(lock) +#define smc_special_lock(lock, flags) spin_lock_irq(lock, flags) +#define smc_special_unlock(lock, flags) spin_unlock_irqrestore(lock, flags) #else -#define smc_special_trylock(lock) (1) -#define smc_special_lock(lock) do { } while (0) -#define smc_special_unlock(lock) do { } while (0) +#define smc_special_trylock(lock, flags) (1) +#define smc_special_lock(lock, flags) do { } while (0) +#define smc_special_unlock(lock, flags) do { } while (0) #endif /* @@ -548,10 +550,11 @@ static void smc_hardware_send_pkt(unsigned long data) struct sk_buff *skb; unsigned int packet_no, len; unsigned char *buf; + unsigned long flags; DBG(3, "%s: %s\n", dev->name, __func__); - if (!smc_special_trylock(&lp->lock)) { + if (!smc_special_trylock(&lp->lock, flags)) { netif_stop_queue(dev); tasklet_schedule(&lp->tx_task); return; @@ -559,7 +562,7 @@ static void smc_hardware_send_pkt(unsigned long data) skb = lp->pending_tx_skb; if (unlikely(!skb)) { - smc_special_unlock(&lp->lock); + smc_special_unlock(&lp->lock, flags); return; } lp->pending_tx_skb = NULL; @@ -569,7 +572,7 @@ static void smc_hardware_send_pkt(unsigned long data) printk("%s: Memory allocation failed.\n", dev->name); dev->stats.tx_errors++; dev->stats.tx_fifo_errors++; - smc_special_unlock(&lp->lock); + smc_special_unlock(&lp->lock, flags); goto done; } @@ -608,7 +611,7 @@ static void smc_hardware_send_pkt(unsigned long data) /* queue the packet for TX */ SMC_SET_MMU_CMD(lp, MC_ENQUEUE); - smc_special_unlock(&lp->lock); + smc_special_unlock(&lp->lock, flags); dev->trans_start = jiffies; dev->stats.tx_packets++; @@ -633,6 +636,7 @@ static int smc_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) struct smc_local *lp = netdev_priv(dev); void __iomem *ioaddr = lp->base; unsigned int numPages, poll_count, status; + unsigned long flags; DBG(3, "%s: %s\n", dev->name, __func__); @@ -658,7 +662,7 @@ static int smc_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) return 0; } - smc_special_lock(&lp->lock); + smc_special_lock(&lp->lock, flags); /* now, try to allocate the memory */ SMC_SET_MMU_CMD(lp, MC_ALLOC | numPages); @@ -676,7 +680,7 @@ static int smc_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) } } while (--poll_count); - smc_special_unlock(&lp->lock); + smc_special_unlock(&lp->lock, flags); lp->pending_tx_skb = skb; if (!poll_count) { diff --git a/drivers/net/tulip/tulip_core.c b/drivers/net/tulip/tulip_core.c index 99a6364..4cf9a65 100644 --- a/drivers/net/tulip/tulip_core.c +++ b/drivers/net/tulip/tulip_core.c @@ -652,8 +652,9 @@ tulip_start_xmit(struct sk_buff *skb, struct net_device *dev) int entry; u32 flag; dma_addr_t mapping; + unsigned long flags; - spin_lock_irq(&tp->lock); + spin_lock_irqsave(&tp->lock, flags); /* Calculate the next Tx descriptor entry. */ entry = tp->cur_tx % TX_RING_SIZE; @@ -688,7 +689,7 @@ tulip_start_xmit(struct sk_buff *skb, struct net_device *dev) /* Trigger an immediate transmit demand. */ iowrite32(0, tp->base_addr + CSR1); - spin_unlock_irq(&tp->lock); + spin_unlock_irqrestore(&tp->lock, flags); dev->trans_start = jiffies; diff --git a/drivers/net/tun.c b/drivers/net/tun.c index 027f7ab..42b6c63 100644 --- a/drivers/net/tun.c +++ b/drivers/net/tun.c @@ -1048,20 +1048,15 @@ static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr) return err; } -static int tun_get_iff(struct net *net, struct file *file, struct ifreq *ifr) +static int tun_get_iff(struct net *net, struct tun_struct *tun, + struct ifreq *ifr) { - struct tun_struct *tun = tun_get(file); - - if (!tun) - return -EBADFD; - DBG(KERN_INFO "%s: tun_get_iff\n", tun->dev->name); strcpy(ifr->ifr_name, tun->dev->name); ifr->ifr_flags = tun_flags(tun); - tun_put(tun); return 0; } @@ -1105,8 +1100,8 @@ static int set_offload(struct net_device *dev, unsigned long arg) return 0; } -static int tun_chr_ioctl(struct inode *inode, struct file *file, - unsigned int cmd, unsigned long arg) +static long tun_chr_ioctl(struct file *file, unsigned int cmd, + unsigned long arg) { struct tun_file *tfile = file->private_data; struct tun_struct *tun; @@ -1128,34 +1123,32 @@ static int tun_chr_ioctl(struct inode *inode, struct file *file, (unsigned int __user*)argp); } + rtnl_lock(); + tun = __tun_get(tfile); if (cmd == TUNSETIFF && !tun) { - int err; - ifr.ifr_name[IFNAMSIZ-1] = '\0'; - rtnl_lock(); - err = tun_set_iff(tfile->net, file, &ifr); - rtnl_unlock(); + ret = tun_set_iff(tfile->net, file, &ifr); - if (err) - return err; + if (ret) + goto unlock; if (copy_to_user(argp, &ifr, sizeof(ifr))) - return -EFAULT; - return 0; + ret = -EFAULT; + goto unlock; } - + ret = -EBADFD; if (!tun) - return -EBADFD; + goto unlock; DBG(KERN_INFO "%s: tun_chr_ioctl cmd %d\n", tun->dev->name, cmd); ret = 0; switch (cmd) { case TUNGETIFF: - ret = tun_get_iff(current->nsproxy->net_ns, file, &ifr); + ret = tun_get_iff(current->nsproxy->net_ns, tun, &ifr); if (ret) break; @@ -1201,7 +1194,6 @@ static int tun_chr_ioctl(struct inode *inode, struct file *file, case TUNSETLINK: /* Only allow setting the type when the interface is down */ - rtnl_lock(); if (tun->dev->flags & IFF_UP) { DBG(KERN_INFO "%s: Linktype set failed because interface is up\n", tun->dev->name); @@ -1211,7 +1203,6 @@ static int tun_chr_ioctl(struct inode *inode, struct file *file, DBG(KERN_INFO "%s: linktype set to %d\n", tun->dev->name, tun->dev->type); ret = 0; } - rtnl_unlock(); break; #ifdef TUN_DEBUG @@ -1220,9 +1211,7 @@ static int tun_chr_ioctl(struct inode *inode, struct file *file, break; #endif case TUNSETOFFLOAD: - rtnl_lock(); ret = set_offload(tun->dev, arg); - rtnl_unlock(); break; case TUNSETTXFILTER: @@ -1230,9 +1219,7 @@ static int tun_chr_ioctl(struct inode *inode, struct file *file, ret = -EINVAL; if ((tun->flags & TUN_TYPE_MASK) != TUN_TAP_DEV) break; - rtnl_lock(); ret = update_filter(&tun->txflt, (void __user *)arg); - rtnl_unlock(); break; case SIOCGIFHWADDR: @@ -1248,9 +1235,7 @@ static int tun_chr_ioctl(struct inode *inode, struct file *file, DBG(KERN_DEBUG "%s: set hw address: %pM\n", tun->dev->name, ifr.ifr_hwaddr.sa_data); - rtnl_lock(); ret = dev_set_mac_address(tun->dev, &ifr.ifr_hwaddr); - rtnl_unlock(); break; case TUNGETSNDBUF: @@ -1273,7 +1258,10 @@ static int tun_chr_ioctl(struct inode *inode, struct file *file, break; }; - tun_put(tun); +unlock: + rtnl_unlock(); + if (tun) + tun_put(tun); return ret; } @@ -1361,7 +1349,7 @@ static const struct file_operations tun_fops = { .write = do_sync_write, .aio_write = tun_chr_aio_write, .poll = tun_chr_poll, - .ioctl = tun_chr_ioctl, + .unlocked_ioctl = tun_chr_ioctl, .open = tun_chr_open, .release = tun_chr_close, .fasync = tun_chr_fasync diff --git a/drivers/net/ucc_geth.c b/drivers/net/ucc_geth.c index 3b957e6..8a7b8c7 100644 --- a/drivers/net/ucc_geth.c +++ b/drivers/net/ucc_geth.c @@ -3111,10 +3111,11 @@ static int ucc_geth_start_xmit(struct sk_buff *skb, struct net_device *dev) u8 __iomem *bd; /* BD pointer */ u32 bd_status; u8 txQ = 0; + unsigned long flags; ugeth_vdbg("%s: IN", __func__); - spin_lock_irq(&ugeth->lock); + spin_lock_irqsave(&ugeth->lock, flags); dev->stats.tx_bytes += skb->len; @@ -3171,7 +3172,7 @@ static int ucc_geth_start_xmit(struct sk_buff *skb, struct net_device *dev) uccf = ugeth->uccf; out_be16(uccf->p_utodr, UCC_FAST_TOD); #endif - spin_unlock_irq(&ugeth->lock); + spin_unlock_irqrestore(&ugeth->lock, flags); return 0; } diff --git a/drivers/net/usb/pegasus.h b/drivers/net/usb/pegasus.h index c746782..f968c83 100644 --- a/drivers/net/usb/pegasus.h +++ b/drivers/net/usb/pegasus.h @@ -250,6 +250,8 @@ PEGASUS_DEV( "IO DATA USB ET/TX", VENDOR_IODATA, 0x0904, DEFAULT_GPIO_RESET ) PEGASUS_DEV( "IO DATA USB ET/TX-S", VENDOR_IODATA, 0x0913, DEFAULT_GPIO_RESET | PEGASUS_II ) +PEGASUS_DEV( "IO DATA USB ETX-US2", VENDOR_IODATA, 0x092a, + DEFAULT_GPIO_RESET | PEGASUS_II ) PEGASUS_DEV( "Kingston KNU101TX Ethernet", VENDOR_KINGSTON, 0x000a, DEFAULT_GPIO_RESET) PEGASUS_DEV( "LANEED USB Ethernet LD-USB/TX", VENDOR_LANEED, 0x4002, diff --git a/drivers/net/via-rhine.c b/drivers/net/via-rhine.c index 88c30a5..934f767 100644 --- a/drivers/net/via-rhine.c +++ b/drivers/net/via-rhine.c @@ -1218,6 +1218,7 @@ static int rhine_start_tx(struct sk_buff *skb, struct net_device *dev) struct rhine_private *rp = netdev_priv(dev); void __iomem *ioaddr = rp->base; unsigned entry; + unsigned long flags; /* Caution: the write order is important here, set the field with the "ownership" bits last. */ @@ -1261,7 +1262,7 @@ static int rhine_start_tx(struct sk_buff *skb, struct net_device *dev) cpu_to_le32(TXDESC | (skb->len >= ETH_ZLEN ? skb->len : ETH_ZLEN)); /* lock eth irq */ - spin_lock_irq(&rp->lock); + spin_lock_irqsave(&rp->lock, flags); wmb(); rp->tx_ring[entry].tx_status = cpu_to_le32(DescOwn); wmb(); @@ -1280,7 +1281,7 @@ static int rhine_start_tx(struct sk_buff *skb, struct net_device *dev) dev->trans_start = jiffies; - spin_unlock_irq(&rp->lock); + spin_unlock_irqrestore(&rp->lock, flags); if (debug > 4) { printk(KERN_DEBUG "%s: Transmit frame #%d queued in slot %d.\n", diff --git a/drivers/net/via-velocity.c b/drivers/net/via-velocity.c index 3ba3595..cee08a1 100644 --- a/drivers/net/via-velocity.c +++ b/drivers/net/via-velocity.c @@ -1778,7 +1778,7 @@ static void velocity_error(struct velocity_info *vptr, int status) * mode */ if (vptr->rev_id < REV_ID_VT3216_A0) { - if (vptr->mii_status | VELOCITY_DUPLEX_FULL) + if (vptr->mii_status & VELOCITY_DUPLEX_FULL) BYTE_REG_BITS_ON(TCR_TB2BDIS, ®s->TCR); else BYTE_REG_BITS_OFF(TCR_TB2BDIS, ®s->TCR); diff --git a/drivers/net/wireless/ath/ar9170/main.c b/drivers/net/wireless/ath/ar9170/main.c index 9d38cf6..88c3d85 100644 --- a/drivers/net/wireless/ath/ar9170/main.c +++ b/drivers/net/wireless/ath/ar9170/main.c @@ -1967,13 +1967,14 @@ static int ar9170_conf_tx(struct ieee80211_hw *hw, u16 queue, int ret; mutex_lock(&ar->mutex); - if ((param) && !(queue > __AR9170_NUM_TXQ)) { + if (queue < __AR9170_NUM_TXQ) { memcpy(&ar->edcf[ar9170_qos_hwmap[queue]], param, sizeof(*param)); ret = ar9170_set_qos(ar); - } else + } else { ret = -EINVAL; + } mutex_unlock(&ar->mutex); return ret; diff --git a/drivers/net/wireless/ath/ar9170/usb.c b/drivers/net/wireless/ath/ar9170/usb.c index 754b1f8..007eb85 100644 --- a/drivers/net/wireless/ath/ar9170/usb.c +++ b/drivers/net/wireless/ath/ar9170/usb.c @@ -598,11 +598,15 @@ static int ar9170_usb_request_firmware(struct ar9170_usb *aru) err = request_firmware(&aru->init_values, "ar9170-1.fw", &aru->udev->dev); + if (err) { + dev_err(&aru->udev->dev, "file with init values not found.\n"); + return err; + } err = request_firmware(&aru->firmware, "ar9170-2.fw", &aru->udev->dev); if (err) { release_firmware(aru->init_values); - dev_err(&aru->udev->dev, "file with init values not found.\n"); + dev_err(&aru->udev->dev, "firmware file not found.\n"); return err; } diff --git a/drivers/net/wireless/ipw2x00/ipw2200.c b/drivers/net/wireless/ipw2x00/ipw2200.c index 44c29b3..6dcac73 100644 --- a/drivers/net/wireless/ipw2x00/ipw2200.c +++ b/drivers/net/wireless/ipw2x00/ipw2200.c @@ -6226,7 +6226,7 @@ static void ipw_add_scan_channels(struct ipw_priv *priv, }; u8 channel; - while (channel_index < IPW_SCAN_CHANNELS) { + while (channel_index < IPW_SCAN_CHANNELS - 1) { channel = priv->speed_scan[priv->speed_scan_pos]; if (channel == 0) { diff --git a/drivers/net/wireless/libertas/assoc.c b/drivers/net/wireless/libertas/assoc.c index d699737..b9b3741 100644 --- a/drivers/net/wireless/libertas/assoc.c +++ b/drivers/net/wireless/libertas/assoc.c @@ -1,7 +1,6 @@ /* Copyright (C) 2006, Red Hat, Inc. */ #include <linux/types.h> -#include <linux/kernel.h> #include <linux/etherdevice.h> #include <linux/ieee80211.h> #include <linux/if_arp.h> @@ -44,21 +43,21 @@ static int get_common_rates(struct lbs_private *priv, u16 *rates_size) { u8 *card_rates = lbs_bg_rates; + size_t num_card_rates = sizeof(lbs_bg_rates); int ret = 0, i, j; - u8 tmp[(ARRAY_SIZE(lbs_bg_rates) - 1) * (*rates_size - 1)]; + u8 tmp[30]; size_t tmp_size = 0; /* For each rate in card_rates that exists in rate1, copy to tmp */ - for (i = 0; i < ARRAY_SIZE(lbs_bg_rates) && card_rates[i]; i++) { - for (j = 0; j < *rates_size && rates[j]; j++) { + for (i = 0; card_rates[i] && (i < num_card_rates); i++) { + for (j = 0; rates[j] && (j < *rates_size); j++) { if (rates[j] == card_rates[i]) tmp[tmp_size++] = card_rates[i]; } } lbs_deb_hex(LBS_DEB_JOIN, "AP rates ", rates, *rates_size); - lbs_deb_hex(LBS_DEB_JOIN, "card rates ", card_rates, - ARRAY_SIZE(lbs_bg_rates)); + lbs_deb_hex(LBS_DEB_JOIN, "card rates ", card_rates, num_card_rates); lbs_deb_hex(LBS_DEB_JOIN, "common rates", tmp, tmp_size); lbs_deb_join("TX data rate 0x%02x\n", priv->cur_rate); @@ -70,7 +69,10 @@ static int get_common_rates(struct lbs_private *priv, lbs_pr_alert("Previously set fixed data rate %#x isn't " "compatible with the network.\n", priv->cur_rate); ret = -1; + goto done; } + ret = 0; + done: memset(rates, 0, *rates_size); *rates_size = min_t(int, tmp_size, *rates_size); @@ -320,7 +322,7 @@ static int lbs_associate(struct lbs_private *priv, rates = (struct mrvl_ie_rates_param_set *) pos; rates->header.type = cpu_to_le16(TLV_TYPE_RATES); memcpy(&rates->rates, &bss->rates, MAX_RATES); - tmplen = min_t(u16, ARRAY_SIZE(rates->rates), MAX_RATES); + tmplen = MAX_RATES; if (get_common_rates(priv, rates->rates, &tmplen)) { ret = -1; goto done; @@ -596,7 +598,7 @@ static int lbs_adhoc_join(struct lbs_private *priv, /* Copy Data rates from the rates recorded in scan response */ memset(cmd.bss.rates, 0, sizeof(cmd.bss.rates)); - ratesize = min_t(u16, ARRAY_SIZE(cmd.bss.rates), MAX_RATES); + ratesize = min_t(u16, sizeof(cmd.bss.rates), MAX_RATES); memcpy(cmd.bss.rates, bss->rates, ratesize); if (get_common_rates(priv, cmd.bss.rates, &ratesize)) { lbs_deb_join("ADHOC_JOIN: get_common_rates returned error.\n"); diff --git a/drivers/net/wireless/libertas/hostcmd.h b/drivers/net/wireless/libertas/hostcmd.h index 0a2e291..c8a1998 100644 --- a/drivers/net/wireless/libertas/hostcmd.h +++ b/drivers/net/wireless/libertas/hostcmd.h @@ -56,8 +56,8 @@ struct rxpd { u8 bss_type; /* BSS number */ u8 bss_num; - } bss; - } u; + } __attribute__ ((packed)) bss; + } __attribute__ ((packed)) u; /* SNR */ u8 snr; diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c index a263d5c..83967af 100644 --- a/drivers/net/wireless/mwl8k.c +++ b/drivers/net/wireless/mwl8k.c @@ -261,7 +261,7 @@ struct mwl8k_vif { */ }; -#define MWL8K_VIF(_vif) (struct mwl8k_vif *)(&((_vif)->drv_priv)) +#define MWL8K_VIF(_vif) ((struct mwl8k_vif *)&((_vif)->drv_priv)) static const struct ieee80211_channel mwl8k_channels[] = { { .center_freq = 2412, .hw_value = 1, }, @@ -1012,6 +1012,8 @@ static int rxq_process(struct ieee80211_hw *hw, int index, int limit) rmb(); skb = rxq->rx_skb[rxq->rx_head]; + if (skb == NULL) + break; rxq->rx_skb[rxq->rx_head] = NULL; rxq->rx_head = (rxq->rx_head + 1) % MWL8K_RX_DESCS; @@ -1591,6 +1593,9 @@ static int mwl8k_post_cmd(struct ieee80211_hw *hw, struct mwl8k_cmd_pkt *cmd) timeout = wait_for_completion_timeout(&cmd_wait, msecs_to_jiffies(MWL8K_CMD_TIMEOUT_MS)); + pci_unmap_single(priv->pdev, dma_addr, dma_size, + PCI_DMA_BIDIRECTIONAL); + result = &cmd->result; if (!timeout) { spin_lock_irq(&priv->fw_lock); @@ -1610,8 +1615,6 @@ static int mwl8k_post_cmd(struct ieee80211_hw *hw, struct mwl8k_cmd_pkt *cmd) *result); } - pci_unmap_single(priv->pdev, dma_addr, dma_size, - PCI_DMA_BIDIRECTIONAL); return rc; } @@ -1654,18 +1657,18 @@ static int mwl8k_cmd_get_hw_spec(struct ieee80211_hw *hw) memset(cmd->perm_addr, 0xff, sizeof(cmd->perm_addr)); cmd->ps_cookie = cpu_to_le32(priv->cookie_dma); cmd->rx_queue_ptr = cpu_to_le32(priv->rxq[0].rx_desc_dma); - cmd->num_tx_queues = MWL8K_TX_QUEUES; + cmd->num_tx_queues = cpu_to_le32(MWL8K_TX_QUEUES); for (i = 0; i < MWL8K_TX_QUEUES; i++) cmd->tx_queue_ptrs[i] = cpu_to_le32(priv->txq[i].tx_desc_dma); - cmd->num_tx_desc_per_queue = MWL8K_TX_DESCS; - cmd->total_rx_desc = MWL8K_RX_DESCS; + cmd->num_tx_desc_per_queue = cpu_to_le32(MWL8K_TX_DESCS); + cmd->total_rx_desc = cpu_to_le32(MWL8K_RX_DESCS); rc = mwl8k_post_cmd(hw, &cmd->header); if (!rc) { SET_IEEE80211_PERM_ADDR(hw, cmd->perm_addr); priv->num_mcaddrs = le16_to_cpu(cmd->num_mcaddrs); - priv->fw_rev = cmd->fw_rev; + priv->fw_rev = le32_to_cpu(cmd->fw_rev); priv->hw_rev = cmd->hw_rev; priv->region_code = le16_to_cpu(cmd->region_code); } @@ -3216,15 +3219,19 @@ static int mwl8k_configure_filter_wt(struct work_struct *wt) struct dev_addr_list *mclist = worker->mclist; struct mwl8k_priv *priv = hw->priv; - struct mwl8k_vif *mv_vif; int rc = 0; if (changed_flags & FIF_BCN_PRBRESP_PROMISC) { if (*total_flags & FIF_BCN_PRBRESP_PROMISC) rc = mwl8k_cmd_set_pre_scan(hw); else { - mv_vif = MWL8K_VIF(priv->vif); - rc = mwl8k_cmd_set_post_scan(hw, mv_vif->bssid); + u8 *bssid; + + bssid = "\x00\x00\x00\x00\x00\x00"; + if (priv->vif != NULL) + bssid = MWL8K_VIF(priv->vif)->bssid; + + rc = mwl8k_cmd_set_post_scan(hw, bssid); } } @@ -3726,6 +3733,8 @@ static void __devexit mwl8k_remove(struct pci_dev *pdev) ieee80211_stop_queues(hw); + ieee80211_unregister_hw(hw); + /* Remove tx reclaim tasklet */ tasklet_kill(&priv->tx_reclaim_task); @@ -3739,8 +3748,6 @@ static void __devexit mwl8k_remove(struct pci_dev *pdev) for (i = 0; i < MWL8K_TX_QUEUES; i++) mwl8k_txq_reclaim(hw, i, 1); - ieee80211_unregister_hw(hw); - for (i = 0; i < MWL8K_TX_QUEUES; i++) mwl8k_txq_deinit(hw, i); diff --git a/drivers/net/wireless/orinoco/hw.c b/drivers/net/wireless/orinoco/hw.c index 632fac8..b394627 100644 --- a/drivers/net/wireless/orinoco/hw.c +++ b/drivers/net/wireless/orinoco/hw.c @@ -70,7 +70,7 @@ int orinoco_hw_get_tkip_iv(struct orinoco_private *priv, int key, u8 *tsc) int err = 0; u8 tsc_arr[4][IW_ENCODE_SEQ_MAX_SIZE]; - if ((key < 0) || (key > 4)) + if ((key < 0) || (key >= 4)) return -EINVAL; err = hermes_read_ltv(hw, USER_BAP, HERMES_RID_CURRENT_TKIP_IV, diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h index a498dde..49c9e2c 100644 --- a/drivers/net/wireless/rt2x00/rt2x00.h +++ b/drivers/net/wireless/rt2x00/rt2x00.h @@ -849,13 +849,15 @@ struct rt2x00_dev { static inline void rt2x00_rf_read(struct rt2x00_dev *rt2x00dev, const unsigned int word, u32 *data) { - *data = rt2x00dev->rf[word]; + BUG_ON(word < 1 || word > rt2x00dev->ops->rf_size / sizeof(u32)); + *data = rt2x00dev->rf[word - 1]; } static inline void rt2x00_rf_write(struct rt2x00_dev *rt2x00dev, const unsigned int word, u32 data) { - rt2x00dev->rf[word] = data; + BUG_ON(word < 1 || word > rt2x00dev->ops->rf_size / sizeof(u32)); + rt2x00dev->rf[word - 1] = data; } /* diff --git a/drivers/net/wireless/rtl818x/rtl8187_dev.c b/drivers/net/wireless/rtl818x/rtl8187_dev.c index 294250e..87a9558 100644 --- a/drivers/net/wireless/rtl818x/rtl8187_dev.c +++ b/drivers/net/wireless/rtl818x/rtl8187_dev.c @@ -869,6 +869,9 @@ static int rtl8187b_init_hw(struct ieee80211_hw *dev) priv->aifsn[3] = 3; /* AIFSN[AC_BE] */ rtl818x_iowrite8(priv, &priv->map->ACM_CONTROL, 0); + /* ENEDCA flag must always be set, transmit issues? */ + rtl818x_iowrite8(priv, &priv->map->MSR, RTL818X_MSR_ENEDCA); + return 0; } @@ -1173,13 +1176,16 @@ static void rtl8187_bss_info_changed(struct ieee80211_hw *dev, rtl818x_iowrite8(priv, &priv->map->BSSID[i], info->bssid[i]); + if (priv->is_rtl8187b) + reg = RTL818X_MSR_ENEDCA; + else + reg = 0; + if (is_valid_ether_addr(info->bssid)) { - reg = RTL818X_MSR_INFRA; - if (priv->is_rtl8187b) - reg |= RTL818X_MSR_ENEDCA; + reg |= RTL818X_MSR_INFRA; rtl818x_iowrite8(priv, &priv->map->MSR, reg); } else { - reg = RTL818X_MSR_NO_LINK; + reg |= RTL818X_MSR_NO_LINK; rtl818x_iowrite8(priv, &priv->map->MSR, reg); } diff --git a/drivers/net/yellowfin.c b/drivers/net/yellowfin.c index a075801..c2fd618 100644 --- a/drivers/net/yellowfin.c +++ b/drivers/net/yellowfin.c @@ -346,7 +346,7 @@ static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd); static int yellowfin_open(struct net_device *dev); static void yellowfin_timer(unsigned long data); static void yellowfin_tx_timeout(struct net_device *dev); -static void yellowfin_init_ring(struct net_device *dev); +static int yellowfin_init_ring(struct net_device *dev); static int yellowfin_start_xmit(struct sk_buff *skb, struct net_device *dev); static irqreturn_t yellowfin_interrupt(int irq, void *dev_instance); static int yellowfin_rx(struct net_device *dev); @@ -573,19 +573,24 @@ static int yellowfin_open(struct net_device *dev) { struct yellowfin_private *yp = netdev_priv(dev); void __iomem *ioaddr = yp->base; - int i; + int i, ret; /* Reset the chip. */ iowrite32(0x80000000, ioaddr + DMACtrl); - i = request_irq(dev->irq, &yellowfin_interrupt, IRQF_SHARED, dev->name, dev); - if (i) return i; + ret = request_irq(dev->irq, &yellowfin_interrupt, IRQF_SHARED, dev->name, dev); + if (ret) + return ret; if (yellowfin_debug > 1) printk(KERN_DEBUG "%s: yellowfin_open() irq %d.\n", dev->name, dev->irq); - yellowfin_init_ring(dev); + ret = yellowfin_init_ring(dev); + if (ret) { + free_irq(dev->irq, dev); + return ret; + } iowrite32(yp->rx_ring_dma, ioaddr + RxPtr); iowrite32(yp->tx_ring_dma, ioaddr + TxPtr); @@ -725,10 +730,10 @@ static void yellowfin_tx_timeout(struct net_device *dev) } /* Initialize the Rx and Tx rings, along with various 'dev' bits. */ -static void yellowfin_init_ring(struct net_device *dev) +static int yellowfin_init_ring(struct net_device *dev) { struct yellowfin_private *yp = netdev_priv(dev); - int i; + int i, j; yp->tx_full = 0; yp->cur_rx = yp->cur_tx = 0; @@ -753,6 +758,11 @@ static void yellowfin_init_ring(struct net_device *dev) yp->rx_ring[i].addr = cpu_to_le32(pci_map_single(yp->pci_dev, skb->data, yp->rx_buf_sz, PCI_DMA_FROMDEVICE)); } + if (i != RX_RING_SIZE) { + for (j = 0; j < i; j++) + dev_kfree_skb(yp->rx_skbuff[j]); + return -ENOMEM; + } yp->rx_ring[i-1].dbdma_cmd = cpu_to_le32(CMD_STOP); yp->dirty_rx = (unsigned int)(i - RX_RING_SIZE); @@ -769,8 +779,6 @@ static void yellowfin_init_ring(struct net_device *dev) yp->tx_ring[--i].dbdma_cmd = cpu_to_le32(CMD_STOP | BRANCH_ALWAYS); #else { - int j; - /* Tx ring needs a pair of descriptors, the second for the status. */ for (i = 0; i < TX_RING_SIZE; i++) { j = 2*i; @@ -805,7 +813,7 @@ static void yellowfin_init_ring(struct net_device *dev) } #endif yp->tx_tail_desc = &yp->tx_status[0]; - return; + return 0; } static int yellowfin_start_xmit(struct sk_buff *skb, struct net_device *dev) diff --git a/drivers/net/zorro8390.c b/drivers/net/zorro8390.c index 37c84e3..81c753a 100644 --- a/drivers/net/zorro8390.c +++ b/drivers/net/zorro8390.c @@ -120,6 +120,9 @@ static int __devinit zorro8390_init_one(struct zorro_dev *z, for (i = ARRAY_SIZE(cards)-1; i >= 0; i--) if (z->id == cards[i].id) break; + if (i < 0) + return -ENODEV; + board = z->resource.start; ioaddr = board+cards[i].offset; dev = alloc_ei_netdev(); diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c index d76c4c8..f99bc7f 100644 --- a/drivers/pci/pci-driver.c +++ b/drivers/pci/pci-driver.c @@ -508,7 +508,7 @@ static int pci_restore_standard_config(struct pci_dev *pci_dev) return error; } - return pci_dev->state_saved ? pci_restore_state(pci_dev) : 0; + return pci_restore_state(pci_dev); } static void pci_pm_default_resume_noirq(struct pci_dev *pci_dev) diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index dbd0f94..7b70312 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -846,6 +846,8 @@ pci_restore_state(struct pci_dev *dev) int i; u32 val; + if (!dev->state_saved) + return 0; /* PCI Express register must be restored first */ pci_restore_pcie_state(dev); diff --git a/drivers/s390/block/dasd.c b/drivers/s390/block/dasd.c index 7498366..3f62dd5 100644 --- a/drivers/s390/block/dasd.c +++ b/drivers/s390/block/dasd.c @@ -2135,9 +2135,9 @@ static int dasd_getgeo(struct block_device *bdev, struct hd_geometry *geo) struct dasd_device *base; block = bdev->bd_disk->private_data; - base = block->base; if (!block) return -ENODEV; + base = block->base; if (!base->discipline || !base->discipline->fill_geometry) diff --git a/drivers/s390/cio/device.c b/drivers/s390/cio/device.c index 3c57c1a..d593bc7 100644 --- a/drivers/s390/cio/device.c +++ b/drivers/s390/cio/device.c @@ -772,10 +772,8 @@ static struct ccw_device * io_subchannel_create_ccwdev(struct subchannel *sch) cdev = io_subchannel_allocate_dev(sch); if (!IS_ERR(cdev)) { ret = io_subchannel_initialize_dev(sch, cdev); - if (ret) { - kfree(cdev); + if (ret) cdev = ERR_PTR(ret); - } } return cdev; } diff --git a/drivers/scsi/mpt2sas/mpt2sas_base.c b/drivers/scsi/mpt2sas/mpt2sas_base.c index f3da592..35a1386 100644 --- a/drivers/scsi/mpt2sas/mpt2sas_base.c +++ b/drivers/scsi/mpt2sas/mpt2sas_base.c @@ -119,6 +119,64 @@ _base_fault_reset_work(struct work_struct *work) spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags); } +/** + * mpt2sas_base_start_watchdog - start the fault_reset_work_q + * @ioc: pointer to scsi command object + * Context: sleep. + * + * Return nothing. + */ +void +mpt2sas_base_start_watchdog(struct MPT2SAS_ADAPTER *ioc) +{ + unsigned long flags; + + if (ioc->fault_reset_work_q) + return; + + /* initialize fault polling */ + INIT_DELAYED_WORK(&ioc->fault_reset_work, _base_fault_reset_work); + snprintf(ioc->fault_reset_work_q_name, + sizeof(ioc->fault_reset_work_q_name), "poll_%d_status", ioc->id); + ioc->fault_reset_work_q = + create_singlethread_workqueue(ioc->fault_reset_work_q_name); + if (!ioc->fault_reset_work_q) { + printk(MPT2SAS_ERR_FMT "%s: failed (line=%d)\n", + ioc->name, __func__, __LINE__); + return; + } + spin_lock_irqsave(&ioc->ioc_reset_in_progress_lock, flags); + if (ioc->fault_reset_work_q) + queue_delayed_work(ioc->fault_reset_work_q, + &ioc->fault_reset_work, + msecs_to_jiffies(FAULT_POLLING_INTERVAL)); + spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags); +} + +/** + * mpt2sas_base_stop_watchdog - stop the fault_reset_work_q + * @ioc: pointer to scsi command object + * Context: sleep. + * + * Return nothing. + */ +void +mpt2sas_base_stop_watchdog(struct MPT2SAS_ADAPTER *ioc) +{ + unsigned long flags; + struct workqueue_struct *wq; + + spin_lock_irqsave(&ioc->ioc_reset_in_progress_lock, flags); + wq = ioc->fault_reset_work_q; + ioc->fault_reset_work_q = NULL; + spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags); + if (wq) { + if (!cancel_delayed_work(&ioc->fault_reset_work)) + flush_workqueue(wq); + destroy_workqueue(wq); + } +} + #ifdef CONFIG_SCSI_MPT2SAS_LOGGING /** * _base_sas_ioc_info - verbose translation of the ioc status @@ -440,6 +498,10 @@ _base_sas_log_info(struct MPT2SAS_ADAPTER *ioc , u32 log_info) if (sas_loginfo.dw.bus_type != 3 /*SAS*/) return; + /* each nexus loss loginfo */ + if (log_info == 0x31170000) + return; + /* eat the loginfos associated with task aborts */ if (ioc->ignore_loginfos && (log_info == 30050000 || log_info == 0x31140000 || log_info == 0x31130000)) @@ -1109,7 +1171,6 @@ mpt2sas_base_map_resources(struct MPT2SAS_ADAPTER *ioc) } } - pci_set_drvdata(pdev, ioc->shost); _base_mask_interrupts(ioc); r = _base_enable_msix(ioc); if (r) @@ -1132,7 +1193,6 @@ mpt2sas_base_map_resources(struct MPT2SAS_ADAPTER *ioc) ioc->pci_irq = -1; pci_release_selected_regions(ioc->pdev, ioc->bars); pci_disable_device(pdev); - pci_set_drvdata(pdev, NULL); return r; } @@ -3191,7 +3251,6 @@ mpt2sas_base_free_resources(struct MPT2SAS_ADAPTER *ioc) ioc->chip_phys = 0; pci_release_selected_regions(ioc->pdev, ioc->bars); pci_disable_device(pdev); - pci_set_drvdata(pdev, NULL); return; } @@ -3205,7 +3264,6 @@ int mpt2sas_base_attach(struct MPT2SAS_ADAPTER *ioc) { int r, i; - unsigned long flags; dinitprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s\n", ioc->name, __func__)); @@ -3214,6 +3272,7 @@ mpt2sas_base_attach(struct MPT2SAS_ADAPTER *ioc) if (r) return r; + pci_set_drvdata(ioc->pdev, ioc->shost); r = _base_make_ioc_ready(ioc, CAN_SLEEP, SOFT_RESET); if (r) goto out_free_resources; @@ -3288,23 +3347,7 @@ mpt2sas_base_attach(struct MPT2SAS_ADAPTER *ioc) if (r) goto out_free_resources; - /* initialize fault polling */ - INIT_DELAYED_WORK(&ioc->fault_reset_work, _base_fault_reset_work); - snprintf(ioc->fault_reset_work_q_name, - sizeof(ioc->fault_reset_work_q_name), "poll_%d_status", ioc->id); - ioc->fault_reset_work_q = - create_singlethread_workqueue(ioc->fault_reset_work_q_name); - if (!ioc->fault_reset_work_q) { - printk(MPT2SAS_ERR_FMT "%s: failed (line=%d)\n", - ioc->name, __func__, __LINE__); - goto out_free_resources; - } - spin_lock_irqsave(&ioc->ioc_reset_in_progress_lock, flags); - if (ioc->fault_reset_work_q) - queue_delayed_work(ioc->fault_reset_work_q, - &ioc->fault_reset_work, - msecs_to_jiffies(FAULT_POLLING_INTERVAL)); - spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags); + mpt2sas_base_start_watchdog(ioc); return 0; out_free_resources: @@ -3312,6 +3355,7 @@ mpt2sas_base_attach(struct MPT2SAS_ADAPTER *ioc) ioc->remove_host = 1; mpt2sas_base_free_resources(ioc); _base_release_memory_pools(ioc); + pci_set_drvdata(ioc->pdev, NULL); kfree(ioc->tm_cmds.reply); kfree(ioc->transport_cmds.reply); kfree(ioc->config_cmds.reply); @@ -3337,22 +3381,14 @@ mpt2sas_base_attach(struct MPT2SAS_ADAPTER *ioc) void mpt2sas_base_detach(struct MPT2SAS_ADAPTER *ioc) { - unsigned long flags; - struct workqueue_struct *wq; dexitprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s\n", ioc->name, __func__)); - spin_lock_irqsave(&ioc->ioc_reset_in_progress_lock, flags); - wq = ioc->fault_reset_work_q; - ioc->fault_reset_work_q = NULL; - spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags); - if (!cancel_delayed_work(&ioc->fault_reset_work)) - flush_workqueue(wq); - destroy_workqueue(wq); - + mpt2sas_base_stop_watchdog(ioc); mpt2sas_base_free_resources(ioc); _base_release_memory_pools(ioc); + pci_set_drvdata(ioc->pdev, NULL); kfree(ioc->pfacts); kfree(ioc->ctl_cmds.reply); kfree(ioc->base_cmds.reply); diff --git a/drivers/scsi/mpt2sas/mpt2sas_base.h b/drivers/scsi/mpt2sas/mpt2sas_base.h index 286c185..acdcff1 100644 --- a/drivers/scsi/mpt2sas/mpt2sas_base.h +++ b/drivers/scsi/mpt2sas/mpt2sas_base.h @@ -69,10 +69,10 @@ #define MPT2SAS_DRIVER_NAME "mpt2sas" #define MPT2SAS_AUTHOR "LSI Corporation <DL-MPTFusionLinux@lsi.com>" #define MPT2SAS_DESCRIPTION "LSI MPT Fusion SAS 2.0 Device Driver" -#define MPT2SAS_DRIVER_VERSION "01.100.03.00" +#define MPT2SAS_DRIVER_VERSION "01.100.04.00" #define MPT2SAS_MAJOR_VERSION 01 #define MPT2SAS_MINOR_VERSION 100 -#define MPT2SAS_BUILD_VERSION 03 +#define MPT2SAS_BUILD_VERSION 04 #define MPT2SAS_RELEASE_VERSION 00 /* @@ -673,6 +673,8 @@ typedef void (*MPT_CALLBACK)(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 VF_ID, /* base shared API */ extern struct list_head mpt2sas_ioc_list; +void mpt2sas_base_start_watchdog(struct MPT2SAS_ADAPTER *ioc); +void mpt2sas_base_stop_watchdog(struct MPT2SAS_ADAPTER *ioc); int mpt2sas_base_attach(struct MPT2SAS_ADAPTER *ioc); void mpt2sas_base_detach(struct MPT2SAS_ADAPTER *ioc); diff --git a/drivers/scsi/mpt2sas/mpt2sas_config.c b/drivers/scsi/mpt2sas/mpt2sas_config.c index 58cfb97..6ddee16 100644 --- a/drivers/scsi/mpt2sas/mpt2sas_config.c +++ b/drivers/scsi/mpt2sas/mpt2sas_config.c @@ -236,17 +236,25 @@ _config_request(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigRequest_t Mpi2ConfigRequest_t *config_request; int r; u8 retry_count; - u8 issue_reset; + u8 issue_host_reset = 0; u16 wait_state_count; + mutex_lock(&ioc->config_cmds.mutex); if (ioc->config_cmds.status != MPT2_CMD_NOT_USED) { printk(MPT2SAS_ERR_FMT "%s: config_cmd in use\n", ioc->name, __func__); + mutex_unlock(&ioc->config_cmds.mutex); return -EAGAIN; } retry_count = 0; retry_config: + if (retry_count) { + if (retry_count > 2) /* attempt only 2 retries */ + return -EFAULT; + printk(MPT2SAS_INFO_FMT "%s: attempting retry (%d)\n", + ioc->name, __func__, retry_count); + } wait_state_count = 0; ioc_state = mpt2sas_base_get_iocstate(ioc, 1); while (ioc_state != MPI2_IOC_STATE_OPERATIONAL) { @@ -254,8 +262,8 @@ _config_request(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigRequest_t printk(MPT2SAS_ERR_FMT "%s: failed due to ioc not operational\n", ioc->name, __func__); - ioc->config_cmds.status = MPT2_CMD_NOT_USED; - return -EFAULT; + r = -EFAULT; + goto out; } ssleep(1); ioc_state = mpt2sas_base_get_iocstate(ioc, 1); @@ -271,8 +279,8 @@ _config_request(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigRequest_t if (!smid) { printk(MPT2SAS_ERR_FMT "%s: failed obtaining a smid\n", ioc->name, __func__); - ioc->config_cmds.status = MPT2_CMD_NOT_USED; - return -EAGAIN; + r = -EAGAIN; + goto out; } r = 0; @@ -292,9 +300,15 @@ _config_request(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigRequest_t ioc->name, __func__); _debug_dump_mf(mpi_request, sizeof(Mpi2ConfigRequest_t)/4); - if (!(ioc->config_cmds.status & MPT2_CMD_RESET)) - issue_reset = 1; - goto issue_host_reset; + retry_count++; + if (ioc->config_cmds.smid == smid) + mpt2sas_base_free_smid(ioc, smid); + if ((ioc->shost_recovery) || + (ioc->config_cmds.status & MPT2_CMD_RESET)) + goto retry_config; + issue_host_reset = 1; + r = -EFAULT; + goto out; } if (ioc->config_cmds.status & MPT2_CMD_REPLY_VALID) memcpy(mpi_reply, ioc->config_cmds.reply, @@ -302,21 +316,13 @@ _config_request(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigRequest_t if (retry_count) printk(MPT2SAS_INFO_FMT "%s: retry completed!!\n", ioc->name, __func__); +out: ioc->config_cmds.status = MPT2_CMD_NOT_USED; - return r; - - issue_host_reset: - if (issue_reset) + mutex_unlock(&ioc->config_cmds.mutex); + if (issue_host_reset) mpt2sas_base_hard_reset_handler(ioc, CAN_SLEEP, FORCE_BIG_HAMMER); - ioc->config_cmds.status = MPT2_CMD_NOT_USED; - if (!retry_count) { - printk(MPT2SAS_INFO_FMT "%s: attempting retry\n", - ioc->name, __func__); - retry_count++; - goto retry_config; - } - return -EFAULT; + return r; } /** @@ -375,7 +381,6 @@ mpt2sas_config_get_manufacturing_pg0(struct MPT2SAS_ADAPTER *ioc, int r; struct config_request mem; - mutex_lock(&ioc->config_cmds.mutex); memset(config_page, 0, sizeof(Mpi2ManufacturingPage0_t)); memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); mpi_request.Function = MPI2_FUNCTION_CONFIG; @@ -417,7 +422,6 @@ mpt2sas_config_get_manufacturing_pg0(struct MPT2SAS_ADAPTER *ioc, _config_free_config_dma_memory(ioc, &mem); out: - mutex_unlock(&ioc->config_cmds.mutex); return r; } @@ -438,7 +442,6 @@ mpt2sas_config_get_bios_pg2(struct MPT2SAS_ADAPTER *ioc, int r; struct config_request mem; - mutex_lock(&ioc->config_cmds.mutex); memset(config_page, 0, sizeof(Mpi2BiosPage2_t)); memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); mpi_request.Function = MPI2_FUNCTION_CONFIG; @@ -480,7 +483,6 @@ mpt2sas_config_get_bios_pg2(struct MPT2SAS_ADAPTER *ioc, _config_free_config_dma_memory(ioc, &mem); out: - mutex_unlock(&ioc->config_cmds.mutex); return r; } @@ -501,7 +503,6 @@ mpt2sas_config_get_bios_pg3(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t int r; struct config_request mem; - mutex_lock(&ioc->config_cmds.mutex); memset(config_page, 0, sizeof(Mpi2BiosPage3_t)); memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); mpi_request.Function = MPI2_FUNCTION_CONFIG; @@ -543,7 +544,6 @@ mpt2sas_config_get_bios_pg3(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t _config_free_config_dma_memory(ioc, &mem); out: - mutex_unlock(&ioc->config_cmds.mutex); return r; } @@ -564,7 +564,6 @@ mpt2sas_config_get_iounit_pg0(struct MPT2SAS_ADAPTER *ioc, int r; struct config_request mem; - mutex_lock(&ioc->config_cmds.mutex); memset(config_page, 0, sizeof(Mpi2IOUnitPage0_t)); memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); mpi_request.Function = MPI2_FUNCTION_CONFIG; @@ -606,7 +605,6 @@ mpt2sas_config_get_iounit_pg0(struct MPT2SAS_ADAPTER *ioc, _config_free_config_dma_memory(ioc, &mem); out: - mutex_unlock(&ioc->config_cmds.mutex); return r; } @@ -627,7 +625,6 @@ mpt2sas_config_get_iounit_pg1(struct MPT2SAS_ADAPTER *ioc, int r; struct config_request mem; - mutex_lock(&ioc->config_cmds.mutex); memset(config_page, 0, sizeof(Mpi2IOUnitPage1_t)); memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); mpi_request.Function = MPI2_FUNCTION_CONFIG; @@ -669,7 +666,6 @@ mpt2sas_config_get_iounit_pg1(struct MPT2SAS_ADAPTER *ioc, _config_free_config_dma_memory(ioc, &mem); out: - mutex_unlock(&ioc->config_cmds.mutex); return r; } @@ -690,7 +686,6 @@ mpt2sas_config_set_iounit_pg1(struct MPT2SAS_ADAPTER *ioc, int r; struct config_request mem; - mutex_lock(&ioc->config_cmds.mutex); memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); mpi_request.Function = MPI2_FUNCTION_CONFIG; mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; @@ -732,7 +727,6 @@ mpt2sas_config_set_iounit_pg1(struct MPT2SAS_ADAPTER *ioc, _config_free_config_dma_memory(ioc, &mem); out: - mutex_unlock(&ioc->config_cmds.mutex); return r; } @@ -753,7 +747,6 @@ mpt2sas_config_get_ioc_pg8(struct MPT2SAS_ADAPTER *ioc, int r; struct config_request mem; - mutex_lock(&ioc->config_cmds.mutex); memset(config_page, 0, sizeof(Mpi2IOCPage8_t)); memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); mpi_request.Function = MPI2_FUNCTION_CONFIG; @@ -795,7 +788,6 @@ mpt2sas_config_get_ioc_pg8(struct MPT2SAS_ADAPTER *ioc, _config_free_config_dma_memory(ioc, &mem); out: - mutex_unlock(&ioc->config_cmds.mutex); return r; } @@ -818,7 +810,6 @@ mpt2sas_config_get_sas_device_pg0(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t int r; struct config_request mem; - mutex_lock(&ioc->config_cmds.mutex); memset(config_page, 0, sizeof(Mpi2SasDevicePage0_t)); memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); mpi_request.Function = MPI2_FUNCTION_CONFIG; @@ -863,7 +854,6 @@ mpt2sas_config_get_sas_device_pg0(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t _config_free_config_dma_memory(ioc, &mem); out: - mutex_unlock(&ioc->config_cmds.mutex); return r; } @@ -886,7 +876,6 @@ mpt2sas_config_get_sas_device_pg1(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t int r; struct config_request mem; - mutex_lock(&ioc->config_cmds.mutex); memset(config_page, 0, sizeof(Mpi2SasDevicePage1_t)); memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); mpi_request.Function = MPI2_FUNCTION_CONFIG; @@ -931,7 +920,6 @@ mpt2sas_config_get_sas_device_pg1(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t _config_free_config_dma_memory(ioc, &mem); out: - mutex_unlock(&ioc->config_cmds.mutex); return r; } @@ -953,7 +941,6 @@ mpt2sas_config_get_number_hba_phys(struct MPT2SAS_ADAPTER *ioc, u8 *num_phys) Mpi2ConfigReply_t mpi_reply; Mpi2SasIOUnitPage0_t config_page; - mutex_lock(&ioc->config_cmds.mutex); memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); mpi_request.Function = MPI2_FUNCTION_CONFIG; mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; @@ -1002,7 +989,6 @@ mpt2sas_config_get_number_hba_phys(struct MPT2SAS_ADAPTER *ioc, u8 *num_phys) _config_free_config_dma_memory(ioc, &mem); out: - mutex_unlock(&ioc->config_cmds.mutex); return r; } @@ -1026,8 +1012,6 @@ mpt2sas_config_get_sas_iounit_pg0(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t Mpi2ConfigRequest_t mpi_request; int r; struct config_request mem; - - mutex_lock(&ioc->config_cmds.mutex); memset(config_page, 0, sz); memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); mpi_request.Function = MPI2_FUNCTION_CONFIG; @@ -1070,7 +1054,6 @@ mpt2sas_config_get_sas_iounit_pg0(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t _config_free_config_dma_memory(ioc, &mem); out: - mutex_unlock(&ioc->config_cmds.mutex); return r; } @@ -1095,7 +1078,6 @@ mpt2sas_config_get_sas_iounit_pg1(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t int r; struct config_request mem; - mutex_lock(&ioc->config_cmds.mutex); memset(config_page, 0, sz); memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); mpi_request.Function = MPI2_FUNCTION_CONFIG; @@ -1138,7 +1120,6 @@ mpt2sas_config_get_sas_iounit_pg1(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t _config_free_config_dma_memory(ioc, &mem); out: - mutex_unlock(&ioc->config_cmds.mutex); return r; } @@ -1161,7 +1142,6 @@ mpt2sas_config_get_expander_pg0(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t int r; struct config_request mem; - mutex_lock(&ioc->config_cmds.mutex); memset(config_page, 0, sizeof(Mpi2ExpanderPage0_t)); memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); mpi_request.Function = MPI2_FUNCTION_CONFIG; @@ -1206,7 +1186,6 @@ mpt2sas_config_get_expander_pg0(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t _config_free_config_dma_memory(ioc, &mem); out: - mutex_unlock(&ioc->config_cmds.mutex); return r; } @@ -1230,7 +1209,6 @@ mpt2sas_config_get_expander_pg1(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t int r; struct config_request mem; - mutex_lock(&ioc->config_cmds.mutex); memset(config_page, 0, sizeof(Mpi2ExpanderPage1_t)); memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); mpi_request.Function = MPI2_FUNCTION_CONFIG; @@ -1277,7 +1255,6 @@ mpt2sas_config_get_expander_pg1(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t _config_free_config_dma_memory(ioc, &mem); out: - mutex_unlock(&ioc->config_cmds.mutex); return r; } @@ -1300,7 +1277,6 @@ mpt2sas_config_get_enclosure_pg0(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t int r; struct config_request mem; - mutex_lock(&ioc->config_cmds.mutex); memset(config_page, 0, sizeof(Mpi2SasEnclosurePage0_t)); memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); mpi_request.Function = MPI2_FUNCTION_CONFIG; @@ -1345,7 +1321,6 @@ mpt2sas_config_get_enclosure_pg0(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t _config_free_config_dma_memory(ioc, &mem); out: - mutex_unlock(&ioc->config_cmds.mutex); return r; } @@ -1367,7 +1342,6 @@ mpt2sas_config_get_phy_pg0(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t int r; struct config_request mem; - mutex_lock(&ioc->config_cmds.mutex); memset(config_page, 0, sizeof(Mpi2SasPhyPage0_t)); memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); mpi_request.Function = MPI2_FUNCTION_CONFIG; @@ -1413,7 +1387,6 @@ mpt2sas_config_get_phy_pg0(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t _config_free_config_dma_memory(ioc, &mem); out: - mutex_unlock(&ioc->config_cmds.mutex); return r; } @@ -1435,7 +1408,6 @@ mpt2sas_config_get_phy_pg1(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t int r; struct config_request mem; - mutex_lock(&ioc->config_cmds.mutex); memset(config_page, 0, sizeof(Mpi2SasPhyPage1_t)); memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); mpi_request.Function = MPI2_FUNCTION_CONFIG; @@ -1481,7 +1453,6 @@ mpt2sas_config_get_phy_pg1(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t _config_free_config_dma_memory(ioc, &mem); out: - mutex_unlock(&ioc->config_cmds.mutex); return r; } @@ -1505,7 +1476,6 @@ mpt2sas_config_get_raid_volume_pg1(struct MPT2SAS_ADAPTER *ioc, int r; struct config_request mem; - mutex_lock(&ioc->config_cmds.mutex); memset(config_page, 0, sizeof(Mpi2RaidVolPage1_t)); memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); mpi_request.Function = MPI2_FUNCTION_CONFIG; @@ -1548,7 +1518,6 @@ mpt2sas_config_get_raid_volume_pg1(struct MPT2SAS_ADAPTER *ioc, _config_free_config_dma_memory(ioc, &mem); out: - mutex_unlock(&ioc->config_cmds.mutex); return r; } @@ -1572,7 +1541,6 @@ mpt2sas_config_get_number_pds(struct MPT2SAS_ADAPTER *ioc, u16 handle, struct config_request mem; u16 ioc_status; - mutex_lock(&ioc->config_cmds.mutex); memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); *num_pds = 0; mpi_request.Function = MPI2_FUNCTION_CONFIG; @@ -1620,7 +1588,6 @@ mpt2sas_config_get_number_pds(struct MPT2SAS_ADAPTER *ioc, u16 handle, _config_free_config_dma_memory(ioc, &mem); out: - mutex_unlock(&ioc->config_cmds.mutex); return r; } @@ -1645,7 +1612,6 @@ mpt2sas_config_get_raid_volume_pg0(struct MPT2SAS_ADAPTER *ioc, int r; struct config_request mem; - mutex_lock(&ioc->config_cmds.mutex); memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); memset(config_page, 0, sz); mpi_request.Function = MPI2_FUNCTION_CONFIG; @@ -1687,7 +1653,6 @@ mpt2sas_config_get_raid_volume_pg0(struct MPT2SAS_ADAPTER *ioc, _config_free_config_dma_memory(ioc, &mem); out: - mutex_unlock(&ioc->config_cmds.mutex); return r; } @@ -1711,7 +1676,6 @@ mpt2sas_config_get_phys_disk_pg0(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t int r; struct config_request mem; - mutex_lock(&ioc->config_cmds.mutex); memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); memset(config_page, 0, sizeof(Mpi2RaidPhysDiskPage0_t)); mpi_request.Function = MPI2_FUNCTION_CONFIG; @@ -1754,7 +1718,6 @@ mpt2sas_config_get_phys_disk_pg0(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t _config_free_config_dma_memory(ioc, &mem); out: - mutex_unlock(&ioc->config_cmds.mutex); return r; } @@ -1778,7 +1741,6 @@ mpt2sas_config_get_volume_handle(struct MPT2SAS_ADAPTER *ioc, u16 pd_handle, struct config_request mem; u16 ioc_status; - mutex_lock(&ioc->config_cmds.mutex); *volume_handle = 0; memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); mpi_request.Function = MPI2_FUNCTION_CONFIG; @@ -1842,7 +1804,6 @@ mpt2sas_config_get_volume_handle(struct MPT2SAS_ADAPTER *ioc, u16 pd_handle, _config_free_config_dma_memory(ioc, &mem); out: - mutex_unlock(&ioc->config_cmds.mutex); return r; } diff --git a/drivers/scsi/mpt2sas/mpt2sas_scsih.c b/drivers/scsi/mpt2sas/mpt2sas_scsih.c index 2a01a5f..2e9a444 100644 --- a/drivers/scsi/mpt2sas/mpt2sas_scsih.c +++ b/drivers/scsi/mpt2sas/mpt2sas_scsih.c @@ -2767,6 +2767,10 @@ _scsih_scsi_ioc_info(struct MPT2SAS_ADAPTER *ioc, struct scsi_cmnd *scmd, char *desc_ioc_state = NULL; char *desc_scsi_status = NULL; char *desc_scsi_state = ioc->tmp_string; + u32 log_info = le32_to_cpu(mpi_reply->IOCLogInfo); + + if (log_info == 0x31170000) + return; switch (ioc_status) { case MPI2_IOCSTATUS_SUCCESS: @@ -3426,7 +3430,7 @@ _scsih_expander_add(struct MPT2SAS_ADAPTER *ioc, u16 handle) __le64 sas_address; int i; unsigned long flags; - struct _sas_port *mpt2sas_port; + struct _sas_port *mpt2sas_port = NULL; int rc = 0; if (!handle) @@ -3518,12 +3522,20 @@ _scsih_expander_add(struct MPT2SAS_ADAPTER *ioc, u16 handle) &expander_pg1, i, handle))) { printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n", ioc->name, __FILE__, __LINE__, __func__); - continue; + rc = -1; + goto out_fail; } sas_expander->phy[i].handle = handle; sas_expander->phy[i].phy_id = i; - mpt2sas_transport_add_expander_phy(ioc, &sas_expander->phy[i], - expander_pg1, sas_expander->parent_dev); + + if ((mpt2sas_transport_add_expander_phy(ioc, + &sas_expander->phy[i], expander_pg1, + sas_expander->parent_dev))) { + printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n", + ioc->name, __FILE__, __LINE__, __func__); + rc = -1; + goto out_fail; + } } if (sas_expander->enclosure_handle) { @@ -3540,8 +3552,9 @@ _scsih_expander_add(struct MPT2SAS_ADAPTER *ioc, u16 handle) out_fail: - if (sas_expander) - kfree(sas_expander->phy); + if (mpt2sas_port) + mpt2sas_transport_port_remove(ioc, sas_expander->sas_address, + sas_expander->parent_handle); kfree(sas_expander); return rc; } @@ -3663,12 +3676,11 @@ _scsih_add_device(struct MPT2SAS_ADAPTER *ioc, u16 handle, u8 phy_num, u8 is_pd) sas_device->hidden_raid_component = is_pd; /* get enclosure_logical_id */ - if (!(mpt2sas_config_get_enclosure_pg0(ioc, &mpi_reply, &enclosure_pg0, - MPI2_SAS_ENCLOS_PGAD_FORM_HANDLE, - sas_device->enclosure_handle))) { + if (sas_device->enclosure_handle && !(mpt2sas_config_get_enclosure_pg0( + ioc, &mpi_reply, &enclosure_pg0, MPI2_SAS_ENCLOS_PGAD_FORM_HANDLE, + sas_device->enclosure_handle))) sas_device->enclosure_logical_id = le64_to_cpu(enclosure_pg0.EnclosureLogicalID); - } /* get device name */ sas_device->device_name = le64_to_cpu(sas_device_pg0.DeviceName); @@ -4250,12 +4262,6 @@ _scsih_sas_volume_add(struct MPT2SAS_ADAPTER *ioc, u16 handle = le16_to_cpu(element->VolDevHandle); int rc; -#if 0 /* RAID_HACKS */ - if (le32_to_cpu(event_data->Flags) & - MPI2_EVENT_IR_CHANGE_FLAGS_FOREIGN_CONFIG) - return; -#endif - mpt2sas_config_get_volume_wwid(ioc, handle, &wwid); if (!wwid) { printk(MPT2SAS_ERR_FMT @@ -4310,12 +4316,6 @@ _scsih_sas_volume_delete(struct MPT2SAS_ADAPTER *ioc, unsigned long flags; struct MPT2SAS_TARGET *sas_target_priv_data; -#if 0 /* RAID_HACKS */ - if (le32_to_cpu(event_data->Flags) & - MPI2_EVENT_IR_CHANGE_FLAGS_FOREIGN_CONFIG) - return; -#endif - spin_lock_irqsave(&ioc->raid_device_lock, flags); raid_device = _scsih_raid_device_find_by_handle(ioc, handle); spin_unlock_irqrestore(&ioc->raid_device_lock, flags); @@ -4428,14 +4428,38 @@ _scsih_sas_pd_add(struct MPT2SAS_ADAPTER *ioc, struct _sas_device *sas_device; unsigned long flags; u16 handle = le16_to_cpu(element->PhysDiskDevHandle); + Mpi2ConfigReply_t mpi_reply; + Mpi2SasDevicePage0_t sas_device_pg0; + u32 ioc_status; spin_lock_irqsave(&ioc->sas_device_lock, flags); sas_device = _scsih_sas_device_find_by_handle(ioc, handle); spin_unlock_irqrestore(&ioc->sas_device_lock, flags); - if (sas_device) + if (sas_device) { sas_device->hidden_raid_component = 1; - else - _scsih_add_device(ioc, handle, 0, 1); + return; + } + + if ((mpt2sas_config_get_sas_device_pg0(ioc, &mpi_reply, &sas_device_pg0, + MPI2_SAS_DEVICE_PGAD_FORM_HANDLE, handle))) { + printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n", + ioc->name, __FILE__, __LINE__, __func__); + return; + } + + ioc_status = le16_to_cpu(mpi_reply.IOCStatus) & + MPI2_IOCSTATUS_MASK; + if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { + printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n", + ioc->name, __FILE__, __LINE__, __func__); + return; + } + + _scsih_link_change(ioc, + le16_to_cpu(sas_device_pg0.ParentDevHandle), + handle, sas_device_pg0.PhyNum, MPI2_SAS_NEG_LINK_RATE_1_5); + + _scsih_add_device(ioc, handle, 0, 1); } #ifdef CONFIG_SCSI_MPT2SAS_LOGGING @@ -4535,12 +4559,15 @@ _scsih_sas_ir_config_change_event(struct MPT2SAS_ADAPTER *ioc, u8 VF_ID, { Mpi2EventIrConfigElement_t *element; int i; + u8 foreign_config; #ifdef CONFIG_SCSI_MPT2SAS_LOGGING if (ioc->logging_level & MPT_DEBUG_EVENT_WORK_TASK) _scsih_sas_ir_config_change_event_debug(ioc, event_data); #endif + foreign_config = (le32_to_cpu(event_data->Flags) & + MPI2_EVENT_IR_CHANGE_FLAGS_FOREIGN_CONFIG) ? 1 : 0; element = (Mpi2EventIrConfigElement_t *)&event_data->ConfigElement[0]; for (i = 0; i < event_data->NumElements; i++, element++) { @@ -4548,11 +4575,13 @@ _scsih_sas_ir_config_change_event(struct MPT2SAS_ADAPTER *ioc, u8 VF_ID, switch (element->ReasonCode) { case MPI2_EVENT_IR_CHANGE_RC_VOLUME_CREATED: case MPI2_EVENT_IR_CHANGE_RC_ADDED: - _scsih_sas_volume_add(ioc, element); + if (!foreign_config) + _scsih_sas_volume_add(ioc, element); break; case MPI2_EVENT_IR_CHANGE_RC_VOLUME_DELETED: case MPI2_EVENT_IR_CHANGE_RC_REMOVED: - _scsih_sas_volume_delete(ioc, element); + if (!foreign_config) + _scsih_sas_volume_delete(ioc, element); break; case MPI2_EVENT_IR_CHANGE_RC_PD_CREATED: _scsih_sas_pd_hide(ioc, element); @@ -4671,6 +4700,9 @@ _scsih_sas_ir_physical_disk_event(struct MPT2SAS_ADAPTER *ioc, u8 VF_ID, u32 state; struct _sas_device *sas_device; unsigned long flags; + Mpi2ConfigReply_t mpi_reply; + Mpi2SasDevicePage0_t sas_device_pg0; + u32 ioc_status; if (event_data->ReasonCode != MPI2_EVENT_IR_PHYSDISK_RC_STATE_CHANGED) return; @@ -4687,22 +4719,40 @@ _scsih_sas_ir_physical_disk_event(struct MPT2SAS_ADAPTER *ioc, u8 VF_ID, spin_unlock_irqrestore(&ioc->sas_device_lock, flags); switch (state) { -#if 0 - case MPI2_RAID_PD_STATE_OFFLINE: - if (sas_device) - _scsih_remove_device(ioc, handle); - break; -#endif case MPI2_RAID_PD_STATE_ONLINE: case MPI2_RAID_PD_STATE_DEGRADED: case MPI2_RAID_PD_STATE_REBUILDING: case MPI2_RAID_PD_STATE_OPTIMAL: - if (sas_device) + if (sas_device) { sas_device->hidden_raid_component = 1; - else - _scsih_add_device(ioc, handle, 0, 1); + return; + } + + if ((mpt2sas_config_get_sas_device_pg0(ioc, &mpi_reply, + &sas_device_pg0, MPI2_SAS_DEVICE_PGAD_FORM_HANDLE, + handle))) { + printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n", + ioc->name, __FILE__, __LINE__, __func__); + return; + } + + ioc_status = le16_to_cpu(mpi_reply.IOCStatus) & + MPI2_IOCSTATUS_MASK; + if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { + printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n", + ioc->name, __FILE__, __LINE__, __func__); + return; + } + + _scsih_link_change(ioc, + le16_to_cpu(sas_device_pg0.ParentDevHandle), + handle, sas_device_pg0.PhyNum, MPI2_SAS_NEG_LINK_RATE_1_5); + + _scsih_add_device(ioc, handle, 0, 1); + break; + case MPI2_RAID_PD_STATE_OFFLINE: case MPI2_RAID_PD_STATE_NOT_CONFIGURED: case MPI2_RAID_PD_STATE_NOT_COMPATIBLE: case MPI2_RAID_PD_STATE_HOT_SPARE: @@ -5774,6 +5824,7 @@ _scsih_suspend(struct pci_dev *pdev, pm_message_t state) struct MPT2SAS_ADAPTER *ioc = shost_priv(shost); u32 device_state; + mpt2sas_base_stop_watchdog(ioc); flush_scheduled_work(); scsi_block_requests(shost); device_state = pci_choose_state(pdev, state); @@ -5816,6 +5867,7 @@ _scsih_resume(struct pci_dev *pdev) mpt2sas_base_hard_reset_handler(ioc, CAN_SLEEP, SOFT_RESET); scsi_unblock_requests(shost); + mpt2sas_base_start_watchdog(ioc); return 0; } #endif /* CONFIG_PM */ diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig index 037c1e0..6553833 100644 --- a/drivers/serial/Kconfig +++ b/drivers/serial/Kconfig @@ -527,7 +527,7 @@ config SERIAL_S3C24A0 config SERIAL_S3C6400 tristate "Samsung S3C6400/S3C6410 Serial port support" - depends on SERIAL_SAMSUNG && (CPU_S3C600 || CPU_S3C6410) + depends on SERIAL_SAMSUNG && (CPU_S3C6400 || CPU_S3C6410) default y help Serial port support for the Samsung S3C6400 and S3C6410 diff --git a/drivers/spi/spi_s3c24xx.c b/drivers/spi/spi_s3c24xx.c index e0d44af..3f3119d 100644 --- a/drivers/spi/spi_s3c24xx.c +++ b/drivers/spi/spi_s3c24xx.c @@ -111,29 +111,32 @@ static int s3c24xx_spi_setupxfer(struct spi_device *spi, unsigned int bpw; unsigned int hz; unsigned int div; + unsigned long clk; bpw = t ? t->bits_per_word : spi->bits_per_word; hz = t ? t->speed_hz : spi->max_speed_hz; + if (!bpw) + bpw = 8; + + if (!hz) + hz = spi->max_speed_hz; + if (bpw != 8) { dev_err(&spi->dev, "invalid bits-per-word (%d)\n", bpw); return -EINVAL; } - div = clk_get_rate(hw->clk) / hz; - - /* is clk = pclk / (2 * (pre+1)), or is it - * clk = (pclk * 2) / ( pre + 1) */ - - div /= 2; - - if (div > 0) - div -= 1; + clk = clk_get_rate(hw->clk); + div = DIV_ROUND_UP(clk, hz * 2) - 1; if (div > 255) div = 255; - dev_dbg(&spi->dev, "setting pre-scaler to %d (hz %d)\n", div, hz); + dev_dbg(&spi->dev, "setting pre-scaler to %d (wanted %d, got %ld)\n", + div, hz, clk / (2 * (div + 1))); + + writeb(div, hw->regs + S3C2410_SPPRE); spin_lock(&hw->bitbang.lock); diff --git a/drivers/video/sh_mobile_lcdcfb.c b/drivers/video/sh_mobile_lcdcfb.c index 8f24564..07f22b6 100644 --- a/drivers/video/sh_mobile_lcdcfb.c +++ b/drivers/video/sh_mobile_lcdcfb.c @@ -481,6 +481,9 @@ static int sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv) /* tell the board code to enable the panel */ for (k = 0; k < ARRAY_SIZE(priv->ch); k++) { ch = &priv->ch[k]; + if (!ch->enabled) + continue; + board_cfg = &ch->cfg.board_cfg; if (board_cfg->display_on) board_cfg->display_on(board_cfg->board_data); @@ -498,6 +501,8 @@ static void sh_mobile_lcdc_stop(struct sh_mobile_lcdc_priv *priv) /* clean up deferred io and ask board code to disable panel */ for (k = 0; k < ARRAY_SIZE(priv->ch); k++) { ch = &priv->ch[k]; + if (!ch->enabled) + continue; /* deferred io mode: * flush frame, and wait for frame end interrupt diff --git a/drivers/watchdog/ar7_wdt.c b/drivers/watchdog/ar7_wdt.c index 3fe9742..2f8643e 100644 --- a/drivers/watchdog/ar7_wdt.c +++ b/drivers/watchdog/ar7_wdt.c @@ -37,7 +37,7 @@ #include <linux/uaccess.h> #include <asm/addrspace.h> -#include <asm/ar7/ar7.h> +#include <asm/mach-ar7/ar7.h> #define DRVNAME "ar7_wdt" #define LONGNAME "TI AR7 Watchdog Timer" |