Re: Linux 2.6.35.1

From: Greg KH
Date: Tue Aug 10 2010 - 14:50:34 EST



diff --git a/Makefile b/Makefile
index 141da26..0b9c763 100644
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
VERSION = 2
PATCHLEVEL = 6
SUBLEVEL = 35
-EXTRAVERSION =
+EXTRAVERSION = .1
NAME = Sheep on Meth

# *DOCUMENTATION*
diff --git a/arch/arm/plat-mxc/gpio.c b/arch/arm/plat-mxc/gpio.c
index 71437c6..9ebbd31 100644
--- a/arch/arm/plat-mxc/gpio.c
+++ b/arch/arm/plat-mxc/gpio.c
@@ -214,13 +214,16 @@ static void _set_gpio_direction(struct gpio_chip *chip, unsigned offset,
struct mxc_gpio_port *port =
container_of(chip, struct mxc_gpio_port, chip);
u32 l;
+ unsigned long flags;

+ spin_lock_irqsave(&port->lock, flags);
l = __raw_readl(port->base + GPIO_GDIR);
if (dir)
l |= 1 << offset;
else
l &= ~(1 << offset);
__raw_writel(l, port->base + GPIO_GDIR);
+ spin_unlock_irqrestore(&port->lock, flags);
}

static void mxc_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
@@ -229,9 +232,12 @@ static void mxc_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
container_of(chip, struct mxc_gpio_port, chip);
void __iomem *reg = port->base + GPIO_DR;
u32 l;
+ unsigned long flags;

+ spin_lock_irqsave(&port->lock, flags);
l = (__raw_readl(reg) & (~(1 << offset))) | (value << offset);
__raw_writel(l, reg);
+ spin_unlock_irqrestore(&port->lock, flags);
}

static int mxc_gpio_get(struct gpio_chip *chip, unsigned offset)
@@ -285,6 +291,8 @@ int __init mxc_gpio_init(struct mxc_gpio_port *port, int cnt)
port[i].chip.base = i * 32;
port[i].chip.ngpio = 32;

+ spin_lock_init(&port[i].lock);
+
/* its a serious configuration bug when it fails */
BUG_ON( gpiochip_add(&port[i].chip) < 0 );

diff --git a/arch/arm/plat-mxc/include/mach/gpio.h b/arch/arm/plat-mxc/include/mach/gpio.h
index 894d2f8..6bd932c 100644
--- a/arch/arm/plat-mxc/include/mach/gpio.h
+++ b/arch/arm/plat-mxc/include/mach/gpio.h
@@ -36,6 +36,7 @@ struct mxc_gpio_port {
int virtual_irq_start;
struct gpio_chip chip;
u32 both_edges;
+ spinlock_t lock;
};

int mxc_gpio_init(struct mxc_gpio_port*, int);
diff --git a/arch/parisc/kernel/firmware.c b/arch/parisc/kernel/firmware.c
index 4c247e0..df971fa 100644
--- a/arch/parisc/kernel/firmware.c
+++ b/arch/parisc/kernel/firmware.c
@@ -1123,7 +1123,6 @@ static char __attribute__((aligned(64))) iodc_dbuf[4096];
*/
int pdc_iodc_print(const unsigned char *str, unsigned count)
{
- static int posx; /* for simple TAB-Simulation... */
unsigned int i;
unsigned long flags;

@@ -1133,19 +1132,12 @@ int pdc_iodc_print(const unsigned char *str, unsigned count)
iodc_dbuf[i+0] = '\r';
iodc_dbuf[i+1] = '\n';
i += 2;
- posx = 0;
goto print;
- case '\t':
- while (posx & 7) {
- iodc_dbuf[i] = ' ';
- i++, posx++;
- }
- break;
case '\b': /* BS */
- posx -= 2;
+ i--; /* overwrite last */
default:
iodc_dbuf[i] = str[i];
- i++, posx++;
+ i++;
break;
}
}
diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c
index 65d8d79..27dff06 100644
--- a/arch/x86/xen/enlighten.c
+++ b/arch/x86/xen/enlighten.c
@@ -927,7 +927,7 @@ static const struct pv_init_ops xen_init_ops __initdata = {
};

static const struct pv_time_ops xen_time_ops __initdata = {
- .sched_clock = xen_sched_clock,
+ .sched_clock = xen_clocksource_read,
};

static const struct pv_cpu_ops xen_cpu_ops __initdata = {
diff --git a/arch/x86/xen/time.c b/arch/x86/xen/time.c
index b3c6c59..a86df42 100644
--- a/arch/x86/xen/time.c
+++ b/arch/x86/xen/time.c
@@ -155,45 +155,6 @@ static void do_stolen_accounting(void)
account_idle_ticks(ticks);
}

-/*
- * Xen sched_clock implementation. Returns the number of unstolen
- * nanoseconds, which is nanoseconds the VCPU spent in RUNNING+BLOCKED
- * states.
- */
-unsigned long long xen_sched_clock(void)
-{
- struct vcpu_runstate_info state;
- cycle_t now;
- u64 ret;
- s64 offset;
-
- /*
- * Ideally sched_clock should be called on a per-cpu basis
- * anyway, so preempt should already be disabled, but that's
- * not current practice at the moment.
- */
- preempt_disable();
-
- now = xen_clocksource_read();
-
- get_runstate_snapshot(&state);
-
- WARN_ON(state.state != RUNSTATE_running);
-
- offset = now - state.state_entry_time;
- if (offset < 0)
- offset = 0;
-
- ret = state.time[RUNSTATE_blocked] +
- state.time[RUNSTATE_running] +
- offset;
-
- preempt_enable();
-
- return ret;
-}
-
-
/* Get the TSC speed from Xen */
unsigned long xen_tsc_khz(void)
{
diff --git a/drivers/edac/amd64_edac.c b/drivers/edac/amd64_edac.c
index ac9f798..c20a6c9 100644
--- a/drivers/edac/amd64_edac.c
+++ b/drivers/edac/amd64_edac.c
@@ -178,7 +178,7 @@ static int amd64_set_scrub_rate(struct mem_ctl_info *mci, u32 *bandwidth)

default:
amd64_printk(KERN_ERR, "Unsupported family!\n");
- break;
+ return -EINVAL;
}
return amd64_search_set_scrub_rate(pvt->misc_f3_ctl, *bandwidth,
min_scrubrate);
@@ -1430,7 +1430,7 @@ static inline u64 f10_get_base_addr_offset(u64 sys_addr, int hi_range_sel,
u64 chan_off;

if (hi_range_sel) {
- if (!(dct_sel_base_addr & 0xFFFFF800) &&
+ if (!(dct_sel_base_addr & 0xFFFF0000) &&
hole_valid && (sys_addr >= 0x100000000ULL))
chan_off = hole_off << 16;
else
@@ -1679,7 +1679,7 @@ static void f10_map_sysaddr_to_csrow(struct mem_ctl_info *mci,
* ganged. Otherwise @chan should already contain the channel at
* this point.
*/
- if (dct_ganging_enabled(pvt) && pvt->nbcfg & K8_NBCFG_CHIPKILL)
+ if (dct_ganging_enabled(pvt) && (pvt->nbcfg & K8_NBCFG_CHIPKILL))
chan = get_channel_from_ecc_syndrome(mci, syndrome);

if (chan >= 0)
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 5e21b31..8a84306 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -42,6 +42,7 @@
bool intel_pipe_has_type (struct drm_crtc *crtc, int type);
static void intel_update_watermarks(struct drm_device *dev);
static void intel_increase_pllclock(struct drm_crtc *crtc, bool schedule);
+static void intel_crtc_update_cursor(struct drm_crtc *crtc);

typedef struct {
/* given values */
@@ -3403,6 +3404,9 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc,
return -EINVAL;
}

+ /* Ensure that the cursor is valid for the new mode before changing... */
+ intel_crtc_update_cursor(crtc);
+
if (is_lvds && dev_priv->lvds_downclock_avail) {
has_reduced_clock = limit->find_pll(limit, crtc,
dev_priv->lvds_downclock,
@@ -3939,6 +3943,85 @@ void intel_crtc_load_lut(struct drm_crtc *crtc)
}
}

+/* If no-part of the cursor is visible on the framebuffer, then the GPU may hang... */
+static void intel_crtc_update_cursor(struct drm_crtc *crtc)
+{
+ struct drm_device *dev = crtc->dev;
+ struct drm_i915_private *dev_priv = dev->dev_private;
+ struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+ int pipe = intel_crtc->pipe;
+ int x = intel_crtc->cursor_x;
+ int y = intel_crtc->cursor_y;
+ uint32_t base, pos;
+ bool visible;
+
+ pos = 0;
+
+ if (crtc->fb) {
+ base = intel_crtc->cursor_addr;
+ if (x > (int) crtc->fb->width)
+ base = 0;
+
+ if (y > (int) crtc->fb->height)
+ base = 0;
+ } else
+ base = 0;
+
+ if (x < 0) {
+ if (x + intel_crtc->cursor_width < 0)
+ base = 0;
+
+ pos |= CURSOR_POS_SIGN << CURSOR_X_SHIFT;
+ x = -x;
+ }
+ pos |= x << CURSOR_X_SHIFT;
+
+ if (y < 0) {
+ if (y + intel_crtc->cursor_height < 0)
+ base = 0;
+
+ pos |= CURSOR_POS_SIGN << CURSOR_Y_SHIFT;
+ y = -y;
+ }
+ pos |= y << CURSOR_Y_SHIFT;
+
+ visible = base != 0;
+ if (!visible && !intel_crtc->cursor_visble)
+ return;
+
+ I915_WRITE(pipe == 0 ? CURAPOS : CURBPOS, pos);
+ if (intel_crtc->cursor_visble != visible) {
+ uint32_t cntl = I915_READ(pipe == 0 ? CURACNTR : CURBCNTR);
+ if (base) {
+ /* Hooray for CUR*CNTR differences */
+ if (IS_MOBILE(dev) || IS_I9XX(dev)) {
+ cntl &= ~(CURSOR_MODE | MCURSOR_PIPE_SELECT);
+ cntl |= CURSOR_MODE_64_ARGB_AX | MCURSOR_GAMMA_ENABLE;
+ cntl |= pipe << 28; /* Connect to correct pipe */
+ } else {
+ cntl &= ~(CURSOR_FORMAT_MASK);
+ cntl |= CURSOR_ENABLE;
+ cntl |= CURSOR_FORMAT_ARGB | CURSOR_GAMMA_ENABLE;
+ }
+ } else {
+ if (IS_MOBILE(dev) || IS_I9XX(dev)) {
+ cntl &= ~(CURSOR_MODE | MCURSOR_GAMMA_ENABLE);
+ cntl |= CURSOR_MODE_DISABLE;
+ } else {
+ cntl &= ~(CURSOR_ENABLE | CURSOR_GAMMA_ENABLE);
+ }
+ }
+ I915_WRITE(pipe == 0 ? CURACNTR : CURBCNTR, cntl);
+
+ intel_crtc->cursor_visble = visible;
+ }
+ /* and commit changes on next vblank */
+ I915_WRITE(pipe == 0 ? CURABASE : CURBBASE, base);
+
+ if (visible)
+ intel_mark_busy(dev, to_intel_framebuffer(crtc->fb)->obj);
+}
+
static int intel_crtc_cursor_set(struct drm_crtc *crtc,
struct drm_file *file_priv,
uint32_t handle,
@@ -3949,11 +4032,7 @@ static int intel_crtc_cursor_set(struct drm_crtc *crtc,
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
struct drm_gem_object *bo;
struct drm_i915_gem_object *obj_priv;
- int pipe = intel_crtc->pipe;
- uint32_t control = (pipe == 0) ? CURACNTR : CURBCNTR;
- uint32_t base = (pipe == 0) ? CURABASE : CURBBASE;
- uint32_t temp = I915_READ(control);
- size_t addr;
+ uint32_t addr;
int ret;

DRM_DEBUG_KMS("\n");
@@ -3961,12 +4040,6 @@ static int intel_crtc_cursor_set(struct drm_crtc *crtc,
/* if we want to turn off the cursor ignore width and height */
if (!handle) {
DRM_DEBUG_KMS("cursor off\n");
- if (IS_MOBILE(dev) || IS_I9XX(dev)) {
- temp &= ~(CURSOR_MODE | MCURSOR_GAMMA_ENABLE);
- temp |= CURSOR_MODE_DISABLE;
- } else {
- temp &= ~(CURSOR_ENABLE | CURSOR_GAMMA_ENABLE);
- }
addr = 0;
bo = NULL;
mutex_lock(&dev->struct_mutex);
@@ -4008,7 +4081,8 @@ static int intel_crtc_cursor_set(struct drm_crtc *crtc,

addr = obj_priv->gtt_offset;
} else {
- ret = i915_gem_attach_phys_object(dev, bo, (pipe == 0) ? I915_GEM_PHYS_CURSOR_0 : I915_GEM_PHYS_CURSOR_1);
+ ret = i915_gem_attach_phys_object(dev, bo,
+ (intel_crtc->pipe == 0) ? I915_GEM_PHYS_CURSOR_0 : I915_GEM_PHYS_CURSOR_1);
if (ret) {
DRM_ERROR("failed to attach phys object\n");
goto fail_locked;
@@ -4019,21 +4093,7 @@ static int intel_crtc_cursor_set(struct drm_crtc *crtc,
if (!IS_I9XX(dev))
I915_WRITE(CURSIZE, (height << 12) | width);

- /* Hooray for CUR*CNTR differences */
- if (IS_MOBILE(dev) || IS_I9XX(dev)) {
- temp &= ~(CURSOR_MODE | MCURSOR_PIPE_SELECT);
- temp |= CURSOR_MODE_64_ARGB_AX | MCURSOR_GAMMA_ENABLE;
- temp |= (pipe << 28); /* Connect to correct pipe */
- } else {
- temp &= ~(CURSOR_FORMAT_MASK);
- temp |= CURSOR_ENABLE;
- temp |= CURSOR_FORMAT_ARGB | CURSOR_GAMMA_ENABLE;
- }
-
finish:
- I915_WRITE(control, temp);
- I915_WRITE(base, addr);
-
if (intel_crtc->cursor_bo) {
if (dev_priv->info->cursor_needs_physical) {
if (intel_crtc->cursor_bo != bo)
@@ -4047,6 +4107,10 @@ static int intel_crtc_cursor_set(struct drm_crtc *crtc,

intel_crtc->cursor_addr = addr;
intel_crtc->cursor_bo = bo;
+ intel_crtc->cursor_width = width;
+ intel_crtc->cursor_height = height;
+
+ intel_crtc_update_cursor(crtc);

return 0;
fail_unpin:
@@ -4060,34 +4124,12 @@ fail:

static int intel_crtc_cursor_move(struct drm_crtc *crtc, int x, int y)
{
- struct drm_device *dev = crtc->dev;
- struct drm_i915_private *dev_priv = dev->dev_private;
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
- struct intel_framebuffer *intel_fb;
- int pipe = intel_crtc->pipe;
- uint32_t temp = 0;
- uint32_t adder;
-
- if (crtc->fb) {
- intel_fb = to_intel_framebuffer(crtc->fb);
- intel_mark_busy(dev, intel_fb->obj);
- }
-
- if (x < 0) {
- temp |= CURSOR_POS_SIGN << CURSOR_X_SHIFT;
- x = -x;
- }
- if (y < 0) {
- temp |= CURSOR_POS_SIGN << CURSOR_Y_SHIFT;
- y = -y;
- }

- temp |= x << CURSOR_X_SHIFT;
- temp |= y << CURSOR_Y_SHIFT;
+ intel_crtc->cursor_x = x;
+ intel_crtc->cursor_y = y;

- adder = intel_crtc->cursor_addr;
- I915_WRITE((pipe == 0) ? CURAPOS : CURBPOS, temp);
- I915_WRITE((pipe == 0) ? CURABASE : CURBBASE, adder);
+ intel_crtc_update_cursor(crtc);

return 0;
}
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 2f7970b..2702652 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -143,8 +143,6 @@ struct intel_crtc {
struct drm_crtc base;
enum pipe pipe;
enum plane plane;
- struct drm_gem_object *cursor_bo;
- uint32_t cursor_addr;
u8 lut_r[256], lut_g[256], lut_b[256];
int dpms_mode;
bool busy; /* is scanout buffer being updated frequently? */
@@ -153,6 +151,12 @@ struct intel_crtc {
struct intel_overlay *overlay;
struct intel_unpin_work *unpin_work;
int fdi_lanes;
+
+ struct drm_gem_object *cursor_bo;
+ uint32_t cursor_addr;
+ int16_t cursor_x, cursor_y;
+ int16_t cursor_width, cursor_height;
+ bool cursor_visble;
};

#define to_intel_crtc(x) container_of(x, struct intel_crtc, base)
diff --git a/drivers/gpu/drm/i915/intel_overlay.c b/drivers/gpu/drm/i915/intel_overlay.c
index d7ad513..fe05ba2 100644
--- a/drivers/gpu/drm/i915/intel_overlay.c
+++ b/drivers/gpu/drm/i915/intel_overlay.c
@@ -958,7 +958,7 @@ static int check_overlay_src(struct drm_device *dev,
|| rec->src_width < N_HORIZ_Y_TAPS*4)
return -EINVAL;

- /* check alingment constrains */
+ /* check alignment constraints */
switch (rec->flags & I915_OVERLAY_TYPE_MASK) {
case I915_OVERLAY_RGB:
/* not implemented */
@@ -990,7 +990,10 @@ static int check_overlay_src(struct drm_device *dev,
return -EINVAL;

/* stride checking */
- stride_mask = 63;
+ if (IS_I830(dev) || IS_845G(dev))
+ stride_mask = 255;
+ else
+ stride_mask = 63;

if (rec->stride_Y & stride_mask || rec->stride_UV & stride_mask)
return -EINVAL;
diff --git a/drivers/gpu/drm/radeon/r600.c b/drivers/gpu/drm/radeon/r600.c
index e100f69..bb3de01 100644
--- a/drivers/gpu/drm/radeon/r600.c
+++ b/drivers/gpu/drm/radeon/r600.c
@@ -869,7 +869,17 @@ void r600_pcie_gart_tlb_flush(struct radeon_device *rdev)
u32 tmp;

/* flush hdp cache so updates hit vram */
- WREG32(R_005480_HDP_MEM_COHERENCY_FLUSH_CNTL, 0x1);
+ if ((rdev->family >= CHIP_RV770) && (rdev->family <= CHIP_RV740)) {
+ void __iomem *ptr = (void *)rdev->gart.table.vram.ptr;
+ u32 tmp;
+
+ /* r7xx hw bug. write to HDP_DEBUG1 followed by fb read
+ * rather than write to HDP_REG_COHERENCY_FLUSH_CNTL
+ */
+ WREG32(HDP_DEBUG1, 0);
+ tmp = readl((void __iomem *)ptr);
+ } else
+ WREG32(R_005480_HDP_MEM_COHERENCY_FLUSH_CNTL, 0x1);

WREG32(VM_CONTEXT0_INVALIDATION_LOW_ADDR, rdev->mc.gtt_start >> 12);
WREG32(VM_CONTEXT0_INVALIDATION_HIGH_ADDR, (rdev->mc.gtt_end - 1) >> 12);
@@ -3512,5 +3522,15 @@ int r600_debugfs_mc_info_init(struct radeon_device *rdev)
*/
void r600_ioctl_wait_idle(struct radeon_device *rdev, struct radeon_bo *bo)
{
- WREG32(R_005480_HDP_MEM_COHERENCY_FLUSH_CNTL, 0x1);
+ /* r7xx hw bug. write to HDP_DEBUG1 followed by fb read
+ * rather than write to HDP_REG_COHERENCY_FLUSH_CNTL
+ */
+ if ((rdev->family >= CHIP_RV770) && (rdev->family <= CHIP_RV740)) {
+ void __iomem *ptr = (void *)rdev->gart.table.vram.ptr;
+ u32 tmp;
+
+ WREG32(HDP_DEBUG1, 0);
+ tmp = readl((void __iomem *)ptr);
+ } else
+ WREG32(R_005480_HDP_MEM_COHERENCY_FLUSH_CNTL, 0x1);
}
diff --git a/drivers/gpu/drm/radeon/r600d.h b/drivers/gpu/drm/radeon/r600d.h
index 59c1f87..84bc28e 100644
--- a/drivers/gpu/drm/radeon/r600d.h
+++ b/drivers/gpu/drm/radeon/r600d.h
@@ -245,6 +245,7 @@
#define HDP_NONSURFACE_SIZE 0x2C0C
#define HDP_REG_COHERENCY_FLUSH_CNTL 0x54A0
#define HDP_TILING_CONFIG 0x2F3C
+#define HDP_DEBUG1 0x2F34

#define MC_VM_AGP_TOP 0x2184
#define MC_VM_AGP_BOT 0x2188
diff --git a/drivers/gpu/drm/radeon/radeon_object.c b/drivers/gpu/drm/radeon/radeon_object.c
index d5b9373..d33b6c9 100644
--- a/drivers/gpu/drm/radeon/radeon_object.c
+++ b/drivers/gpu/drm/radeon/radeon_object.c
@@ -110,6 +110,7 @@ int radeon_bo_create(struct radeon_device *rdev, struct drm_gem_object *gobj,
bo->surface_reg = -1;
INIT_LIST_HEAD(&bo->list);

+retry:
radeon_ttm_placement_from_domain(bo, domain);
/* Kernel allocation are uninterruptible */
mutex_lock(&rdev->vram_mutex);
@@ -118,10 +119,15 @@ int radeon_bo_create(struct radeon_device *rdev, struct drm_gem_object *gobj,
&radeon_ttm_bo_destroy);
mutex_unlock(&rdev->vram_mutex);
if (unlikely(r != 0)) {
- if (r != -ERESTARTSYS)
+ if (r != -ERESTARTSYS) {
+ if (domain == RADEON_GEM_DOMAIN_VRAM) {
+ domain |= RADEON_GEM_DOMAIN_GTT;
+ goto retry;
+ }
dev_err(rdev->dev,
"object_init failed for (%lu, 0x%08X)\n",
size, domain);
+ }
return r;
}
*bo_ptr = bo;
@@ -321,6 +327,7 @@ int radeon_bo_list_validate(struct list_head *head)
{
struct radeon_bo_list *lobj;
struct radeon_bo *bo;
+ u32 domain;
int r;

list_for_each_entry(lobj, head, list) {
@@ -333,17 +340,19 @@ int radeon_bo_list_validate(struct list_head *head)
list_for_each_entry(lobj, head, list) {
bo = lobj->bo;
if (!bo->pin_count) {
- if (lobj->wdomain) {
- radeon_ttm_placement_from_domain(bo,
- lobj->wdomain);
- } else {
- radeon_ttm_placement_from_domain(bo,
- lobj->rdomain);
- }
+ domain = lobj->wdomain ? lobj->wdomain : lobj->rdomain;
+
+ retry:
+ radeon_ttm_placement_from_domain(bo, domain);
r = ttm_bo_validate(&bo->tbo, &bo->placement,
true, false, false);
- if (unlikely(r))
+ if (unlikely(r)) {
+ if (r != -ERESTARTSYS && domain == RADEON_GEM_DOMAIN_VRAM) {
+ domain |= RADEON_GEM_DOMAIN_GTT;
+ goto retry;
+ }
return r;
+ }
}
lobj->gpu_offset = radeon_bo_gpu_offset(bo);
lobj->tiling_flags = bo->tiling_flags;
diff --git a/drivers/gpu/drm/radeon/rs690.c b/drivers/gpu/drm/radeon/rs690.c
index ce4ecbe..76c768b 100644
--- a/drivers/gpu/drm/radeon/rs690.c
+++ b/drivers/gpu/drm/radeon/rs690.c
@@ -398,7 +398,9 @@ void rs690_bandwidth_update(struct radeon_device *rdev)
struct drm_display_mode *mode1 = NULL;
struct rs690_watermark wm0;
struct rs690_watermark wm1;
- u32 tmp, d1mode_priority_a_cnt, d2mode_priority_a_cnt;
+ u32 tmp;
+ u32 d1mode_priority_a_cnt = S_006548_D1MODE_PRIORITY_A_OFF(1);
+ u32 d2mode_priority_a_cnt = S_006548_D1MODE_PRIORITY_A_OFF(1);
fixed20_12 priority_mark02, priority_mark12, fill_rate;
fixed20_12 a, b;

@@ -495,10 +497,6 @@ void rs690_bandwidth_update(struct radeon_device *rdev)
d1mode_priority_a_cnt |= S_006548_D1MODE_PRIORITY_A_ALWAYS_ON(1);
d2mode_priority_a_cnt |= S_006D48_D2MODE_PRIORITY_A_ALWAYS_ON(1);
}
- WREG32(R_006548_D1MODE_PRIORITY_A_CNT, d1mode_priority_a_cnt);
- WREG32(R_00654C_D1MODE_PRIORITY_B_CNT, d1mode_priority_a_cnt);
- WREG32(R_006D48_D2MODE_PRIORITY_A_CNT, d2mode_priority_a_cnt);
- WREG32(R_006D4C_D2MODE_PRIORITY_B_CNT, d2mode_priority_a_cnt);
} else if (mode0) {
if (dfixed_trunc(wm0.dbpp) > 64)
a.full = dfixed_mul(wm0.dbpp, wm0.num_line_pair);
@@ -528,13 +526,7 @@ void rs690_bandwidth_update(struct radeon_device *rdev)
d1mode_priority_a_cnt = dfixed_trunc(priority_mark02);
if (rdev->disp_priority == 2)
d1mode_priority_a_cnt |= S_006548_D1MODE_PRIORITY_A_ALWAYS_ON(1);
- WREG32(R_006548_D1MODE_PRIORITY_A_CNT, d1mode_priority_a_cnt);
- WREG32(R_00654C_D1MODE_PRIORITY_B_CNT, d1mode_priority_a_cnt);
- WREG32(R_006D48_D2MODE_PRIORITY_A_CNT,
- S_006D48_D2MODE_PRIORITY_A_OFF(1));
- WREG32(R_006D4C_D2MODE_PRIORITY_B_CNT,
- S_006D4C_D2MODE_PRIORITY_B_OFF(1));
- } else {
+ } else if (mode1) {
if (dfixed_trunc(wm1.dbpp) > 64)
a.full = dfixed_mul(wm1.dbpp, wm1.num_line_pair);
else
@@ -563,13 +555,12 @@ void rs690_bandwidth_update(struct radeon_device *rdev)
d2mode_priority_a_cnt = dfixed_trunc(priority_mark12);
if (rdev->disp_priority == 2)
d2mode_priority_a_cnt |= S_006D48_D2MODE_PRIORITY_A_ALWAYS_ON(1);
- WREG32(R_006548_D1MODE_PRIORITY_A_CNT,
- S_006548_D1MODE_PRIORITY_A_OFF(1));
- WREG32(R_00654C_D1MODE_PRIORITY_B_CNT,
- S_00654C_D1MODE_PRIORITY_B_OFF(1));
- WREG32(R_006D48_D2MODE_PRIORITY_A_CNT, d2mode_priority_a_cnt);
- WREG32(R_006D4C_D2MODE_PRIORITY_B_CNT, d2mode_priority_a_cnt);
}
+
+ WREG32(R_006548_D1MODE_PRIORITY_A_CNT, d1mode_priority_a_cnt);
+ WREG32(R_00654C_D1MODE_PRIORITY_B_CNT, d1mode_priority_a_cnt);
+ WREG32(R_006D48_D2MODE_PRIORITY_A_CNT, d2mode_priority_a_cnt);
+ WREG32(R_006D4C_D2MODE_PRIORITY_B_CNT, d2mode_priority_a_cnt);
}

uint32_t rs690_mc_rreg(struct radeon_device *rdev, uint32_t reg)
diff --git a/drivers/gpu/drm/radeon/rv515.c b/drivers/gpu/drm/radeon/rv515.c
index 0c9c169..7e4fbdb 100644
--- a/drivers/gpu/drm/radeon/rv515.c
+++ b/drivers/gpu/drm/radeon/rv515.c
@@ -925,7 +925,9 @@ void rv515_bandwidth_avivo_update(struct radeon_device *rdev)
struct drm_display_mode *mode1 = NULL;
struct rv515_watermark wm0;
struct rv515_watermark wm1;
- u32 tmp, d1mode_priority_a_cnt, d2mode_priority_a_cnt;
+ u32 tmp;
+ u32 d1mode_priority_a_cnt = MODE_PRIORITY_OFF;
+ u32 d2mode_priority_a_cnt = MODE_PRIORITY_OFF;
fixed20_12 priority_mark02, priority_mark12, fill_rate;
fixed20_12 a, b;

@@ -999,10 +1001,6 @@ void rv515_bandwidth_avivo_update(struct radeon_device *rdev)
d1mode_priority_a_cnt |= MODE_PRIORITY_ALWAYS_ON;
d2mode_priority_a_cnt |= MODE_PRIORITY_ALWAYS_ON;
}
- WREG32(D1MODE_PRIORITY_A_CNT, d1mode_priority_a_cnt);
- WREG32(D1MODE_PRIORITY_B_CNT, d1mode_priority_a_cnt);
- WREG32(D2MODE_PRIORITY_A_CNT, d2mode_priority_a_cnt);
- WREG32(D2MODE_PRIORITY_B_CNT, d2mode_priority_a_cnt);
} else if (mode0) {
if (dfixed_trunc(wm0.dbpp) > 64)
a.full = dfixed_div(wm0.dbpp, wm0.num_line_pair);
@@ -1032,11 +1030,7 @@ void rv515_bandwidth_avivo_update(struct radeon_device *rdev)
d1mode_priority_a_cnt = dfixed_trunc(priority_mark02);
if (rdev->disp_priority == 2)
d1mode_priority_a_cnt |= MODE_PRIORITY_ALWAYS_ON;
- WREG32(D1MODE_PRIORITY_A_CNT, d1mode_priority_a_cnt);
- WREG32(D1MODE_PRIORITY_B_CNT, d1mode_priority_a_cnt);
- WREG32(D2MODE_PRIORITY_A_CNT, MODE_PRIORITY_OFF);
- WREG32(D2MODE_PRIORITY_B_CNT, MODE_PRIORITY_OFF);
- } else {
+ } else if (mode1) {
if (dfixed_trunc(wm1.dbpp) > 64)
a.full = dfixed_div(wm1.dbpp, wm1.num_line_pair);
else
@@ -1065,11 +1059,12 @@ void rv515_bandwidth_avivo_update(struct radeon_device *rdev)
d2mode_priority_a_cnt = dfixed_trunc(priority_mark12);
if (rdev->disp_priority == 2)
d2mode_priority_a_cnt |= MODE_PRIORITY_ALWAYS_ON;
- WREG32(D1MODE_PRIORITY_A_CNT, MODE_PRIORITY_OFF);
- WREG32(D1MODE_PRIORITY_B_CNT, MODE_PRIORITY_OFF);
- WREG32(D2MODE_PRIORITY_A_CNT, d2mode_priority_a_cnt);
- WREG32(D2MODE_PRIORITY_B_CNT, d2mode_priority_a_cnt);
}
+
+ WREG32(D1MODE_PRIORITY_A_CNT, d1mode_priority_a_cnt);
+ WREG32(D1MODE_PRIORITY_B_CNT, d1mode_priority_a_cnt);
+ WREG32(D2MODE_PRIORITY_A_CNT, d2mode_priority_a_cnt);
+ WREG32(D2MODE_PRIORITY_B_CNT, d2mode_priority_a_cnt);
}

void rv515_bandwidth_update(struct radeon_device *rdev)
diff --git a/drivers/gpu/drm/radeon/rv770.c b/drivers/gpu/drm/radeon/rv770.c
index b7fd820..1d6fb79 100644
--- a/drivers/gpu/drm/radeon/rv770.c
+++ b/drivers/gpu/drm/radeon/rv770.c
@@ -189,7 +189,10 @@ static void rv770_mc_program(struct radeon_device *rdev)
WREG32((0x2c20 + j), 0x00000000);
WREG32((0x2c24 + j), 0x00000000);
}
- WREG32(HDP_REG_COHERENCY_FLUSH_CNTL, 0);
+ /* r7xx hw bug. Read from HDP_DEBUG1 rather
+ * than writing to HDP_REG_COHERENCY_FLUSH_CNTL
+ */
+ tmp = RREG32(HDP_DEBUG1);

rv515_mc_stop(rdev, &save);
if (r600_mc_wait_for_idle(rdev)) {
diff --git a/drivers/gpu/drm/radeon/rv770d.h b/drivers/gpu/drm/radeon/rv770d.h
index 9506f8c..6111a02 100644
--- a/drivers/gpu/drm/radeon/rv770d.h
+++ b/drivers/gpu/drm/radeon/rv770d.h
@@ -128,6 +128,7 @@
#define HDP_NONSURFACE_SIZE 0x2C0C
#define HDP_REG_COHERENCY_FLUSH_CNTL 0x54A0
#define HDP_TILING_CONFIG 0x2F3C
+#define HDP_DEBUG1 0x2F34

#define MC_SHARED_CHMAP 0x2004
#define NOOFCHAN_SHIFT 12
diff --git a/drivers/misc/enclosure.c b/drivers/misc/enclosure.c
index 48c84a5..00e5fcac8 100644
--- a/drivers/misc/enclosure.c
+++ b/drivers/misc/enclosure.c
@@ -285,8 +285,11 @@ enclosure_component_register(struct enclosure_device *edev,
cdev->groups = enclosure_groups;

err = device_register(cdev);
- if (err)
- ERR_PTR(err);
+ if (err) {
+ ecomp->number = -1;
+ put_device(cdev);
+ return ERR_PTR(err);
+ }

return ecomp;
}
diff --git a/drivers/net/e1000e/hw.h b/drivers/net/e1000e/hw.h
index 5d1220d..664ed58 100644
--- a/drivers/net/e1000e/hw.h
+++ b/drivers/net/e1000e/hw.h
@@ -308,7 +308,7 @@ enum e1e_registers {
#define E1000_KMRNCTRLSTA_INBAND_PARAM 0x9 /* Kumeran InBand Parameters */
#define E1000_KMRNCTRLSTA_DIAG_NELPBK 0x1000 /* Nearend Loopback mode */
#define E1000_KMRNCTRLSTA_K1_CONFIG 0x7
-#define E1000_KMRNCTRLSTA_K1_ENABLE 0x140E
+#define E1000_KMRNCTRLSTA_K1_ENABLE 0x0002
#define E1000_KMRNCTRLSTA_K1_DISABLE 0x1400

#define IFE_PHY_EXTENDED_STATUS_CONTROL 0x10
diff --git a/drivers/net/e1000e/netdev.c b/drivers/net/e1000e/netdev.c
index 57a7e41..79e38dc 100644
--- a/drivers/net/e1000e/netdev.c
+++ b/drivers/net/e1000e/netdev.c
@@ -3419,13 +3419,18 @@ static int e1000_test_msi(struct e1000_adapter *adapter)

/* disable SERR in case the MSI write causes a master abort */
pci_read_config_word(adapter->pdev, PCI_COMMAND, &pci_cmd);
- pci_write_config_word(adapter->pdev, PCI_COMMAND,
- pci_cmd & ~PCI_COMMAND_SERR);
+ if (pci_cmd & PCI_COMMAND_SERR)
+ pci_write_config_word(adapter->pdev, PCI_COMMAND,
+ pci_cmd & ~PCI_COMMAND_SERR);

err = e1000_test_msi_interrupt(adapter);

- /* restore previous setting of command word */
- pci_write_config_word(adapter->pdev, PCI_COMMAND, pci_cmd);
+ /* re-enable SERR */
+ if (pci_cmd & PCI_COMMAND_SERR) {
+ pci_read_config_word(adapter->pdev, PCI_COMMAND, &pci_cmd);
+ pci_cmd |= PCI_COMMAND_SERR;
+ pci_write_config_word(adapter->pdev, PCI_COMMAND, pci_cmd);
+ }

/* success ! */
if (!err)
diff --git a/drivers/net/igb/igb_main.c b/drivers/net/igb/igb_main.c
index cea37e0..df2a6d7 100644
--- a/drivers/net/igb/igb_main.c
+++ b/drivers/net/igb/igb_main.c
@@ -630,9 +630,6 @@ static void igb_cache_ring_register(struct igb_adapter *adapter)
for (; i < adapter->rss_queues; i++)
adapter->rx_ring[i]->reg_idx = rbase_offset +
Q_IDX_82576(i);
- for (; j < adapter->rss_queues; j++)
- adapter->tx_ring[j]->reg_idx = rbase_offset +
- Q_IDX_82576(j);
}
case e1000_82575:
case e1000_82580:
@@ -996,7 +993,10 @@ static void igb_set_interrupt_capability(struct igb_adapter *adapter)

/* Number of supported queues. */
adapter->num_rx_queues = adapter->rss_queues;
- adapter->num_tx_queues = adapter->rss_queues;
+ if (adapter->vfs_allocated_count)
+ adapter->num_tx_queues = 1;
+ else
+ adapter->num_tx_queues = adapter->rss_queues;

/* start with one vector for every rx queue */
numvecs = adapter->num_rx_queues;
diff --git a/drivers/net/wireless/ath/ath9k/ar9002_calib.c b/drivers/net/wireless/ath/ath9k/ar9002_calib.c
index 5fdbb53..dabafb8 100644
--- a/drivers/net/wireless/ath/ath9k/ar9002_calib.c
+++ b/drivers/net/wireless/ath/ath9k/ar9002_calib.c
@@ -239,7 +239,7 @@ static void ar9002_hw_iqcalibrate(struct ath_hw *ah, u8 numChains)
if (qCoff > 15)
qCoff = 15;
else if (qCoff <= -16)
- qCoff = 16;
+ qCoff = -16;

ath_print(common, ATH_DBG_CALIBRATE,
"Chn %d : iCoff = 0x%x qCoff = 0x%x\n",
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c
index 23eb60e..cb4e7da 100644
--- a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c
+++ b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c
@@ -944,7 +944,7 @@ static u8 ath9k_hw_ar9300_get_num_ant_config(struct ath_hw *ah,
return 1;
}

-static u16 ath9k_hw_ar9300_get_eeprom_antenna_cfg(struct ath_hw *ah,
+static u32 ath9k_hw_ar9300_get_eeprom_antenna_cfg(struct ath_hw *ah,
struct ath9k_channel *chan)
{
return -EINVAL;
diff --git a/drivers/net/wireless/ath/ath9k/eeprom.h b/drivers/net/wireless/ath/ath9k/eeprom.h
index 21354c1..5f01a0f 100644
--- a/drivers/net/wireless/ath/ath9k/eeprom.h
+++ b/drivers/net/wireless/ath/ath9k/eeprom.h
@@ -669,7 +669,7 @@ struct eeprom_ops {
int (*get_eeprom_ver)(struct ath_hw *hw);
int (*get_eeprom_rev)(struct ath_hw *hw);
u8 (*get_num_ant_config)(struct ath_hw *hw, enum ieee80211_band band);
- u16 (*get_eeprom_antenna_cfg)(struct ath_hw *hw,
+ u32 (*get_eeprom_antenna_cfg)(struct ath_hw *hw,
struct ath9k_channel *chan);
void (*set_board_values)(struct ath_hw *hw, struct ath9k_channel *chan);
void (*set_addac)(struct ath_hw *hw, struct ath9k_channel *chan);
diff --git a/drivers/net/wireless/ath/ath9k/eeprom_4k.c b/drivers/net/wireless/ath/ath9k/eeprom_4k.c
index 41a77d1..1576bbb 100644
--- a/drivers/net/wireless/ath/ath9k/eeprom_4k.c
+++ b/drivers/net/wireless/ath/ath9k/eeprom_4k.c
@@ -1149,13 +1149,13 @@ static void ath9k_hw_4k_set_board_values(struct ath_hw *ah,
}
}

-static u16 ath9k_hw_4k_get_eeprom_antenna_cfg(struct ath_hw *ah,
+static u32 ath9k_hw_4k_get_eeprom_antenna_cfg(struct ath_hw *ah,
struct ath9k_channel *chan)
{
struct ar5416_eeprom_4k *eep = &ah->eeprom.map4k;
struct modal_eep_4k_header *pModal = &eep->modalHeader;

- return pModal->antCtrlCommon & 0xFFFF;
+ return pModal->antCtrlCommon;
}

static u8 ath9k_hw_4k_get_num_ant_config(struct ath_hw *ah,
diff --git a/drivers/net/wireless/ath/ath9k/eeprom_9287.c b/drivers/net/wireless/ath/ath9k/eeprom_9287.c
index b471db5..2705eb0 100644
--- a/drivers/net/wireless/ath/ath9k/eeprom_9287.c
+++ b/drivers/net/wireless/ath/ath9k/eeprom_9287.c
@@ -1131,13 +1131,13 @@ static u8 ath9k_hw_AR9287_get_num_ant_config(struct ath_hw *ah,
return 1;
}

-static u16 ath9k_hw_AR9287_get_eeprom_antenna_cfg(struct ath_hw *ah,
+static u32 ath9k_hw_AR9287_get_eeprom_antenna_cfg(struct ath_hw *ah,
struct ath9k_channel *chan)
{
struct ar9287_eeprom *eep = &ah->eeprom.map9287;
struct modal_eep_ar9287_header *pModal = &eep->modalHeader;

- return pModal->antCtrlCommon & 0xFFFF;
+ return pModal->antCtrlCommon;
}

static u16 ath9k_hw_AR9287_get_spur_channel(struct ath_hw *ah,
diff --git a/drivers/net/wireless/ath/ath9k/eeprom_def.c b/drivers/net/wireless/ath/ath9k/eeprom_def.c
index 7e1ed78..54ce34e 100644
--- a/drivers/net/wireless/ath/ath9k/eeprom_def.c
+++ b/drivers/net/wireless/ath/ath9k/eeprom_def.c
@@ -729,7 +729,7 @@ static void ath9k_hw_get_def_gain_boundaries_pdadcs(struct ath_hw *ah,
vpdTableI[i][sizeCurrVpdTable - 2]);
vpdStep = (int16_t)((vpdStep < 1) ? 1 : vpdStep);

- if (tgtIndex > maxIndex) {
+ if (tgtIndex >= maxIndex) {
while ((ss <= tgtIndex) &&
(k < (AR5416_NUM_PDADC_VALUES - 1))) {
tmpVal = (int16_t)((vpdTableI[i][sizeCurrVpdTable - 1] +
@@ -1437,14 +1437,14 @@ static u8 ath9k_hw_def_get_num_ant_config(struct ath_hw *ah,
return num_ant_config;
}

-static u16 ath9k_hw_def_get_eeprom_antenna_cfg(struct ath_hw *ah,
+static u32 ath9k_hw_def_get_eeprom_antenna_cfg(struct ath_hw *ah,
struct ath9k_channel *chan)
{
struct ar5416_eeprom_def *eep = &ah->eeprom.def;
struct modal_eep_header *pModal =
&(eep->modalHeader[IS_CHAN_2GHZ(chan)]);

- return pModal->antCtrlCommon & 0xFFFF;
+ return pModal->antCtrlCommon;
}

static u16 ath9k_hw_def_get_spur_channel(struct ath_hw *ah, u16 i, bool is2GHz)
diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c
index c33f17d..2feee1d 100644
--- a/drivers/net/wireless/ath/ath9k/hw.c
+++ b/drivers/net/wireless/ath/ath9k/hw.c
@@ -537,7 +537,8 @@ static int __ath9k_hw_init(struct ath_hw *ah)

if (ah->config.serialize_regmode == SER_REG_MODE_AUTO) {
if (ah->hw_version.macVersion == AR_SREV_VERSION_5416_PCI ||
- (AR_SREV_9280(ah) && !ah->is_pciexpress)) {
+ ((AR_SREV_9160(ah) || AR_SREV_9280(ah)) &&
+ !ah->is_pciexpress)) {
ah->config.serialize_regmode =
SER_REG_MODE_ON;
} else {
@@ -1232,9 +1233,11 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,

if (!ah->chip_fullsleep) {
ath9k_hw_abortpcurecv(ah);
- if (!ath9k_hw_stopdmarecv(ah))
+ if (!ath9k_hw_stopdmarecv(ah)) {
ath_print(common, ATH_DBG_XMIT,
"Failed to stop receive dma\n");
+ bChannelChange = false;
+ }
}

if (!ath9k_hw_setpower(ah, ATH9K_PM_AWAKE))
@@ -1265,7 +1268,8 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,
macStaId1 = REG_READ(ah, AR_STA_ID1) & AR_STA_ID1_BASE_RATE_11B;

/* For chips on which RTC reset is done, save TSF before it gets cleared */
- if (AR_SREV_9280(ah) && ah->eep_ops->get_eeprom(ah, EEP_OL_PWRCTRL))
+ if (AR_SREV_9100(ah) ||
+ (AR_SREV_9280(ah) && ah->eep_ops->get_eeprom(ah, EEP_OL_PWRCTRL)))
tsf = ath9k_hw_gettsf64(ah);

saveLedState = REG_READ(ah, AR_CFG_LED) &
@@ -1297,7 +1301,7 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,
}

/* Restore TSF */
- if (tsf && AR_SREV_9280(ah) && ah->eep_ops->get_eeprom(ah, EEP_OL_PWRCTRL))
+ if (tsf)
ath9k_hw_settsf64(ah, tsf);

if (AR_SREV_9280_10_OR_LATER(ah))
@@ -1307,6 +1311,17 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,
if (r)
return r;

+ /*
+ * Some AR91xx SoC devices frequently fail to accept TSF writes
+ * right after the chip reset. When that happens, write a new
+ * value after the initvals have been applied, with an offset
+ * based on measured time difference
+ */
+ if (AR_SREV_9100(ah) && (ath9k_hw_gettsf64(ah) < tsf)) {
+ tsf += 1500;
+ ath9k_hw_settsf64(ah, tsf);
+ }
+
/* Setup MFP options for CCMP */
if (AR_SREV_9280_20_OR_LATER(ah)) {
/* Mask Retry(b11), PwrMgt(b12), MoreData(b13) to 0 in mgmt
diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c
index 859aa4a..d8dd503 100644
--- a/drivers/net/wireless/ath/ath9k/xmit.c
+++ b/drivers/net/wireless/ath/ath9k/xmit.c
@@ -328,6 +328,7 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,
u32 ba[WME_BA_BMP_SIZE >> 5];
int isaggr, txfail, txpending, sendbar = 0, needreset = 0, nbad = 0;
bool rc_update = true;
+ struct ieee80211_tx_rate rates[4];

skb = bf->bf_mpdu;
hdr = (struct ieee80211_hdr *)skb->data;
@@ -335,12 +336,30 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,
tx_info = IEEE80211_SKB_CB(skb);
hw = bf->aphy->hw;

+ memcpy(rates, tx_info->control.rates, sizeof(rates));
+
rcu_read_lock();

/* XXX: use ieee80211_find_sta! */
sta = ieee80211_find_sta_by_hw(hw, hdr->addr1);
if (!sta) {
rcu_read_unlock();
+
+ INIT_LIST_HEAD(&bf_head);
+ while (bf) {
+ bf_next = bf->bf_next;
+
+ bf->bf_state.bf_type |= BUF_XRETRY;
+ if ((sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) ||
+ !bf->bf_stale || bf_next != NULL)
+ list_move_tail(&bf->list, &bf_head);
+
+ ath_tx_rc_status(bf, ts, 0, 0, false);
+ ath_tx_complete_buf(sc, bf, txq, &bf_head, ts,
+ 0, 0);
+
+ bf = bf_next;
+ }
return;
}

@@ -375,6 +394,9 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,
txfail = txpending = 0;
bf_next = bf->bf_next;

+ skb = bf->bf_mpdu;
+ tx_info = IEEE80211_SKB_CB(skb);
+
if (ATH_BA_ISSET(ba, ATH_BA_INDEX(seq_st, bf->bf_seqno))) {
/* transmit completion, subframe is
* acked by block ack */
@@ -428,6 +450,7 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,
spin_unlock_bh(&txq->axq_lock);

if (rc_update && (acked_cnt == 1 || txfail_cnt == 1)) {
+ memcpy(tx_info->control.rates, rates, sizeof(rates));
ath_tx_rc_status(bf, ts, nbad, txok, true);
rc_update = false;
} else {
@@ -487,6 +510,14 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,
bf = bf_next;
}

+ /* prepend un-acked frames to the beginning of the pending frame queue */
+ if (!list_empty(&bf_pending)) {
+ spin_lock_bh(&txq->axq_lock);
+ list_splice(&bf_pending, &tid->buf_q);
+ ath_tx_queue_tid(txq, tid);
+ spin_unlock_bh(&txq->axq_lock);
+ }
+
if (tid->state & AGGR_CLEANUP) {
if (tid->baw_head == tid->baw_tail) {
tid->state &= ~AGGR_ADDBA_COMPLETE;
@@ -499,14 +530,6 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,
return;
}

- /* prepend un-acked frames to the beginning of the pending frame queue */
- if (!list_empty(&bf_pending)) {
- spin_lock_bh(&txq->axq_lock);
- list_splice(&bf_pending, &tid->buf_q);
- ath_tx_queue_tid(txq, tid);
- spin_unlock_bh(&txq->axq_lock);
- }
-
rcu_read_unlock();

if (needreset)
@@ -2050,7 +2073,7 @@ static void ath_tx_rc_status(struct ath_buf *bf, struct ath_tx_status *ts,
tx_info->status.rates[i].idx = -1;
}

- tx_info->status.rates[tx_rateindex].count = bf->bf_retries + 1;
+ tx_info->status.rates[tx_rateindex].count = ts->ts_longretry + 1;
}

static void ath_wake_mac80211_queue(struct ath_softc *sc, struct ath_txq *txq)
@@ -2161,7 +2184,6 @@ static void ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq)
* This frame is sent out as a single frame.
* Use hardware retry status for this frame.
*/
- bf->bf_retries = ts.ts_longretry;
if (ts.ts_status & ATH9K_TXERR_XRETRY)
bf->bf_state.bf_type |= BUF_XRETRY;
ath_tx_rc_status(bf, &ts, 0, txok, true);
@@ -2280,7 +2302,6 @@ void ath_tx_edma_tasklet(struct ath_softc *sc)
txok = !(txs.ts_status & ATH9K_TXERR_MASK);

if (!bf_isampdu(bf)) {
- bf->bf_retries = txs.ts_longretry;
if (txs.ts_status & ATH9K_TXERR_XRETRY)
bf->bf_state.bf_type |= BUF_XRETRY;
ath_tx_rc_status(bf, &txs, 0, txok, true);
@@ -2449,37 +2470,37 @@ void ath_tx_node_init(struct ath_softc *sc, struct ath_node *an)

void ath_tx_node_cleanup(struct ath_softc *sc, struct ath_node *an)
{
- int i;
- struct ath_atx_ac *ac, *ac_tmp;
- struct ath_atx_tid *tid, *tid_tmp;
+ struct ath_atx_ac *ac;
+ struct ath_atx_tid *tid;
struct ath_txq *txq;
+ int i, tidno;

- for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) {
- if (ATH_TXQ_SETUP(sc, i)) {
- txq = &sc->tx.txq[i];
+ for (tidno = 0, tid = &an->tid[tidno];
+ tidno < WME_NUM_TID; tidno++, tid++) {
+ i = tid->ac->qnum;

- spin_lock_bh(&txq->axq_lock);
+ if (!ATH_TXQ_SETUP(sc, i))
+ continue;

- list_for_each_entry_safe(ac,
- ac_tmp, &txq->axq_acq, list) {
- tid = list_first_entry(&ac->tid_q,
- struct ath_atx_tid, list);
- if (tid && tid->an != an)
- continue;
- list_del(&ac->list);
- ac->sched = false;
-
- list_for_each_entry_safe(tid,
- tid_tmp, &ac->tid_q, list) {
- list_del(&tid->list);
- tid->sched = false;
- ath_tid_drain(sc, txq, tid);
- tid->state &= ~AGGR_ADDBA_COMPLETE;
- tid->state &= ~AGGR_CLEANUP;
- }
- }
+ txq = &sc->tx.txq[i];
+ ac = tid->ac;

- spin_unlock_bh(&txq->axq_lock);
+ spin_lock_bh(&txq->axq_lock);
+
+ if (tid->sched) {
+ list_del(&tid->list);
+ tid->sched = false;
+ }
+
+ if (ac->sched) {
+ list_del(&ac->list);
+ tid->ac->sched = false;
}
+
+ ath_tid_drain(sc, txq, tid);
+ tid->state &= ~AGGR_ADDBA_COMPLETE;
+ tid->state &= ~AGGR_CLEANUP;
+
+ spin_unlock_bh(&txq->axq_lock);
}
}
diff --git a/drivers/net/wireless/iwlwifi/iwl-scan.c b/drivers/net/wireless/iwlwifi/iwl-scan.c
index 386c5f9..e1af9fd 100644
--- a/drivers/net/wireless/iwlwifi/iwl-scan.c
+++ b/drivers/net/wireless/iwlwifi/iwl-scan.c
@@ -420,11 +420,10 @@ void iwl_bg_scan_check(struct work_struct *data)
return;

mutex_lock(&priv->mutex);
- if (test_bit(STATUS_SCANNING, &priv->status) ||
- test_bit(STATUS_SCAN_ABORTING, &priv->status)) {
- IWL_DEBUG_SCAN(priv, "Scan completion watchdog resetting "
- "adapter (%dms)\n",
- jiffies_to_msecs(IWL_SCAN_CHECK_WATCHDOG));
+ if (test_bit(STATUS_SCANNING, &priv->status) &&
+ !test_bit(STATUS_SCAN_ABORTING, &priv->status)) {
+ IWL_DEBUG_SCAN(priv, "Scan completion watchdog (%dms)\n",
+ jiffies_to_msecs(IWL_SCAN_CHECK_WATCHDOG));

if (!test_bit(STATUS_EXIT_PENDING, &priv->status))
iwl_send_scan_abort(priv);
@@ -489,12 +488,11 @@ void iwl_bg_abort_scan(struct work_struct *work)
!test_bit(STATUS_GEO_CONFIGURED, &priv->status))
return;

- mutex_lock(&priv->mutex);
-
- cancel_delayed_work_sync(&priv->scan_check);
- set_bit(STATUS_SCAN_ABORTING, &priv->status);
- iwl_send_scan_abort(priv);
+ cancel_delayed_work(&priv->scan_check);

+ mutex_lock(&priv->mutex);
+ if (test_bit(STATUS_SCAN_ABORTING, &priv->status))
+ iwl_send_scan_abort(priv);
mutex_unlock(&priv->mutex);
}
EXPORT_SYMBOL(iwl_bg_abort_scan);
diff --git a/drivers/net/xen-netfront.c b/drivers/net/xen-netfront.c
index d504e2b..b50fedc 100644
--- a/drivers/net/xen-netfront.c
+++ b/drivers/net/xen-netfront.c
@@ -1621,6 +1621,7 @@ static void backend_changed(struct xenbus_device *dev,
if (xennet_connect(netdev) != 0)
break;
xenbus_switch_state(dev, XenbusStateConnected);
+ netif_notify_peers(netdev);
break;

case XenbusStateClosing:
diff --git a/drivers/parisc/led.c b/drivers/parisc/led.c
index 188bc84..d02be78 100644
--- a/drivers/parisc/led.c
+++ b/drivers/parisc/led.c
@@ -176,16 +176,18 @@ static ssize_t led_proc_write(struct file *file, const char *buf,
size_t count, loff_t *pos)
{
void *data = PDE(file->f_path.dentry->d_inode)->data;
- char *cur, lbuf[count + 1];
+ char *cur, lbuf[32];
int d;

if (!capable(CAP_SYS_ADMIN))
return -EACCES;

- memset(lbuf, 0, count + 1);
+ if (count >= sizeof(lbuf))
+ count = sizeof(lbuf)-1;

if (copy_from_user(lbuf, buf, count))
return -EFAULT;
+ lbuf[count] = 0;

cur = lbuf;

diff --git a/drivers/ssb/driver_chipcommon.c b/drivers/ssb/driver_chipcommon.c
index 59ae76b..d9c7e54 100644
--- a/drivers/ssb/driver_chipcommon.c
+++ b/drivers/ssb/driver_chipcommon.c
@@ -235,6 +235,7 @@ void ssb_chipcommon_init(struct ssb_chipcommon *cc)
return; /* We don't have a ChipCommon */
if (cc->dev->id.revision >= 11)
cc->status = chipco_read32(cc, SSB_CHIPCO_CHIPSTAT);
+ ssb_dprintk(KERN_INFO PFX "chipcommon status is 0x%x\n", cc->status);
ssb_pmu_init(cc);
chipco_powercontrol_init(cc);
ssb_chipco_set_clockmode(cc, SSB_CLKMODE_FAST);
diff --git a/drivers/ssb/pci.c b/drivers/ssb/pci.c
index 6dcda86..6e88d2b 100644
--- a/drivers/ssb/pci.c
+++ b/drivers/ssb/pci.c
@@ -626,11 +626,22 @@ static int ssb_pci_sprom_get(struct ssb_bus *bus,
return -ENODEV;
}
if (bus->chipco.dev) { /* can be unavailible! */
- bus->sprom_offset = (bus->chipco.dev->id.revision < 31) ?
- SSB_SPROM_BASE1 : SSB_SPROM_BASE31;
+ /*
+ * get SPROM offset: SSB_SPROM_BASE1 except for
+ * chipcommon rev >= 31 or chip ID is 0x4312 and
+ * chipcommon status & 3 == 2
+ */
+ if (bus->chipco.dev->id.revision >= 31)
+ bus->sprom_offset = SSB_SPROM_BASE31;
+ else if (bus->chip_id == 0x4312 &&
+ (bus->chipco.status & 0x03) == 2)
+ bus->sprom_offset = SSB_SPROM_BASE31;
+ else
+ bus->sprom_offset = SSB_SPROM_BASE1;
} else {
bus->sprom_offset = SSB_SPROM_BASE1;
}
+ ssb_dprintk(KERN_INFO PFX "SPROM offset is 0x%x\n", bus->sprom_offset);

buf = kcalloc(SSB_SPROMSIZE_WORDS_R123, sizeof(u16), GFP_KERNEL);
if (!buf)
diff --git a/fs/block_dev.c b/fs/block_dev.c
index 99d6af8..b3171fb 100644
--- a/fs/block_dev.c
+++ b/fs/block_dev.c
@@ -681,8 +681,8 @@ retry:
if (!bd_may_claim(bdev, whole, holder))
return -EBUSY;

- /* if someone else is claiming, wait for it to finish */
- if (whole->bd_claiming && whole->bd_claiming != holder) {
+ /* if claiming is already in progress, wait for it to finish */
+ if (whole->bd_claiming) {
wait_queue_head_t *wq = bit_waitqueue(&whole->bd_claiming, 0);
DEFINE_WAIT(wait);

diff --git a/include/drm/drm_pciids.h b/include/drm/drm_pciids.h
index 2d428b0..3a9940e 100644
--- a/include/drm/drm_pciids.h
+++ b/include/drm/drm_pciids.h
@@ -146,6 +146,8 @@
{0x1002, 0x6888, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CYPRESS|RADEON_NEW_MEMMAP}, \
{0x1002, 0x6889, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CYPRESS|RADEON_NEW_MEMMAP}, \
{0x1002, 0x688A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CYPRESS|RADEON_NEW_MEMMAP}, \
+ {0x1002, 0x688C, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CYPRESS|RADEON_NEW_MEMMAP}, \
+ {0x1002, 0x688D, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CYPRESS|RADEON_NEW_MEMMAP}, \
{0x1002, 0x6898, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CYPRESS|RADEON_NEW_MEMMAP}, \
{0x1002, 0x6899, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CYPRESS|RADEON_NEW_MEMMAP}, \
{0x1002, 0x689c, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_HEMLOCK|RADEON_NEW_MEMMAP}, \
@@ -161,6 +163,7 @@
{0x1002, 0x68be, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_JUNIPER|RADEON_NEW_MEMMAP}, \
{0x1002, 0x68c0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_REDWOOD|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
{0x1002, 0x68c1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_REDWOOD|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
+ {0x1002, 0x68c7, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_REDWOOD|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
{0x1002, 0x68c8, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_REDWOOD|RADEON_NEW_MEMMAP}, \
{0x1002, 0x68c9, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_REDWOOD|RADEON_NEW_MEMMAP}, \
{0x1002, 0x68d8, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_REDWOOD|RADEON_NEW_MEMMAP}, \
@@ -174,6 +177,7 @@
{0x1002, 0x68e8, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CEDAR|RADEON_NEW_MEMMAP}, \
{0x1002, 0x68e9, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CEDAR|RADEON_NEW_MEMMAP}, \
{0x1002, 0x68f1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CEDAR|RADEON_NEW_MEMMAP}, \
+ {0x1002, 0x68f2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CEDAR|RADEON_NEW_MEMMAP}, \
{0x1002, 0x68f8, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CEDAR|RADEON_NEW_MEMMAP}, \
{0x1002, 0x68f9, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CEDAR|RADEON_NEW_MEMMAP}, \
{0x1002, 0x68fe, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CEDAR|RADEON_NEW_MEMMAP}, \
@@ -314,6 +318,7 @@
{0x1002, 0x9456, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV770|RADEON_NEW_MEMMAP}, \
{0x1002, 0x945A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV770|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
{0x1002, 0x945B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV770|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
+ {0x1002, 0x945E, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV770|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
{0x1002, 0x9460, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV770|RADEON_NEW_MEMMAP}, \
{0x1002, 0x9462, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV770|RADEON_NEW_MEMMAP}, \
{0x1002, 0x946A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV770|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
@@ -324,6 +329,7 @@
{0x1002, 0x9487, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV730|RADEON_NEW_MEMMAP}, \
{0x1002, 0x9488, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV730|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
{0x1002, 0x9489, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV730|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
+ {0x1002, 0x948A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV730|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
{0x1002, 0x948F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV730|RADEON_NEW_MEMMAP}, \
{0x1002, 0x9490, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV730|RADEON_NEW_MEMMAP}, \
{0x1002, 0x9491, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV730|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
@@ -366,6 +372,7 @@
{0x1002, 0x9553, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV710|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
{0x1002, 0x9555, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV710|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
{0x1002, 0x9557, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV710|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
+ {0x1002, 0x955f, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV710|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
{0x1002, 0x9580, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV630|RADEON_NEW_MEMMAP}, \
{0x1002, 0x9581, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV630|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
{0x1002, 0x9583, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV630|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index b21e405..142bf18 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -1775,6 +1775,8 @@ extern void netif_carrier_on(struct net_device *dev);

extern void netif_carrier_off(struct net_device *dev);

+extern void netif_notify_peers(struct net_device *dev);
+
/**
* netif_dormant_on - mark device as dormant.
* @dev: network device
diff --git a/include/linux/notifier.h b/include/linux/notifier.h
index 540703b..22c2abb 100644
--- a/include/linux/notifier.h
+++ b/include/linux/notifier.h
@@ -210,6 +210,7 @@ static inline int notifier_to_errno(int ret)
#define NETDEV_POST_INIT 0x0010
#define NETDEV_UNREGISTER_BATCH 0x0011
#define NETDEV_BONDING_DESLAVE 0x0012
+#define NETDEV_NOTIFY_PEERS 0x0012

#define SYS_DOWN 0x0001 /* Notify of system down */
#define SYS_RESTART SYS_DOWN
diff --git a/kernel/signal.c b/kernel/signal.c
index 906ae5a..bded651 100644
--- a/kernel/signal.c
+++ b/kernel/signal.c
@@ -637,7 +637,7 @@ static inline bool si_fromuser(const struct siginfo *info)

/*
* Bad permissions for sending the signal
- * - the caller must hold at least the RCU read lock
+ * - the caller must hold the RCU read lock
*/
static int check_kill_permission(int sig, struct siginfo *info,
struct task_struct *t)
@@ -1127,11 +1127,14 @@ struct sighand_struct *lock_task_sighand(struct task_struct *tsk, unsigned long

/*
* send signal info to all the members of a group
- * - the caller must hold the RCU read lock at least
*/
int group_send_sig_info(int sig, struct siginfo *info, struct task_struct *p)
{
- int ret = check_kill_permission(sig, info, p);
+ int ret;
+
+ rcu_read_lock();
+ ret = check_kill_permission(sig, info, p);
+ rcu_read_unlock();

if (!ret && sig)
ret = do_send_sig_info(sig, info, p, true);
diff --git a/net/9p/trans_fd.c b/net/9p/trans_fd.c
index 98ce9bc..c85109d 100644
--- a/net/9p/trans_fd.c
+++ b/net/9p/trans_fd.c
@@ -948,7 +948,7 @@ p9_fd_create_unix(struct p9_client *client, const char *addr, char *args)

csocket = NULL;

- if (strlen(addr) > UNIX_PATH_MAX) {
+ if (strlen(addr) >= UNIX_PATH_MAX) {
P9_EPRINTK(KERN_ERR, "p9_trans_unix: address too long: %s\n",
addr);
return -ENAMETOOLONG;
diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c
index 382bc76..da14c49 100644
--- a/net/ipv4/devinet.c
+++ b/net/ipv4/devinet.c
@@ -1081,6 +1081,7 @@ static int inetdev_event(struct notifier_block *this, unsigned long event,
}
ip_mc_up(in_dev);
/* fall through */
+ case NETDEV_NOTIFY_PEERS:
case NETDEV_CHANGEADDR:
/* Send gratuitous ARP to notify of link change */
if (IN_DEV_ARP_NOTIFY(in_dev)) {
diff --git a/net/mac80211/mesh_plink.c b/net/mac80211/mesh_plink.c
index 3cd5f7b..ea13a80 100644
--- a/net/mac80211/mesh_plink.c
+++ b/net/mac80211/mesh_plink.c
@@ -65,7 +65,6 @@ void mesh_plink_inc_estab_count(struct ieee80211_sub_if_data *sdata)
{
atomic_inc(&sdata->u.mesh.mshstats.estab_plinks);
mesh_accept_plinks_update(sdata);
- ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON);
}

static inline
@@ -73,7 +72,6 @@ void mesh_plink_dec_estab_count(struct ieee80211_sub_if_data *sdata)
{
atomic_dec(&sdata->u.mesh.mshstats.estab_plinks);
mesh_accept_plinks_update(sdata);
- ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON);
}

/**
@@ -115,7 +113,7 @@ static struct sta_info *mesh_plink_alloc(struct ieee80211_sub_if_data *sdata,
}

/**
- * mesh_plink_deactivate - deactivate mesh peer link
+ * __mesh_plink_deactivate - deactivate mesh peer link
*
* @sta: mesh peer link to deactivate
*
@@ -123,18 +121,23 @@ static struct sta_info *mesh_plink_alloc(struct ieee80211_sub_if_data *sdata,
*
* Locking: the caller must hold sta->lock
*/
-static void __mesh_plink_deactivate(struct sta_info *sta)
+static bool __mesh_plink_deactivate(struct sta_info *sta)
{
struct ieee80211_sub_if_data *sdata = sta->sdata;
+ bool deactivated = false;

- if (sta->plink_state == PLINK_ESTAB)
+ if (sta->plink_state == PLINK_ESTAB) {
mesh_plink_dec_estab_count(sdata);
+ deactivated = true;
+ }
sta->plink_state = PLINK_BLOCKED;
mesh_path_flush_by_nexthop(sta);
+
+ return deactivated;
}

/**
- * __mesh_plink_deactivate - deactivate mesh peer link
+ * mesh_plink_deactivate - deactivate mesh peer link
*
* @sta: mesh peer link to deactivate
*
@@ -142,9 +145,15 @@ static void __mesh_plink_deactivate(struct sta_info *sta)
*/
void mesh_plink_deactivate(struct sta_info *sta)
{
+ struct ieee80211_sub_if_data *sdata = sta->sdata;
+ bool deactivated;
+
spin_lock_bh(&sta->lock);
- __mesh_plink_deactivate(sta);
+ deactivated = __mesh_plink_deactivate(sta);
spin_unlock_bh(&sta->lock);
+
+ if (deactivated)
+ ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON);
}

static int mesh_plink_frame_tx(struct ieee80211_sub_if_data *sdata,
@@ -381,10 +390,16 @@ int mesh_plink_open(struct sta_info *sta)

void mesh_plink_block(struct sta_info *sta)
{
+ struct ieee80211_sub_if_data *sdata = sta->sdata;
+ bool deactivated;
+
spin_lock_bh(&sta->lock);
- __mesh_plink_deactivate(sta);
+ deactivated = __mesh_plink_deactivate(sta);
sta->plink_state = PLINK_BLOCKED;
spin_unlock_bh(&sta->lock);
+
+ if (deactivated)
+ ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON);
}


@@ -397,6 +412,7 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m
enum plink_event event;
enum plink_frame_type ftype;
size_t baselen;
+ bool deactivated;
u8 ie_len;
u8 *baseaddr;
__le16 plid, llid, reason;
@@ -651,8 +667,9 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m
case CNF_ACPT:
del_timer(&sta->plink_timer);
sta->plink_state = PLINK_ESTAB;
- mesh_plink_inc_estab_count(sdata);
spin_unlock_bh(&sta->lock);
+ mesh_plink_inc_estab_count(sdata);
+ ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON);
mpl_dbg("Mesh plink with %pM ESTABLISHED\n",
sta->sta.addr);
break;
@@ -684,8 +701,9 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m
case OPN_ACPT:
del_timer(&sta->plink_timer);
sta->plink_state = PLINK_ESTAB;
- mesh_plink_inc_estab_count(sdata);
spin_unlock_bh(&sta->lock);
+ mesh_plink_inc_estab_count(sdata);
+ ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON);
mpl_dbg("Mesh plink with %pM ESTABLISHED\n",
sta->sta.addr);
mesh_plink_frame_tx(sdata, PLINK_CONFIRM, sta->sta.addr, llid,
@@ -702,11 +720,13 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m
case CLS_ACPT:
reason = cpu_to_le16(MESH_CLOSE_RCVD);
sta->reason = reason;
- __mesh_plink_deactivate(sta);
+ deactivated = __mesh_plink_deactivate(sta);
sta->plink_state = PLINK_HOLDING;
llid = sta->llid;
mod_plink_timer(sta, dot11MeshHoldingTimeout(sdata));
spin_unlock_bh(&sta->lock);
+ if (deactivated)
+ ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON);
mesh_plink_frame_tx(sdata, PLINK_CLOSE, sta->sta.addr, llid,
plid, reason);
break;
diff --git a/net/sched/sch_generic.c b/net/sched/sch_generic.c
index a63029e..bd1892f 100644
--- a/net/sched/sch_generic.c
+++ b/net/sched/sch_generic.c
@@ -327,6 +327,24 @@ void netif_carrier_off(struct net_device *dev)
}
EXPORT_SYMBOL(netif_carrier_off);

+/**
+ * netif_notify_peers - notify network peers about existence of @dev
+ * @dev: network device
+ *
+ * Generate traffic such that interested network peers are aware of
+ * @dev, such as by generating a gratuitous ARP. This may be used when
+ * a device wants to inform the rest of the network about some sort of
+ * reconfiguration such as a failover event or virtual machine
+ * migration.
+ */
+void netif_notify_peers(struct net_device *dev)
+{
+ rtnl_lock();
+ call_netdevice_notifiers(NETDEV_NOTIFY_PEERS, dev);
+ rtnl_unlock();
+}
+EXPORT_SYMBOL(netif_notify_peers);
+
/* "NOOP" scheduler: the best scheduler, recommended for all interfaces
under all circumstances. It is difficult to invent anything faster or
cheaper.
diff --git a/net/wireless/mlme.c b/net/wireless/mlme.c
index 48ead6f..ef17fcf 100644
--- a/net/wireless/mlme.c
+++ b/net/wireless/mlme.c
@@ -44,10 +44,10 @@ void cfg80211_send_rx_auth(struct net_device *dev, const u8 *buf, size_t len)
}
}

- WARN_ON(!done);
-
- nl80211_send_rx_auth(rdev, dev, buf, len, GFP_KERNEL);
- cfg80211_sme_rx_auth(dev, buf, len);
+ if (done) {
+ nl80211_send_rx_auth(rdev, dev, buf, len, GFP_KERNEL);
+ cfg80211_sme_rx_auth(dev, buf, len);
+ }

wdev_unlock(wdev);
}
diff --git a/net/wireless/scan.c b/net/wireless/scan.c
index 58401d2..5ca8c71 100644
--- a/net/wireless/scan.c
+++ b/net/wireless/scan.c
@@ -275,6 +275,7 @@ struct cfg80211_bss *cfg80211_get_bss(struct wiphy *wiphy,
{
struct cfg80211_registered_device *dev = wiphy_to_dev(wiphy);
struct cfg80211_internal_bss *bss, *res = NULL;
+ unsigned long now = jiffies;

spin_lock_bh(&dev->bss_lock);

@@ -283,6 +284,10 @@ struct cfg80211_bss *cfg80211_get_bss(struct wiphy *wiphy,
continue;
if (channel && bss->pub.channel != channel)
continue;
+ /* Don't get expired BSS structs */
+ if (time_after(now, bss->ts + IEEE80211_SCAN_RESULT_EXPIRE) &&
+ !atomic_read(&bss->hold))
+ continue;
if (is_bss(&bss->pub, bssid, ssid, ssid_len)) {
res = bss;
kref_get(&res->ref);
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/