From ed10f95d60d41033d356fdcf88c240d7065bd5b4 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Mon, 29 Jun 2009 18:29:11 +1000 Subject: drm/radeon/kms: fix some GART table entry bugs. 1. rv370 can accept 40-bit addresses - also at 24-bit shift not 4 bits 2. rs480 table can be in 40-bit space. - 4 bit shift for top 8 bits 3. rs480 table entries can be in 40-bit space. Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/r100.c | 2 +- drivers/gpu/drm/radeon/r300.c | 4 +++- drivers/gpu/drm/radeon/radeon_gart.c | 2 +- drivers/gpu/drm/radeon/rs400.c | 13 +++++++++++-- 4 files changed, 16 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/radeon/r100.c b/drivers/gpu/drm/radeon/r100.c index c550932a108f..1b23106f9552 100644 --- a/drivers/gpu/drm/radeon/r100.c +++ b/drivers/gpu/drm/radeon/r100.c @@ -110,7 +110,7 @@ int r100_pci_gart_set_page(struct radeon_device *rdev, int i, uint64_t addr) if (i < 0 || i > rdev->gart.num_gpu_pages) { return -EINVAL; } - rdev->gart.table.ram.ptr[i] = cpu_to_le32((uint32_t)addr); + rdev->gart.table.ram.ptr[i] = cpu_to_le32(lower_32_bits(addr)); return 0; } diff --git a/drivers/gpu/drm/radeon/r300.c b/drivers/gpu/drm/radeon/r300.c index e2ed5bc08170..cd9ea98e9c6f 100644 --- a/drivers/gpu/drm/radeon/r300.c +++ b/drivers/gpu/drm/radeon/r300.c @@ -150,7 +150,9 @@ int rv370_pcie_gart_set_page(struct radeon_device *rdev, int i, uint64_t addr) if (i < 0 || i > rdev->gart.num_gpu_pages) { return -EINVAL; } - addr = (((u32)addr) >> 8) | ((upper_32_bits(addr) & 0xff) << 4) | 0xC; + addr = (lower_32_bits(addr) >> 8) | + ((upper_32_bits(addr) & 0xff) << 24) | + 0xc; writel(cpu_to_le32(addr), ((void __iomem *)ptr) + (i * 4)); return 0; } diff --git a/drivers/gpu/drm/radeon/radeon_gart.c b/drivers/gpu/drm/radeon/radeon_gart.c index d343a15316ec..2977539880fb 100644 --- a/drivers/gpu/drm/radeon/radeon_gart.c +++ b/drivers/gpu/drm/radeon/radeon_gart.c @@ -177,7 +177,7 @@ int radeon_gart_bind(struct radeon_device *rdev, unsigned offset, return -ENOMEM; } rdev->gart.pages[p] = pagelist[i]; - page_base = (uint32_t)rdev->gart.pages_addr[p]; + page_base = rdev->gart.pages_addr[p]; for (j = 0; j < (PAGE_SIZE / 4096); j++, t++) { radeon_gart_set_page(rdev, t, page_base); page_base += 4096; diff --git a/drivers/gpu/drm/radeon/rs400.c b/drivers/gpu/drm/radeon/rs400.c index cc074b5a8f74..3275de4b6e3b 100644 --- a/drivers/gpu/drm/radeon/rs400.c +++ b/drivers/gpu/drm/radeon/rs400.c @@ -164,7 +164,9 @@ int rs400_gart_enable(struct radeon_device *rdev) WREG32(RADEON_BUS_CNTL, tmp); } /* Table should be in 32bits address space so ignore bits above. */ - tmp = rdev->gart.table_addr & 0xfffff000; + tmp = (u32)rdev->gart.table_addr & 0xfffff000; + tmp |= (upper_32_bits(rdev->gart.table_addr) & 0xff) << 4; + WREG32_MC(RS480_GART_BASE, tmp); /* TODO: more tweaking here */ WREG32_MC(RS480_GART_FEATURE_ID, @@ -201,10 +203,17 @@ void rs400_gart_disable(struct radeon_device *rdev) int rs400_gart_set_page(struct radeon_device *rdev, int i, uint64_t addr) { + uint32_t entry; + if (i < 0 || i > rdev->gart.num_gpu_pages) { return -EINVAL; } - rdev->gart.table.ram.ptr[i] = cpu_to_le32(((uint32_t)addr) | 0xC); + + entry = (lower_32_bits(addr) & PAGE_MASK) | + ((upper_32_bits(addr) & 0xff) << 4) | + 0xc; + entry = cpu_to_le32(entry); + rdev->gart.table.ram.ptr[i] = entry; return 0; } -- cgit v1.2.3 From 4c9bc75cbc6f2f447a38a123aa6e0605fab3cb7a Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Mon, 29 Jun 2009 18:29:12 +1000 Subject: drm/radeon/kms: mmio base/size should be resource_size_t. Unsigned long is incorrect for 64-bit resources on 32-bit hw. Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/radeon.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h index d61f2fc61df5..e7662ba9abfb 100644 --- a/drivers/gpu/drm/radeon/radeon.h +++ b/drivers/gpu/drm/radeon/radeon.h @@ -594,8 +594,8 @@ struct radeon_device { struct radeon_object *fbdev_robj; struct radeon_framebuffer *fbdev_rfb; /* Register mmio */ - unsigned long rmmio_base; - unsigned long rmmio_size; + resource_size_t rmmio_base; + resource_size_t rmmio_size; void *rmmio; radeon_rreg_t mm_rreg; radeon_wreg_t mm_wreg; -- cgit v1.2.3 From 6cdf65855cf884712532fc72770baaef7bdf1b9a Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Mon, 29 Jun 2009 18:29:13 +1000 Subject: drm/radeon/kms: remove IB flushing trick. If there is a problem then this is hiding it, we shouldn't ever need to flush the IB. Either the buffers are: WB - caching just works. WC - no need to do explicit flush, the MB + readback will do it Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/radeon_ring.c | 15 +-------------- 1 file changed, 1 insertion(+), 14 deletions(-) diff --git a/drivers/gpu/drm/radeon/radeon_ring.c b/drivers/gpu/drm/radeon/radeon_ring.c index a853261d1881..60d159308b88 100644 --- a/drivers/gpu/drm/radeon/radeon_ring.c +++ b/drivers/gpu/drm/radeon/radeon_ring.c @@ -126,32 +126,19 @@ static void radeon_ib_align(struct radeon_device *rdev, struct radeon_ib *ib) } } -static void radeon_ib_cpu_flush(struct radeon_device *rdev, - struct radeon_ib *ib) -{ - unsigned long tmp; - unsigned i; - - /* To force CPU cache flush ugly but seems reliable */ - for (i = 0; i < ib->length_dw; i += (rdev->cp.align_mask + 1)) { - tmp = readl(&ib->ptr[i]); - } -} - int radeon_ib_schedule(struct radeon_device *rdev, struct radeon_ib *ib) { int r = 0; mutex_lock(&rdev->ib_pool.mutex); radeon_ib_align(rdev, ib); - radeon_ib_cpu_flush(rdev, ib); if (!ib->length_dw || !rdev->cp.ready) { /* TODO: Nothings in the ib we should report. */ mutex_unlock(&rdev->ib_pool.mutex); DRM_ERROR("radeon: couldn't schedule IB(%lu).\n", ib->idx); return -EINVAL; } - /* 64 dwords should be enought for fence too */ + /* 64 dwords should be enough for fence too */ r = radeon_ring_lock(rdev, 64); if (r) { DRM_ERROR("radeon: scheduling IB failled (%d).\n", r); -- cgit v1.2.3 From 4162338a1dab388474d4115289d1d7071623f04d Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Thu, 9 Jul 2009 15:04:19 +1000 Subject: drm/radeon/kms: set crtc and cursor offsets correctly on legacy chips. The crtc and cursor offsets on the legacy chips are offset from DISPLAY_BASE_ADDR. The code worked if display base addr was at 0, but otherwise falls to pieces. Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/radeon_cursor.c | 2 +- drivers/gpu/drm/radeon/radeon_legacy_crtc.c | 11 +++++++---- drivers/gpu/drm/radeon/radeon_mode.h | 1 + 3 files changed, 9 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/radeon/radeon_cursor.c b/drivers/gpu/drm/radeon/radeon_cursor.c index 5232441f119b..5f8ce370c4f8 100644 --- a/drivers/gpu/drm/radeon/radeon_cursor.c +++ b/drivers/gpu/drm/radeon/radeon_cursor.c @@ -113,7 +113,7 @@ static void radeon_set_cursor(struct drm_crtc *crtc, struct drm_gem_object *obj, WREG32(AVIVO_D1CUR_SURFACE_ADDRESS + radeon_crtc->crtc_offset, gpu_addr); else /* offset is from DISP(2)_BASE_ADDRESS */ - WREG32(RADEON_CUR_OFFSET + radeon_crtc->crtc_offset, gpu_addr); + WREG32(RADEON_CUR_OFFSET + radeon_crtc->crtc_offset, (gpu_addr-radeon_crtc->legacy_display_base_addr)); } int radeon_crtc_cursor_set(struct drm_crtc *crtc, diff --git a/drivers/gpu/drm/radeon/radeon_legacy_crtc.c b/drivers/gpu/drm/radeon/radeon_legacy_crtc.c index 8086ecf7f03d..14c1a5107fc9 100644 --- a/drivers/gpu/drm/radeon/radeon_legacy_crtc.c +++ b/drivers/gpu/drm/radeon/radeon_legacy_crtc.c @@ -244,7 +244,12 @@ int radeon_crtc_set_base(struct drm_crtc *crtc, int x, int y, if (radeon_gem_object_pin(obj, RADEON_GEM_DOMAIN_VRAM, &base)) { return -EINVAL; } - crtc_offset = (u32)base; + /* if scanout was in GTT this really wouldn't work */ + /* crtc offset is from display base addr not FB location */ + radeon_crtc->legacy_display_base_addr = rdev->mc.vram_location; + + base -= radeon_crtc->legacy_display_base_addr; + crtc_offset_cntl = 0; pitch_pixels = crtc->fb->pitch / (crtc->fb->bits_per_pixel / 8); @@ -303,11 +308,9 @@ int radeon_crtc_set_base(struct drm_crtc *crtc, int x, int y, base &= ~7; - /* update sarea TODO */ - crtc_offset = (u32)base; - WREG32(RADEON_DISPLAY_BASE_ADDR + radeon_crtc->crtc_offset, rdev->mc.vram_location); + WREG32(RADEON_DISPLAY_BASE_ADDR + radeon_crtc->crtc_offset, radeon_crtc->legacy_display_base_addr); if (ASIC_IS_R300(rdev)) { if (radeon_crtc->crtc_id) diff --git a/drivers/gpu/drm/radeon/radeon_mode.h b/drivers/gpu/drm/radeon/radeon_mode.h index 9173b687462b..86f766e868e7 100644 --- a/drivers/gpu/drm/radeon/radeon_mode.h +++ b/drivers/gpu/drm/radeon/radeon_mode.h @@ -185,6 +185,7 @@ struct radeon_crtc { uint64_t cursor_addr; int cursor_width; int cursor_height; + uint32_t legacy_display_base_addr; }; #define RADEON_USE_RMX 1 -- cgit v1.2.3 From 3e43d82125952826202a8cd20ba84a66f3ff8808 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Thu, 9 Jul 2009 15:04:18 +1000 Subject: drm/radeon/kms: respect TOM on rs100->rs480 IGP variants. Normally we are free to place VRAM where we want in the GPUs memory address space, however on IGP chips the VRAM is actual RAM, and no special translation or aperture is used inside the GPU MC. So when you move the VRAM aperture away from the TOM register, you actually move it into main memory and can trash things quite badly. This commit makes the code respect the TOM location for MC_FB_LOCATION. Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/r100.c | 5 ++++- drivers/gpu/drm/radeon/rs400.c | 6 ++++-- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/radeon/r100.c b/drivers/gpu/drm/radeon/r100.c index 1b23106f9552..a3db56bb013d 100644 --- a/drivers/gpu/drm/radeon/r100.c +++ b/drivers/gpu/drm/radeon/r100.c @@ -215,7 +215,6 @@ int r100_mc_init(struct radeon_device *rdev) r100_pci_gart_disable(rdev); /* Setup GPU memory space */ - rdev->mc.vram_location = 0xFFFFFFFFUL; rdev->mc.gtt_location = 0xFFFFFFFFUL; if (rdev->flags & RADEON_IS_AGP) { r = radeon_agp_init(rdev); @@ -1265,6 +1264,8 @@ void r100_vram_info(struct radeon_device *rdev) /* read NB_TOM to get the amount of ram stolen for the GPU */ tom = RREG32(RADEON_NB_TOM); rdev->mc.vram_size = (((tom >> 16) - (tom & 0xffff) + 1) << 16); + /* for IGPs we need to keep VRAM where it was put by the BIOS */ + rdev->mc.vram_location = (tom & 0xffff) << 16; WREG32(RADEON_CONFIG_MEMSIZE, rdev->mc.vram_size); } else { rdev->mc.vram_size = RREG32(RADEON_CONFIG_MEMSIZE); @@ -1275,6 +1276,8 @@ void r100_vram_info(struct radeon_device *rdev) rdev->mc.vram_size = 8192 * 1024; WREG32(RADEON_CONFIG_MEMSIZE, rdev->mc.vram_size); } + /* let driver place VRAM */ + rdev->mc.vram_location = 0xFFFFFFFFUL; } rdev->mc.aper_base = drm_get_resource_start(rdev->ddev, 0); diff --git a/drivers/gpu/drm/radeon/rs400.c b/drivers/gpu/drm/radeon/rs400.c index 3275de4b6e3b..a18d053065c0 100644 --- a/drivers/gpu/drm/radeon/rs400.c +++ b/drivers/gpu/drm/radeon/rs400.c @@ -235,7 +235,6 @@ int rs400_mc_init(struct radeon_device *rdev) rdev->mc.gtt_location = rdev->mc.vram_size; rdev->mc.gtt_location += (rdev->mc.gtt_size - 1); rdev->mc.gtt_location &= ~(rdev->mc.gtt_size - 1); - rdev->mc.vram_location = 0xFFFFFFFFUL; r = radeon_mc_setup(rdev); if (r) { return r; @@ -305,7 +304,10 @@ void rs400_vram_info(struct radeon_device *rdev) rdev->mc.vram_size = (((tom >> 16) - (tom & 0xffff) + 1) << 16); WREG32(RADEON_CONFIG_MEMSIZE, rdev->mc.vram_size); - /* Could aper size report 0 ? */ + /* RS480 IGPs don't seem to translate to main RAM, they + * just reserve and scan out of it. So setting VRAM location + * to say 0, will actually trash the OS. */ + rdev->mc.vram_location = (tom & 0xffff) << 16; rdev->mc.aper_base = drm_get_resource_start(rdev->ddev, 0); rdev->mc.aper_size = drm_get_resource_len(rdev->ddev, 0); } -- cgit v1.2.3 From 531369e62649bb8f31217cc0bf33ee6f89f1dff6 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Mon, 29 Jun 2009 11:21:25 +1000 Subject: drm/radeon: fix support for vline relocations. Userspace sends us a special relocation type to sync video/exa to vlines to avoid tearing, this deals with the relocation in the kernel, it picks the correct crtc and avoids issues where crtcs are disabled. This version also parses the wait until to make sure it isn't trying to do anything evil. Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/r100.c | 105 ++++++++++++++++++++++++++++++++++++++ drivers/gpu/drm/radeon/r300.c | 13 ++++- drivers/gpu/drm/radeon/r500_reg.h | 2 + drivers/gpu/drm/radeon/rv515.c | 23 +++++++-- 4 files changed, 137 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/radeon/r100.c b/drivers/gpu/drm/radeon/r100.c index a3db56bb013d..154648a2c027 100644 --- a/drivers/gpu/drm/radeon/r100.c +++ b/drivers/gpu/drm/radeon/r100.c @@ -751,6 +751,102 @@ int r100_cs_packet_parse(struct radeon_cs_parser *p, return 0; } +/** + * r100_cs_packet_next_vline() - parse userspace VLINE packet + * @parser: parser structure holding parsing context. + * + * Userspace sends a special sequence for VLINE waits. + * PACKET0 - VLINE_START_END + value + * PACKET0 - WAIT_UNTIL +_value + * RELOC (P3) - crtc_id in reloc. + * + * This function parses this and relocates the VLINE START END + * and WAIT UNTIL packets to the correct crtc. + * It also detects a switched off crtc and nulls out the + * wait in that case. + */ +int r100_cs_packet_parse_vline(struct radeon_cs_parser *p) +{ + struct radeon_cs_chunk *ib_chunk; + struct drm_mode_object *obj; + struct drm_crtc *crtc; + struct radeon_crtc *radeon_crtc; + struct radeon_cs_packet p3reloc, waitreloc; + int crtc_id; + int r; + uint32_t header, h_idx, reg; + + ib_chunk = &p->chunks[p->chunk_ib_idx]; + + /* parse the wait until */ + r = r100_cs_packet_parse(p, &waitreloc, p->idx); + if (r) + return r; + + /* check its a wait until and only 1 count */ + if (waitreloc.reg != RADEON_WAIT_UNTIL || + waitreloc.count != 0) { + DRM_ERROR("vline wait had illegal wait until segment\n"); + r = -EINVAL; + return r; + } + + if (ib_chunk->kdata[waitreloc.idx + 1] != RADEON_WAIT_CRTC_VLINE) { + DRM_ERROR("vline wait had illegal wait until\n"); + r = -EINVAL; + return r; + } + + /* jump over the NOP */ + r = r100_cs_packet_parse(p, &p3reloc, p->idx); + if (r) + return r; + + h_idx = p->idx - 2; + p->idx += waitreloc.count; + p->idx += p3reloc.count; + + header = ib_chunk->kdata[h_idx]; + crtc_id = ib_chunk->kdata[h_idx + 5]; + reg = ib_chunk->kdata[h_idx] >> 2; + mutex_lock(&p->rdev->ddev->mode_config.mutex); + obj = drm_mode_object_find(p->rdev->ddev, crtc_id, DRM_MODE_OBJECT_CRTC); + if (!obj) { + DRM_ERROR("cannot find crtc %d\n", crtc_id); + r = -EINVAL; + goto out; + } + crtc = obj_to_crtc(obj); + radeon_crtc = to_radeon_crtc(crtc); + crtc_id = radeon_crtc->crtc_id; + + if (!crtc->enabled) { + /* if the CRTC isn't enabled - we need to nop out the wait until */ + ib_chunk->kdata[h_idx + 2] = PACKET2(0); + ib_chunk->kdata[h_idx + 3] = PACKET2(0); + } else if (crtc_id == 1) { + switch (reg) { + case AVIVO_D1MODE_VLINE_START_END: + header &= R300_CP_PACKET0_REG_MASK; + header |= AVIVO_D2MODE_VLINE_START_END >> 2; + break; + case RADEON_CRTC_GUI_TRIG_VLINE: + header &= R300_CP_PACKET0_REG_MASK; + header |= RADEON_CRTC2_GUI_TRIG_VLINE >> 2; + break; + default: + DRM_ERROR("unknown crtc reloc\n"); + r = -EINVAL; + goto out; + } + ib_chunk->kdata[h_idx] = header; + ib_chunk->kdata[h_idx + 3] |= RADEON_ENG_DISPLAY_SELECT_CRTC1; + } +out: + mutex_unlock(&p->rdev->ddev->mode_config.mutex); + return r; +} + /** * r100_cs_packet_next_reloc() - parse next packet which should be reloc packet3 * @parser: parser structure holding parsing context. @@ -824,6 +920,15 @@ static int r100_packet0_check(struct radeon_cs_parser *p, } for (i = 0; i <= pkt->count; i++, idx++, reg += 4) { switch (reg) { + case RADEON_CRTC_GUI_TRIG_VLINE: + r = r100_cs_packet_parse_vline(p); + if (r) { + DRM_ERROR("No reloc for ib[%d]=0x%04X\n", + idx, reg); + r100_cs_dump_packet(p, pkt); + return r; + } + break; /* FIXME: only allow PACKET3 blit? easier to check for out of * range access */ case RADEON_DST_PITCH_OFFSET: diff --git a/drivers/gpu/drm/radeon/r300.c b/drivers/gpu/drm/radeon/r300.c index cd9ea98e9c6f..656d9238bb06 100644 --- a/drivers/gpu/drm/radeon/r300.c +++ b/drivers/gpu/drm/radeon/r300.c @@ -44,6 +44,7 @@ int r100_gui_wait_for_idle(struct radeon_device *rdev); int r100_cs_packet_parse(struct radeon_cs_parser *p, struct radeon_cs_packet *pkt, unsigned idx); +int r100_cs_packet_parse_vline(struct radeon_cs_parser *p); int r100_cs_packet_next_reloc(struct radeon_cs_parser *p, struct radeon_cs_reloc **cs_reloc); int r100_cs_parse_packet0(struct radeon_cs_parser *p, @@ -972,7 +973,7 @@ static inline void r300_cs_track_clear(struct r300_cs_track *track) static const unsigned r300_reg_safe_bm[159] = { 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, - 0xFFFFFFBF, 0xFFFFFFFF, 0xFFFFFFBF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, @@ -1029,6 +1030,16 @@ static int r300_packet0_check(struct radeon_cs_parser *p, ib_chunk = &p->chunks[p->chunk_ib_idx]; track = (struct r300_cs_track*)p->track; switch(reg) { + case AVIVO_D1MODE_VLINE_START_END: + case RADEON_CRTC_GUI_TRIG_VLINE: + r = r100_cs_packet_parse_vline(p); + if (r) { + DRM_ERROR("No reloc for ib[%d]=0x%04X\n", + idx, reg); + r100_cs_dump_packet(p, pkt); + return r; + } + break; case RADEON_DST_PITCH_OFFSET: case RADEON_SRC_PITCH_OFFSET: r = r100_cs_packet_next_reloc(p, &reloc); diff --git a/drivers/gpu/drm/radeon/r500_reg.h b/drivers/gpu/drm/radeon/r500_reg.h index 9070a1c2ce23..036691b38cb7 100644 --- a/drivers/gpu/drm/radeon/r500_reg.h +++ b/drivers/gpu/drm/radeon/r500_reg.h @@ -445,6 +445,7 @@ #define AVIVO_D1MODE_DATA_FORMAT 0x6528 # define AVIVO_D1MODE_INTERLEAVE_EN (1 << 0) #define AVIVO_D1MODE_DESKTOP_HEIGHT 0x652C +#define AVIVO_D1MODE_VLINE_START_END 0x6538 #define AVIVO_D1MODE_VIEWPORT_START 0x6580 #define AVIVO_D1MODE_VIEWPORT_SIZE 0x6584 #define AVIVO_D1MODE_EXT_OVERSCAN_LEFT_RIGHT 0x6588 @@ -496,6 +497,7 @@ #define AVIVO_D2CUR_SIZE 0x6c10 #define AVIVO_D2CUR_POSITION 0x6c14 +#define AVIVO_D2MODE_VLINE_START_END 0x6d38 #define AVIVO_D2MODE_VIEWPORT_START 0x6d80 #define AVIVO_D2MODE_VIEWPORT_SIZE 0x6d84 #define AVIVO_D2MODE_EXT_OVERSCAN_LEFT_RIGHT 0x6d88 diff --git a/drivers/gpu/drm/radeon/rv515.c b/drivers/gpu/drm/radeon/rv515.c index ffea37b1b3e2..d1384d3991ad 100644 --- a/drivers/gpu/drm/radeon/rv515.c +++ b/drivers/gpu/drm/radeon/rv515.c @@ -509,9 +509,9 @@ int rv515_debugfs_ga_info_init(struct radeon_device *rdev) /* * Asic initialization */ -static const unsigned r500_reg_safe_bm[159] = { +static const unsigned r500_reg_safe_bm[219] = { + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, - 0xFFFFFFBF, 0xFFFFFFFF, 0xFFFFFFBF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, @@ -549,11 +549,24 @@ static const unsigned r500_reg_safe_bm[159] = { 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFF80FFFF, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x0003FC01, 0x3FFFFCF8, 0xFE800B19, + 0x0003FC01, 0x3FFFFCF8, 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 rv515_init(struct radeon_device *rdev) { rdev->config.r300.reg_safe_bm = r500_reg_safe_bm; -- cgit v1.2.3 From d1724078d6a01177c1db4ea0b75fda1ca8a73d57 Mon Sep 17 00:00:00 2001 From: Thomas Hellstrom Date: Wed, 24 Jun 2009 19:57:35 +0200 Subject: ttm: Make messages more readable. Signed-off-by: Thomas Hellstrom Signed-off-by: Dave Airlie --- include/drm/ttm/ttm_module.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/drm/ttm/ttm_module.h b/include/drm/ttm/ttm_module.h index 889a4c7958ae..d1d433834e4f 100644 --- a/include/drm/ttm/ttm_module.h +++ b/include/drm/ttm/ttm_module.h @@ -33,7 +33,7 @@ #include -#define TTM_PFX "[TTM]" +#define TTM_PFX "[TTM] " enum ttm_global_types { TTM_GLOBAL_TTM_MEM = 0, -- cgit v1.2.3 From ae3e8122cbf8f9301369f276f4179aa6ec1b5b9c Mon Sep 17 00:00:00 2001 From: Thomas Hellstrom Date: Wed, 24 Jun 2009 19:57:34 +0200 Subject: ttm: Fix caching mode selection. A bug caused a new caching state to be selected on each buffer object validation regardless of the current caching state. Moreover, a caching state could be selected that wasn't supported by the memory type. Signed-off-by: Thomas Hellstrom Signed-off-by: Dave Airlie --- drivers/gpu/drm/ttm/ttm_bo.c | 51 +++++++++++++++++++++++++++++++++----------- 1 file changed, 39 insertions(+), 12 deletions(-) diff --git a/drivers/gpu/drm/ttm/ttm_bo.c b/drivers/gpu/drm/ttm/ttm_bo.c index c1c407f7cca3..a753598a5e35 100644 --- a/drivers/gpu/drm/ttm/ttm_bo.c +++ b/drivers/gpu/drm/ttm/ttm_bo.c @@ -655,31 +655,52 @@ retry_pre_get: return 0; } +static uint32_t ttm_bo_select_caching(struct ttm_mem_type_manager *man, + uint32_t cur_placement, + uint32_t proposed_placement) +{ + uint32_t caching = proposed_placement & TTM_PL_MASK_CACHING; + uint32_t result = proposed_placement & ~TTM_PL_MASK_CACHING; + + /** + * Keep current caching if possible. + */ + + if ((cur_placement & caching) != 0) + result |= (cur_placement & caching); + else if ((man->default_caching & caching) != 0) + result |= man->default_caching; + else if ((TTM_PL_FLAG_CACHED & caching) != 0) + result |= TTM_PL_FLAG_CACHED; + else if ((TTM_PL_FLAG_WC & caching) != 0) + result |= TTM_PL_FLAG_WC; + else if ((TTM_PL_FLAG_UNCACHED & caching) != 0) + result |= TTM_PL_FLAG_UNCACHED; + + return result; +} + + static bool ttm_bo_mt_compatible(struct ttm_mem_type_manager *man, bool disallow_fixed, uint32_t mem_type, - uint32_t mask, uint32_t *res_mask) + uint32_t proposed_placement, + uint32_t *masked_placement) { uint32_t cur_flags = ttm_bo_type_flags(mem_type); if ((man->flags & TTM_MEMTYPE_FLAG_FIXED) && disallow_fixed) return false; - if ((cur_flags & mask & TTM_PL_MASK_MEM) == 0) + if ((cur_flags & proposed_placement & TTM_PL_MASK_MEM) == 0) return false; - if ((mask & man->available_caching) == 0) + if ((proposed_placement & man->available_caching) == 0) return false; - if (mask & man->default_caching) - cur_flags |= man->default_caching; - else if (mask & TTM_PL_FLAG_CACHED) - cur_flags |= TTM_PL_FLAG_CACHED; - else if (mask & TTM_PL_FLAG_WC) - cur_flags |= TTM_PL_FLAG_WC; - else - cur_flags |= TTM_PL_FLAG_UNCACHED; - *res_mask = cur_flags; + cur_flags |= (proposed_placement & man->available_caching); + + *masked_placement = cur_flags; return true; } @@ -723,6 +744,9 @@ int ttm_bo_mem_space(struct ttm_buffer_object *bo, if (!type_ok) continue; + cur_flags = ttm_bo_select_caching(man, bo->mem.placement, + cur_flags); + if (mem_type == TTM_PL_SYSTEM) break; @@ -779,6 +803,9 @@ int ttm_bo_mem_space(struct ttm_buffer_object *bo, proposed_placement, &cur_flags)) continue; + cur_flags = ttm_bo_select_caching(man, bo->mem.placement, + cur_flags); + ret = ttm_bo_mem_force_space(bdev, mem, mem_type, interruptible, no_wait); -- cgit v1.2.3 From 848577ee27f704231b1860ae987a1be78b88b06e Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Wed, 8 Jul 2009 16:15:30 -0400 Subject: drm/radeon/kms: fix quirk for MSI laptop The line mux for the connector in the bios tables is used for enumerating drm connectors. Since this laptop has a quirk where the same line much is listed for both VGA and LVDS, the connectors get combined. Setting the line mux on LVDS to an unused value prevents both encoders from being combined into the same connector. This should fix bko bug 13720. Signed-off-by: Alex Deucher Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/radeon_atombios.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/radeon/radeon_atombios.c b/drivers/gpu/drm/radeon/radeon_atombios.c index 1f5a1a490984..fcfe5c02d744 100644 --- a/drivers/gpu/drm/radeon/radeon_atombios.c +++ b/drivers/gpu/drm/radeon/radeon_atombios.c @@ -103,7 +103,8 @@ static inline struct radeon_i2c_bus_rec radeon_lookup_gpio(struct drm_device static bool radeon_atom_apply_quirks(struct drm_device *dev, uint32_t supported_device, int *connector_type, - struct radeon_i2c_bus_rec *i2c_bus) + struct radeon_i2c_bus_rec *i2c_bus, + uint8_t *line_mux) { /* Asus M2A-VM HDMI board lists the DVI port as HDMI */ @@ -127,8 +128,10 @@ static bool radeon_atom_apply_quirks(struct drm_device *dev, if ((dev->pdev->device == 0x5653) && (dev->pdev->subsystem_vendor == 0x1462) && (dev->pdev->subsystem_device == 0x0291)) { - if (*connector_type == DRM_MODE_CONNECTOR_LVDS) + if (*connector_type == DRM_MODE_CONNECTOR_LVDS) { i2c_bus->valid = false; + *line_mux = 53; + } } /* Funky macbooks */ @@ -526,7 +529,7 @@ bool radeon_get_atom_connector_info_from_supported_devices_table(struct if (!radeon_atom_apply_quirks (dev, (1 << i), &bios_connectors[i].connector_type, - &bios_connectors[i].ddc_bus)) + &bios_connectors[i].ddc_bus, &bios_connectors[i].line_mux)) continue; bios_connectors[i].valid = true; -- cgit v1.2.3 From 2007d633d639c896396e4c4b53b38068f3831307 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Wed, 8 Jul 2009 16:17:23 -0400 Subject: drm/radeon/kms: get lvds info for DIG LVTMA and UNIPHY encoders MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Noticed by Rafał Miłecki on dri-devel. On r6xx/r7xx hardware, laptop panels can be driven by KLDSCP_LVTMA or UNIPHY. Signed-off-by: Alex Deucher Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/radeon_encoders.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/radeon/radeon_encoders.c b/drivers/gpu/drm/radeon/radeon_encoders.c index c8ef0d14ffab..ea15284e7580 100644 --- a/drivers/gpu/drm/radeon/radeon_encoders.c +++ b/drivers/gpu/drm/radeon/radeon_encoders.c @@ -1700,8 +1700,14 @@ radeon_add_atom_encoder(struct drm_device *dev, uint32_t encoder_id, uint32_t su case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA: case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: - drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs, DRM_MODE_ENCODER_TMDS); - radeon_encoder->enc_priv = radeon_atombios_set_dig_info(radeon_encoder); + if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) { + radeon_encoder->rmx_type = RMX_FULL; + drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs, DRM_MODE_ENCODER_LVDS); + radeon_encoder->enc_priv = radeon_atombios_get_lvds_info(radeon_encoder); + } else { + drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs, DRM_MODE_ENCODER_TMDS); + radeon_encoder->enc_priv = radeon_atombios_set_dig_info(radeon_encoder); + } drm_encoder_helper_add(encoder, &radeon_atom_dig_helper_funcs); break; } -- cgit v1.2.3 From e7168cab5bbac0a0e5413fd55ba0e92555bf860d Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Thu, 9 Jul 2009 16:01:42 +1000 Subject: drm/radeon/kms: fix vram vs aper size check. Fix this to be correct like the DDX code, looks like a typo on transfer to the kernel. Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/radeon_device.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/radeon/radeon_device.c b/drivers/gpu/drm/radeon/radeon_device.c index f97563db4e59..332911267ebe 100644 --- a/drivers/gpu/drm/radeon/radeon_device.c +++ b/drivers/gpu/drm/radeon/radeon_device.c @@ -552,7 +552,7 @@ int radeon_device_init(struct radeon_device *rdev, * for RN50/M6/M7 - Novell bug 204882 ? */ if (rdev->mc.vram_size < rdev->mc.aper_size) { - rdev->mc.aper_size = rdev->mc.vram_size; + rdev->mc.vram_size = rdev->mc.aper_size; } /* Add an MTRR for the VRAM */ rdev->mc.vram_mtrr = mtrr_add(rdev->mc.aper_base, rdev->mc.aper_size, -- cgit v1.2.3 From 5176fdc4c5873e52f9cb6e166d80e843847e7eb4 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Tue, 30 Jun 2009 11:47:14 +1000 Subject: drm/radeon/kms: drop zero length CS indirect buffers. If userspace sends a zero length IB, it really shouldn't have bothered so EINVAL it. Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/radeon_cs.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/radeon/radeon_cs.c b/drivers/gpu/drm/radeon/radeon_cs.c index b843f9bdfb14..a169067efc4e 100644 --- a/drivers/gpu/drm/radeon/radeon_cs.c +++ b/drivers/gpu/drm/radeon/radeon_cs.c @@ -127,17 +127,23 @@ int radeon_cs_parser_init(struct radeon_cs_parser *p, void *data) sizeof(struct drm_radeon_cs_chunk))) { return -EFAULT; } + p->chunks[i].length_dw = user_chunk.length_dw; + p->chunks[i].kdata = NULL; p->chunks[i].chunk_id = user_chunk.chunk_id; + if (p->chunks[i].chunk_id == RADEON_CHUNK_ID_RELOCS) { p->chunk_relocs_idx = i; } if (p->chunks[i].chunk_id == RADEON_CHUNK_ID_IB) { p->chunk_ib_idx = i; + /* zero length IB isn't useful */ + if (p->chunks[i].length_dw == 0) + return -EINVAL; } + p->chunks[i].length_dw = user_chunk.length_dw; cdata = (uint32_t *)(unsigned long)user_chunk.chunk_data; - p->chunks[i].kdata = NULL; size = p->chunks[i].length_dw * sizeof(uint32_t); p->chunks[i].kdata = kzalloc(size, GFP_KERNEL); if (p->chunks[i].kdata == NULL) { -- cgit v1.2.3 From 77bd36f014bc5a3f28507a4e86a81b2b3d2439c3 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Fri, 10 Jul 2009 09:33:00 +1000 Subject: drm/radeon/kms: don't swap PCIEGART PTEs in VRAM. On powerpc, since we aren't using any hw swappers, this will get flipped around by default in hw. tested on a G5 + rv515. Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/r300.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/radeon/r300.c b/drivers/gpu/drm/radeon/r300.c index 656d9238bb06..6435d659cbd1 100644 --- a/drivers/gpu/drm/radeon/r300.c +++ b/drivers/gpu/drm/radeon/r300.c @@ -154,7 +154,10 @@ int rv370_pcie_gart_set_page(struct radeon_device *rdev, int i, uint64_t addr) addr = (lower_32_bits(addr) >> 8) | ((upper_32_bits(addr) & 0xff) << 24) | 0xc; - writel(cpu_to_le32(addr), ((void __iomem *)ptr) + (i * 4)); + /* on x86 we want this to be CPU endian, on powerpc + * on powerpc without HW swappers, it'll get swapped on way + * into VRAM - so no need for cpu_to_le32 on VRAM tables */ + writel(addr, ((void __iomem *)ptr) + (i * 4)); return 0; } -- cgit v1.2.3 From 61b576dbbe6a19d102c025ebc102a0749e2d3c80 Mon Sep 17 00:00:00 2001 From: Michel Dänzer Date: Wed, 24 Jun 2009 00:12:55 +1000 Subject: drm/radeon: Endianness fixes for radeondrmfb. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit For now handle it via r/g/b offsets and disallow 16 bpp modes on big endian machines. Signed-off-by: Michel Dänzer Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/radeon_fb.c | 53 +++++++++++++++++++++++++++++++++++--- 1 file changed, 50 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/radeon/radeon_fb.c b/drivers/gpu/drm/radeon/radeon_fb.c index 9e8f191eb64a..260870a29d83 100644 --- a/drivers/gpu/drm/radeon/radeon_fb.c +++ b/drivers/gpu/drm/radeon/radeon_fb.c @@ -101,9 +101,10 @@ static int radeonfb_setcolreg(unsigned regno, break; case 24: case 32: - fb->pseudo_palette[regno] = ((red & 0xff00) << 8) | - (green & 0xff00) | - ((blue & 0xff00) >> 8); + fb->pseudo_palette[regno] = + (((red >> 8) & 0xff) << info->var.red.offset) | + (((green >> 8) & 0xff) << info->var.green.offset) | + (((blue >> 8) & 0xff) << info->var.blue.offset); break; } } @@ -154,6 +155,7 @@ static int radeonfb_check_var(struct fb_var_screeninfo *var, var->transp.length = 0; var->transp.offset = 0; break; +#ifdef __LITTLE_ENDIAN case 15: var->red.offset = 10; var->green.offset = 5; @@ -194,6 +196,28 @@ static int radeonfb_check_var(struct fb_var_screeninfo *var, var->transp.length = 8; var->transp.offset = 24; break; +#else + case 24: + var->red.offset = 8; + var->green.offset = 16; + var->blue.offset = 24; + var->red.length = 8; + var->green.length = 8; + var->blue.length = 8; + var->transp.length = 0; + var->transp.offset = 0; + break; + case 32: + var->red.offset = 8; + var->green.offset = 16; + var->blue.offset = 24; + var->red.length = 8; + var->green.length = 8; + var->blue.length = 8; + var->transp.length = 8; + var->transp.offset = 0; + break; +#endif default: return -EINVAL; } @@ -600,6 +624,7 @@ int radeonfb_create(struct radeon_device *rdev, info->var.transp.offset = 0; info->var.transp.length = 0; break; +#ifdef __LITTLE_ENDIAN case 15: info->var.red.offset = 10; info->var.green.offset = 5; @@ -639,7 +664,29 @@ int radeonfb_create(struct radeon_device *rdev, info->var.transp.offset = 24; info->var.transp.length = 8; break; +#else + case 24: + info->var.red.offset = 8; + info->var.green.offset = 16; + info->var.blue.offset = 24; + info->var.red.length = 8; + info->var.green.length = 8; + info->var.blue.length = 8; + info->var.transp.offset = 0; + info->var.transp.length = 0; + break; + case 32: + info->var.red.offset = 8; + info->var.green.offset = 16; + info->var.blue.offset = 24; + info->var.red.length = 8; + info->var.green.length = 8; + info->var.blue.length = 8; + info->var.transp.offset = 0; + info->var.transp.length = 8; + break; default: +#endif break; } -- cgit v1.2.3 From ad49f501867cba87e1e45e5ebae0b12435d68bf1 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Fri, 10 Jul 2009 22:36:26 +1000 Subject: drm/ttm/radeon: add dma32 support. This add support for using dma32 memory on gpus that really need it. Currently IGPs are left without DMA32 but we might need to change that unless we can fix rs690. Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/radeon.h | 1 + drivers/gpu/drm/radeon/radeon_device.c | 17 +++++++++++++++-- drivers/gpu/drm/radeon/radeon_ttm.c | 3 ++- drivers/gpu/drm/ttm/ttm_bo.c | 7 ++++++- drivers/gpu/drm/ttm/ttm_tt.c | 9 +++++++-- include/drm/ttm/ttm_bo_driver.h | 5 ++++- 6 files changed, 35 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h index e7662ba9abfb..3060ce14071e 100644 --- a/drivers/gpu/drm/radeon/radeon.h +++ b/drivers/gpu/drm/radeon/radeon.h @@ -624,6 +624,7 @@ struct radeon_device { bool gpu_lockup; bool shutdown; bool suspend; + bool need_dma32; }; int radeon_device_init(struct radeon_device *rdev, diff --git a/drivers/gpu/drm/radeon/radeon_device.c b/drivers/gpu/drm/radeon/radeon_device.c index 332911267ebe..27a5ac969953 100644 --- a/drivers/gpu/drm/radeon/radeon_device.c +++ b/drivers/gpu/drm/radeon/radeon_device.c @@ -450,6 +450,7 @@ int radeon_device_init(struct radeon_device *rdev, uint32_t flags) { int r, ret; + int dma_bits; DRM_INFO("radeon: Initializing kernel modesetting.\n"); rdev->shutdown = false; @@ -492,8 +493,20 @@ int radeon_device_init(struct radeon_device *rdev, return r; } - /* Report DMA addressing limitation */ - r = pci_set_dma_mask(rdev->pdev, DMA_BIT_MASK(32)); + /* set DMA mask + need_dma32 flags. + * PCIE - can handle 40-bits. + * IGP - can handle 40-bits (in theory) + * AGP - generally dma32 is safest + * PCI - only dma32 + */ + rdev->need_dma32 = false; + if (rdev->flags & RADEON_IS_AGP) + rdev->need_dma32 = true; + if (rdev->flags & RADEON_IS_PCI) + rdev->need_dma32 = true; + + dma_bits = rdev->need_dma32 ? 32 : 40; + r = pci_set_dma_mask(rdev->pdev, DMA_BIT_MASK(dma_bits)); if (r) { printk(KERN_WARNING "radeon: No suitable DMA available.\n"); } diff --git a/drivers/gpu/drm/radeon/radeon_ttm.c b/drivers/gpu/drm/radeon/radeon_ttm.c index 1227a97f5169..4ca9aa9203d0 100644 --- a/drivers/gpu/drm/radeon/radeon_ttm.c +++ b/drivers/gpu/drm/radeon/radeon_ttm.c @@ -442,7 +442,8 @@ int radeon_ttm_init(struct radeon_device *rdev) /* No others user of address space so set it to 0 */ r = ttm_bo_device_init(&rdev->mman.bdev, rdev->mman.mem_global_ref.object, - &radeon_bo_driver, DRM_FILE_PAGE_OFFSET); + &radeon_bo_driver, DRM_FILE_PAGE_OFFSET, + rdev->need_dma32); if (r) { DRM_ERROR("failed initializing buffer object driver(%d).\n", r); return r; diff --git a/drivers/gpu/drm/ttm/ttm_bo.c b/drivers/gpu/drm/ttm/ttm_bo.c index a753598a5e35..e55e7972c897 100644 --- a/drivers/gpu/drm/ttm/ttm_bo.c +++ b/drivers/gpu/drm/ttm/ttm_bo.c @@ -224,6 +224,9 @@ static int ttm_bo_add_ttm(struct ttm_buffer_object *bo, bool zero_alloc) TTM_ASSERT_LOCKED(&bo->mutex); bo->ttm = NULL; + if (bdev->need_dma32) + page_flags |= TTM_PAGE_FLAG_DMA32; + switch (bo->type) { case ttm_bo_type_device: if (zero_alloc) @@ -1332,7 +1335,8 @@ EXPORT_SYMBOL(ttm_bo_device_release); int ttm_bo_device_init(struct ttm_bo_device *bdev, struct ttm_mem_global *mem_glob, - struct ttm_bo_driver *driver, uint64_t file_page_offset) + struct ttm_bo_driver *driver, uint64_t file_page_offset, + bool need_dma32) { int ret = -EINVAL; @@ -1369,6 +1373,7 @@ int ttm_bo_device_init(struct ttm_bo_device *bdev, INIT_LIST_HEAD(&bdev->ddestroy); INIT_LIST_HEAD(&bdev->swap_lru); bdev->dev_mapping = NULL; + bdev->need_dma32 = need_dma32; ttm_mem_init_shrink(&bdev->shrink, ttm_bo_swapout); ret = ttm_mem_register_shrink(mem_glob, &bdev->shrink); if (unlikely(ret != 0)) { diff --git a/drivers/gpu/drm/ttm/ttm_tt.c b/drivers/gpu/drm/ttm/ttm_tt.c index 75dc8bd24592..81ab81f030a3 100644 --- a/drivers/gpu/drm/ttm/ttm_tt.c +++ b/drivers/gpu/drm/ttm/ttm_tt.c @@ -131,10 +131,15 @@ static void ttm_tt_free_page_directory(struct ttm_tt *ttm) static struct page *ttm_tt_alloc_page(unsigned page_flags) { + gfp_t gfp_flags = GFP_HIGHUSER; + if (page_flags & TTM_PAGE_FLAG_ZERO_ALLOC) - return alloc_page(GFP_HIGHUSER | __GFP_ZERO); + gfp_flags |= __GFP_ZERO; + + if (page_flags & TTM_PAGE_FLAG_DMA32) + gfp_flags |= __GFP_DMA32; - return alloc_page(GFP_HIGHUSER); + return alloc_page(gfp_flags); } static void ttm_tt_free_user_pages(struct ttm_tt *ttm) diff --git a/include/drm/ttm/ttm_bo_driver.h b/include/drm/ttm/ttm_bo_driver.h index 62ed733c52a2..ea83dd23a4d7 100644 --- a/include/drm/ttm/ttm_bo_driver.h +++ b/include/drm/ttm/ttm_bo_driver.h @@ -121,6 +121,7 @@ struct ttm_backend { #define TTM_PAGE_FLAG_SWAPPED (1 << 4) #define TTM_PAGE_FLAG_PERSISTANT_SWAP (1 << 5) #define TTM_PAGE_FLAG_ZERO_ALLOC (1 << 6) +#define TTM_PAGE_FLAG_DMA32 (1 << 7) enum ttm_caching_state { tt_uncached, @@ -429,6 +430,8 @@ struct ttm_bo_device { */ struct delayed_work wq; + + bool need_dma32; }; /** @@ -648,7 +651,7 @@ extern int ttm_bo_device_release(struct ttm_bo_device *bdev); extern int ttm_bo_device_init(struct ttm_bo_device *bdev, struct ttm_mem_global *mem_glob, struct ttm_bo_driver *driver, - uint64_t file_page_offset); + uint64_t file_page_offset, bool need_dma32); /** * ttm_bo_reserve: -- cgit v1.2.3 From 2a0f8918fc34713ecaeb900ffb9afa61df4cb08e Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Sat, 11 Jul 2009 04:44:47 +1000 Subject: drm/radeon/kms: fix VRAM sizing like DDX does it. Doing this like the DDX seems like the most sure fire way to avoid having to reinvent it slowly and painfully. At the moment we keep getting things wrong with aper vs vram, so we know the DDX does it right. booted on PCI r100, PCIE rv370, IGP rs400. Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/r100.c | 65 ++++++++++++++++++++++++++++++++-- drivers/gpu/drm/radeon/r300.c | 4 +-- drivers/gpu/drm/radeon/r520.c | 4 +-- drivers/gpu/drm/radeon/radeon.h | 2 ++ drivers/gpu/drm/radeon/radeon_device.c | 7 +--- drivers/gpu/drm/radeon/rs400.c | 14 +------- drivers/gpu/drm/radeon/rv515.c | 6 ++-- 7 files changed, 71 insertions(+), 31 deletions(-) diff --git a/drivers/gpu/drm/radeon/r100.c b/drivers/gpu/drm/radeon/r100.c index 154648a2c027..97c9229b9299 100644 --- a/drivers/gpu/drm/radeon/r100.c +++ b/drivers/gpu/drm/radeon/r100.c @@ -1360,9 +1360,50 @@ static void r100_vram_get_type(struct radeon_device *rdev) } } -void r100_vram_info(struct radeon_device *rdev) +static u32 r100_get_accessible_vram(struct radeon_device *rdev) { - r100_vram_get_type(rdev); + u32 aper_size; + u8 byte; + + aper_size = RREG32(RADEON_CONFIG_APER_SIZE); + + /* Set HDP_APER_CNTL only on cards that are known not to be broken, + * that is has the 2nd generation multifunction PCI interface + */ + if (rdev->family == CHIP_RV280 || + rdev->family >= CHIP_RV350) { + WREG32_P(RADEON_HOST_PATH_CNTL, RADEON_HDP_APER_CNTL, + ~RADEON_HDP_APER_CNTL); + DRM_INFO("Generation 2 PCI interface, using max accessible memory\n"); + return aper_size * 2; + } + + /* Older cards have all sorts of funny issues to deal with. First + * check if it's a multifunction card by reading the PCI config + * header type... Limit those to one aperture size + */ + pci_read_config_byte(rdev->pdev, 0xe, &byte); + if (byte & 0x80) { + DRM_INFO("Generation 1 PCI interface in multifunction mode\n"); + DRM_INFO("Limiting VRAM to one aperture\n"); + return aper_size; + } + + /* Single function older card. We read HDP_APER_CNTL to see how the BIOS + * have set it up. We don't write this as it's broken on some ASICs but + * we expect the BIOS to have done the right thing (might be too optimistic...) + */ + if (RREG32(RADEON_HOST_PATH_CNTL) & RADEON_HDP_APER_CNTL) + return aper_size * 2; + return aper_size; +} + +void r100_vram_init_sizes(struct radeon_device *rdev) +{ + u64 config_aper_size; + u32 accessible; + + config_aper_size = RREG32(RADEON_CONFIG_APER_SIZE); if (rdev->flags & RADEON_IS_IGP) { uint32_t tom; @@ -1383,10 +1424,30 @@ void r100_vram_info(struct radeon_device *rdev) } /* let driver place VRAM */ rdev->mc.vram_location = 0xFFFFFFFFUL; + /* Fix for RN50, M6, M7 with 8/16/32(??) MBs of VRAM - + * Novell bug 204882 + along with lots of ubuntu ones */ + if (config_aper_size > rdev->mc.vram_size) + rdev->mc.vram_size = config_aper_size; } + /* work out accessible VRAM */ + accessible = r100_get_accessible_vram(rdev); + rdev->mc.aper_base = drm_get_resource_start(rdev->ddev, 0); rdev->mc.aper_size = drm_get_resource_len(rdev->ddev, 0); + + if (accessible > rdev->mc.aper_size) + accessible = rdev->mc.aper_size; + + if (rdev->mc.vram_size > rdev->mc.aper_size) + rdev->mc.vram_size = rdev->mc.aper_size; +} + +void r100_vram_info(struct radeon_device *rdev) +{ + r100_vram_get_type(rdev); + + r100_vram_init_sizes(rdev); } diff --git a/drivers/gpu/drm/radeon/r300.c b/drivers/gpu/drm/radeon/r300.c index 6435d659cbd1..0e0e094da503 100644 --- a/drivers/gpu/drm/radeon/r300.c +++ b/drivers/gpu/drm/radeon/r300.c @@ -585,10 +585,8 @@ void r300_vram_info(struct radeon_device *rdev) } else { rdev->mc.vram_width = 64; } - rdev->mc.vram_size = RREG32(RADEON_CONFIG_MEMSIZE); - rdev->mc.aper_base = drm_get_resource_start(rdev->ddev, 0); - rdev->mc.aper_size = drm_get_resource_len(rdev->ddev, 0); + r100_vram_init_sizes(rdev); } diff --git a/drivers/gpu/drm/radeon/r520.c b/drivers/gpu/drm/radeon/r520.c index 570a244bd88b..b6bd3758db6b 100644 --- a/drivers/gpu/drm/radeon/r520.c +++ b/drivers/gpu/drm/radeon/r520.c @@ -227,8 +227,6 @@ static void r520_vram_get_type(struct radeon_device *rdev) void r520_vram_info(struct radeon_device *rdev) { r520_vram_get_type(rdev); - rdev->mc.vram_size = RREG32(RADEON_CONFIG_MEMSIZE); - rdev->mc.aper_base = drm_get_resource_start(rdev->ddev, 0); - rdev->mc.aper_size = drm_get_resource_len(rdev->ddev, 0); + r100_vram_init_sizes(rdev); } diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h index 3060ce14071e..248e3341a984 100644 --- a/drivers/gpu/drm/radeon/radeon.h +++ b/drivers/gpu/drm/radeon/radeon.h @@ -541,6 +541,8 @@ union radeon_asic_config { struct r300_asic r300; }; +/* r100 */ +void r100_vram_init_sizes(struct radeon_device *rdev); /* * IOCTL. diff --git a/drivers/gpu/drm/radeon/radeon_device.c b/drivers/gpu/drm/radeon/radeon_device.c index 27a5ac969953..cdef6eb01baf 100644 --- a/drivers/gpu/drm/radeon/radeon_device.c +++ b/drivers/gpu/drm/radeon/radeon_device.c @@ -561,12 +561,7 @@ int radeon_device_init(struct radeon_device *rdev, } /* Get vram informations */ radeon_vram_info(rdev); - /* Device is severly broken if aper size > vram size. - * for RN50/M6/M7 - Novell bug 204882 ? - */ - if (rdev->mc.vram_size < rdev->mc.aper_size) { - rdev->mc.vram_size = rdev->mc.aper_size; - } + /* Add an MTRR for the VRAM */ rdev->mc.vram_mtrr = mtrr_add(rdev->mc.aper_base, rdev->mc.aper_size, MTRR_TYPE_WRCOMB, 1); diff --git a/drivers/gpu/drm/radeon/rs400.c b/drivers/gpu/drm/radeon/rs400.c index a18d053065c0..daf24e85cba3 100644 --- a/drivers/gpu/drm/radeon/rs400.c +++ b/drivers/gpu/drm/radeon/rs400.c @@ -292,24 +292,12 @@ void rs400_gpu_init(struct radeon_device *rdev) */ void rs400_vram_info(struct radeon_device *rdev) { - uint32_t tom; - rs400_gart_adjust_size(rdev); /* DDR for all card after R300 & IGP */ rdev->mc.vram_is_ddr = true; rdev->mc.vram_width = 128; - /* read NB_TOM to get the amount of ram stolen for the GPU */ - tom = RREG32(RADEON_NB_TOM); - rdev->mc.vram_size = (((tom >> 16) - (tom & 0xffff) + 1) << 16); - WREG32(RADEON_CONFIG_MEMSIZE, rdev->mc.vram_size); - - /* RS480 IGPs don't seem to translate to main RAM, they - * just reserve and scan out of it. So setting VRAM location - * to say 0, will actually trash the OS. */ - rdev->mc.vram_location = (tom & 0xffff) << 16; - rdev->mc.aper_base = drm_get_resource_start(rdev->ddev, 0); - rdev->mc.aper_size = drm_get_resource_len(rdev->ddev, 0); + r100_vram_init_sizes(rdev); } diff --git a/drivers/gpu/drm/radeon/rv515.c b/drivers/gpu/drm/radeon/rv515.c index d1384d3991ad..677929ed8ed3 100644 --- a/drivers/gpu/drm/radeon/rv515.c +++ b/drivers/gpu/drm/radeon/rv515.c @@ -395,10 +395,8 @@ static void rv515_vram_get_type(struct radeon_device *rdev) void rv515_vram_info(struct radeon_device *rdev) { rv515_vram_get_type(rdev); - rdev->mc.vram_size = RREG32(RADEON_CONFIG_MEMSIZE); - - rdev->mc.aper_base = drm_get_resource_start(rdev->ddev, 0); - rdev->mc.aper_size = drm_get_resource_len(rdev->ddev, 0); + + r100_vram_init_sizes(rdev); } -- cgit v1.2.3 From b995e4330de0d8b1b8b9e49ce10cc6dc78e2cbba Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Tue, 14 Jul 2009 02:02:32 +1000 Subject: drm/radeon/kms: block RN50 from using 3D engine. RN50/ES1000 is a cut-down rv100 chip used in the server market. The 3D engine on these is either not there or unverified so refuse any attempt to configure registers on it. Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/r100.c | 5 +++++ drivers/gpu/drm/radeon/radeon.h | 2 ++ 2 files changed, 7 insertions(+) diff --git a/drivers/gpu/drm/radeon/r100.c b/drivers/gpu/drm/radeon/r100.c index 97c9229b9299..0d05909f03f6 100644 --- a/drivers/gpu/drm/radeon/r100.c +++ b/drivers/gpu/drm/radeon/r100.c @@ -973,6 +973,11 @@ static int r100_packet0_check(struct radeon_cs_parser *p, case R300_TX_OFFSET_0+52: case R300_TX_OFFSET_0+56: case R300_TX_OFFSET_0+60: + /* rn50 has no 3D engine so fail on any 3d setup */ + if (ASIC_IS_RN50(p->rdev)) { + DRM_ERROR("attempt to use RN50 3D engine failed\n"); + return -EINVAL; + } r = r100_cs_packet_next_reloc(p, &reloc); if (r) { DRM_ERROR("No reloc for ib[%d]=0x%04X\n", diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h index 248e3341a984..7f007185e7f7 100644 --- a/drivers/gpu/drm/radeon/radeon.h +++ b/drivers/gpu/drm/radeon/radeon.h @@ -673,6 +673,8 @@ void r100_pll_errata_after_index(struct radeon_device *rdev); /* * ASICs helpers. */ +#define ASIC_IS_RN50(rdev) ((rdev->pdev->device == 0x515e) || \ + (rdev->pdev->device == 0x5969)) #define ASIC_IS_RV100(rdev) ((rdev->family == CHIP_RV100) || \ (rdev->family == CHIP_RV200) || \ (rdev->family == CHIP_RS100) || \ -- cgit v1.2.3 From d0e275a90a81b37409a0cfbca77581e3d235f5cf Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Mon, 13 Jul 2009 11:08:18 -0400 Subject: drm/radeon/kms: add PLL flag to prefer frequencies <= the target freq This is needed when using fractional feedback dividers on some IGP chips. Signed-off-by: Alex Deucher Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/radeon_display.c | 6 +++++- drivers/gpu/drm/radeon/radeon_mode.h | 1 + 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c index 3efcf1a526be..bc312f3d9a0a 100644 --- a/drivers/gpu/drm/radeon/radeon_display.c +++ b/drivers/gpu/drm/radeon/radeon_display.c @@ -491,7 +491,11 @@ void radeon_compute_pll(struct radeon_pll *pll, tmp += (uint64_t)pll->reference_freq * 1000 * frac_feedback_div; current_freq = radeon_div(tmp, ref_div * post_div); - error = abs(current_freq - freq); + if (flags & RADEON_PLL_PREFER_CLOSEST_LOWER) { + error = freq - current_freq; + error = error < 0 ? 0xffffffff : error; + } else + error = abs(current_freq - freq); vco_diff = abs(vco - best_vco); if ((best_vco == 0 && error < best_error) || diff --git a/drivers/gpu/drm/radeon/radeon_mode.h b/drivers/gpu/drm/radeon/radeon_mode.h index 86f766e868e7..38c1dd082441 100644 --- a/drivers/gpu/drm/radeon/radeon_mode.h +++ b/drivers/gpu/drm/radeon/radeon_mode.h @@ -124,6 +124,7 @@ struct radeon_tmds_pll { #define RADEON_PLL_PREFER_LOW_POST_DIV (1 << 8) #define RADEON_PLL_PREFER_HIGH_POST_DIV (1 << 9) #define RADEON_PLL_USE_FRAC_FB_DIV (1 << 10) +#define RADEON_PLL_PREFER_CLOSEST_LOWER (1 << 11) struct radeon_pll { uint16_t reference_freq; -- cgit v1.2.3 From eb1300bcd70b3bffbefb6ae0eab13a571255ee93 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Mon, 13 Jul 2009 11:09:56 -0400 Subject: drm/radeon/kms: enable frac fb divs on rs600/rs690/rs740 Allows us to hit dot clocks much closer, especially on chips with non-27 Mhz reference clocks like most IGP chips. This fixes most flickering and blanking problems with non-exact dot clocks on these chips. Signed-off-by: Alex Deucher Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/atombios_crtc.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/gpu/drm/radeon/atombios_crtc.c b/drivers/gpu/drm/radeon/atombios_crtc.c index c0080cc9bf8d..e64a199b5ee1 100644 --- a/drivers/gpu/drm/radeon/atombios_crtc.c +++ b/drivers/gpu/drm/radeon/atombios_crtc.c @@ -203,6 +203,12 @@ void atombios_crtc_set_pll(struct drm_crtc *crtc, struct drm_display_mode *mode) if (ASIC_IS_AVIVO(rdev)) { uint32_t ss_cntl; + if ((rdev->family == CHIP_RS600) || + (rdev->family == CHIP_RS690) || + (rdev->family == CHIP_RS740)) + pll_flags |= (RADEON_PLL_USE_FRAC_FB_DIV | + RADEON_PLL_PREFER_CLOSEST_LOWER); + if (ASIC_IS_DCE32(rdev) && mode->clock > 200000) /* range limits??? */ pll_flags |= RADEON_PLL_PREFER_HIGH_FB_DIV; else -- cgit v1.2.3 From c836e862803b2aa2bd9a354e151316d2b42c44ec Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Mon, 13 Jul 2009 13:51:03 -0400 Subject: drm/radeon/kms: fix hotspot handling on pre-avivo chips Need to adjust CUR_OFFSET for yorigin Signed-off-by: Alex Deucher Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/radeon_cursor.c | 9 +++++++-- drivers/gpu/drm/radeon/radeon_mode.h | 1 + 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/radeon/radeon_cursor.c b/drivers/gpu/drm/radeon/radeon_cursor.c index 5f8ce370c4f8..b13c79e38bc0 100644 --- a/drivers/gpu/drm/radeon/radeon_cursor.c +++ b/drivers/gpu/drm/radeon/radeon_cursor.c @@ -111,9 +111,11 @@ static void radeon_set_cursor(struct drm_crtc *crtc, struct drm_gem_object *obj, if (ASIC_IS_AVIVO(rdev)) WREG32(AVIVO_D1CUR_SURFACE_ADDRESS + radeon_crtc->crtc_offset, gpu_addr); - else + else { + radeon_crtc->legacy_cursor_offset = gpu_addr - radeon_crtc->legacy_display_base_addr; /* offset is from DISP(2)_BASE_ADDRESS */ - WREG32(RADEON_CUR_OFFSET + radeon_crtc->crtc_offset, (gpu_addr-radeon_crtc->legacy_display_base_addr)); + WREG32(RADEON_CUR_OFFSET + radeon_crtc->crtc_offset, radeon_crtc->legacy_cursor_offset); + } } int radeon_crtc_cursor_set(struct drm_crtc *crtc, @@ -245,6 +247,9 @@ int radeon_crtc_cursor_move(struct drm_crtc *crtc, (RADEON_CUR_LOCK | ((xorigin ? 0 : x) << 16) | (yorigin ? 0 : y))); + /* offset is from DISP(2)_BASE_ADDRESS */ + WREG32(RADEON_CUR_OFFSET + radeon_crtc->crtc_offset, (radeon_crtc->legacy_cursor_offset + + (yorigin * 256))); } radeon_lock_cursor(crtc, false); diff --git a/drivers/gpu/drm/radeon/radeon_mode.h b/drivers/gpu/drm/radeon/radeon_mode.h index 38c1dd082441..ba89b59f6e50 100644 --- a/drivers/gpu/drm/radeon/radeon_mode.h +++ b/drivers/gpu/drm/radeon/radeon_mode.h @@ -187,6 +187,7 @@ struct radeon_crtc { int cursor_width; int cursor_height; uint32_t legacy_display_base_addr; + uint32_t legacy_cursor_offset; }; #define RADEON_USE_RMX 1 -- cgit v1.2.3 From 0f58b44582001c8bcdb75f36cf85ebbe5170e959 Mon Sep 17 00:00:00 2001 From: Peter Oberparleiter Date: Tue, 14 Jul 2009 17:56:15 +0200 Subject: sysfs: fix hardlink count on device_move Update directory hardlink count when moving kobjects to a new parent. Fixes the following problem which occurs when several devices are moved to the same parent and then unregistered: > ls -laF /sys/devices/css0/defunct/ > total 0 > drwxr-xr-x 4294967295 root root 0 2009-07-14 17:02 ./ > drwxr-xr-x 114 root root 0 2009-07-14 17:02 ../ > drwxr-xr-x 2 root root 0 2009-07-14 17:01 power/ > -rw-r--r-- 1 root root 4096 2009-07-14 17:01 uevent Signed-off-by: Peter Oberparleiter Cc: stable Signed-off-by: Greg Kroah-Hartman --- fs/sysfs/dir.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/fs/sysfs/dir.c b/fs/sysfs/dir.c index d88d0fac9fa5..14f2d71ea3ce 100644 --- a/fs/sysfs/dir.c +++ b/fs/sysfs/dir.c @@ -939,8 +939,10 @@ again: /* Remove from old parent's list and insert into new parent's list. */ sysfs_unlink_sibling(sd); sysfs_get(new_parent_sd); + drop_nlink(old_parent->d_inode); sysfs_put(sd->s_parent); sd->s_parent = new_parent_sd; + inc_nlink(new_parent->d_inode); sysfs_link_sibling(sd); out_unlock: -- cgit v1.2.3 From 3b4418c67a70278964b063b5e1f56dcb3d0a41f3 Mon Sep 17 00:00:00 2001 From: Ming Lei Date: Sat, 11 Jul 2009 11:11:10 +0800 Subject: driver core: firmware_class:fix memory leak of page pointers array The page pointers array is allocated in fw_realloc_buffer() called by firmware_data_write(), and should be freed in release function of firmware device. Signed-off-by: Ming Lei Reported-by: Catalin Marinas Acked-by: David Woodhouse Signed-off-by: Greg Kroah-Hartman --- drivers/base/firmware_class.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/base/firmware_class.c b/drivers/base/firmware_class.c index f285f441fab9..7376367bcb80 100644 --- a/drivers/base/firmware_class.c +++ b/drivers/base/firmware_class.c @@ -180,7 +180,6 @@ static ssize_t firmware_loading_store(struct device *dev, goto err; } /* Pages will be freed by vfree() */ - fw_priv->pages = NULL; fw_priv->page_array_size = 0; fw_priv->nr_pages = 0; complete(&fw_priv->completion); -- cgit v1.2.3 From 4df7b3e0370ab6161ea2f258f51dd7c43bef2bda Mon Sep 17 00:00:00 2001 From: Roel Kluin Date: Wed, 15 Jul 2009 20:29:07 +0200 Subject: Dynamic debug: fix typo: -/-> The member was intended, not the local variable. Signed-off-by: Roel Kluin Cc: Jason Baron Cc: Greg Banks Signed-off-by: Andrew Morton Signed-off-by: Greg Kroah-Hartman --- lib/dynamic_debug.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/dynamic_debug.c b/lib/dynamic_debug.c index 833139ce1e22..e22c148e4b7f 100644 --- a/lib/dynamic_debug.c +++ b/lib/dynamic_debug.c @@ -164,7 +164,7 @@ static void ddebug_change(const struct ddebug_query *query, if (!newflags) dt->num_enabled--; - else if (!dp-flags) + else if (!dp->flags) dt->num_enabled++; dp->flags = newflags; if (newflags) { -- cgit v1.2.3 From 79f0313bfc67aa13abb931e8c12a1411f0161a68 Mon Sep 17 00:00:00 2001 From: Xiaotian Feng Date: Fri, 24 Jul 2009 17:31:41 +0800 Subject: driver core: sysdev: do not send KOBJ_ADD uevent if kobject_init_and_add fails If kobject_init_and_add fails, sysdev_register should not send KOBJ_ADD uevent to userspace. Signed-off-by: Xiaotian Feng Signed-off-by: Greg Kroah-Hartman --- drivers/base/sys.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/base/sys.c b/drivers/base/sys.c index 79a9ae5238ac..0d903909af7e 100644 --- a/drivers/base/sys.c +++ b/drivers/base/sys.c @@ -275,9 +275,9 @@ int sysdev_register(struct sys_device *sysdev) drv->add(sysdev); } mutex_unlock(&sysdev_drivers_lock); + kobject_uevent(&sysdev->kobj, KOBJ_ADD); } - kobject_uevent(&sysdev->kobj, KOBJ_ADD); return error; } -- cgit v1.2.3 From a39ea210ec8c8f6ed381f8dafbe755c57b8f30c3 Mon Sep 17 00:00:00 2001 From: Lucian Adrian Grijincu Date: Mon, 27 Jul 2009 09:06:42 -0700 Subject: driver core: documentation: make it clear that sysfs is optional The original text suggested that sysfs is mandatory and always compiled in the kernel. Signed-off-by: Lucian Adrian Grijincu Signed-off-by: Randy Dunlap Signed-off-by: Greg Kroah-Hartman --- Documentation/filesystems/sysfs.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Documentation/filesystems/sysfs.txt b/Documentation/filesystems/sysfs.txt index 7e81e37c0b1e..b245d524d568 100644 --- a/Documentation/filesystems/sysfs.txt +++ b/Documentation/filesystems/sysfs.txt @@ -23,7 +23,8 @@ interface. Using sysfs ~~~~~~~~~~~ -sysfs is always compiled in. You can access it by doing: +sysfs is always compiled in if CONFIG_SYSFS is defined. You can access +it by doing: mount -t sysfs sysfs /sys -- cgit v1.2.3 From f3a756883ac028c536479e2eb283477fec80c828 Mon Sep 17 00:00:00 2001 From: Bill Pemberton Date: Tue, 14 Jul 2009 15:33:52 -0400 Subject: Staging: serqt_usb2: add missing calls to tty_kref_put() tty_port_tty_get() was called without a corresponding tty_kref_put() in qt_read_bulk_callback() and qt_close(). Signed-off-by: Bill Pemberton Signed-off-by: Greg Kroah-Hartman --- drivers/staging/serqt_usb2/serqt_usb2.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/drivers/staging/serqt_usb2/serqt_usb2.c b/drivers/staging/serqt_usb2/serqt_usb2.c index a9bd4106beb7..f9ff9c266780 100644 --- a/drivers/staging/serqt_usb2/serqt_usb2.c +++ b/drivers/staging/serqt_usb2/serqt_usb2.c @@ -360,18 +360,18 @@ static void qt_read_bulk_callback(struct urb *urb) if (port_paranoia_check(port, __func__) != 0) { dbg("%s - port_paranoia_check, exiting\n", __func__); qt_port->ReadBulkStopped = 1; - return; + goto exit; } if (!serial) { dbg("%s - bad serial pointer, exiting\n", __func__); - return; + goto exit; } if (qt_port->closePending == 1) { /* Were closing , stop reading */ dbg("%s - (qt_port->closepending == 1\n", __func__); qt_port->ReadBulkStopped = 1; - return; + goto exit; } /* @@ -381,7 +381,7 @@ static void qt_read_bulk_callback(struct urb *urb) */ if (qt_port->RxHolding == 1) { qt_port->ReadBulkStopped = 1; - return; + goto exit; } if (urb->status) { @@ -389,7 +389,7 @@ static void qt_read_bulk_callback(struct urb *urb) dbg("%s - nonzero read bulk status received: %d\n", __func__, urb->status); - return; + goto exit; } if (tty && RxCount) { @@ -463,6 +463,8 @@ static void qt_read_bulk_callback(struct urb *urb) } schedule_work(&port->work); +exit: + tty_kref_put(tty); } /* @@ -1041,7 +1043,7 @@ static void qt_block_until_empty(struct tty_struct *tty, } } -static void qt_close( struct usb_serial_port *port) +static void qt_close(struct usb_serial_port *port) { struct usb_serial *serial = port->serial; struct quatech_port *qt_port; @@ -1068,6 +1070,7 @@ static void qt_close( struct usb_serial_port *port) /* wait up to for transmitter to empty */ if (serial->dev) qt_block_until_empty(tty, qt_port); + tty_kref_put(tty); /* Close uart channel */ status = qt_close_channel(serial, index); -- cgit v1.2.3 From de8f8bd63334fe2014be7d9ab3a81ce9b96e5d19 Mon Sep 17 00:00:00 2001 From: Oliver Neukum Date: Mon, 13 Jul 2009 10:46:57 +0200 Subject: Staging: serqt_usb2: fix memory leak in error case a standard memory leak, as later allocations may fail even if prior allocations did not. Then the prior allocations must be undone. Signed-off-by: Oliver Neukum Signed-off-by: Greg Kroah-Hartman --- drivers/staging/serqt_usb2/serqt_usb2.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/staging/serqt_usb2/serqt_usb2.c b/drivers/staging/serqt_usb2/serqt_usb2.c index f9ff9c266780..0fdf8c6dc648 100644 --- a/drivers/staging/serqt_usb2/serqt_usb2.c +++ b/drivers/staging/serqt_usb2/serqt_usb2.c @@ -738,6 +738,11 @@ static int qt_startup(struct usb_serial *serial) if (!qt_port) { dbg("%s: kmalloc for quatech_port (%d) failed!.", __func__, i); + for(--i; i >= 0; i--) { + port = serial->port[i]; + kfree(usb_get_serial_port_data(port)); + usb_set_serial_port_data(port, NULL); + } return -ENOMEM; } spin_lock_init(&qt_port->lock); -- cgit v1.2.3 From a6a9f81ccc9f5c86ccc22bbed1960a57d0316e8b Mon Sep 17 00:00:00 2001 From: David Rientjes Date: Tue, 16 Jun 2009 16:42:53 -0700 Subject: Staging: android: lowmemorykiller.c: fix it for "oom: move oom_adj value from task_struct to mm_struct" I'm about to merge "oom: move oom_adj value from task_struct to mm_struct", and this fixup is needed to repair linux-next's drivers/staging/android/lowmemorykiller.c. Signed-off-by: Andrew Morton Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/lowmemorykiller.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/drivers/staging/android/lowmemorykiller.c b/drivers/staging/android/lowmemorykiller.c index fe72240f5a9e..f934393f3959 100644 --- a/drivers/staging/android/lowmemorykiller.c +++ b/drivers/staging/android/lowmemorykiller.c @@ -96,19 +96,21 @@ static int lowmem_shrink(int nr_to_scan, gfp_t gfp_mask) read_lock(&tasklist_lock); for_each_process(p) { + struct mm_struct *mm; int oom_adj; task_lock(p); - if (!p->mm) { + mm = p->mm; + if (!mm) { task_unlock(p); continue; } - oom_adj = p->oomkilladj; + oom_adj = mm->oom_adj; if (oom_adj < min_adj) { task_unlock(p); continue; } - tasksize = get_mm_rss(p->mm); + tasksize = get_mm_rss(mm); task_unlock(p); if (tasksize <= 0) continue; -- cgit v1.2.3 From 0bfc240575acb8769d0be78facedabd8e3d2c33a Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Sun, 19 Jul 2009 23:37:32 -0700 Subject: staging: remove aten2011 driver This driver is not needed, as the existing mos7840 driver works properly for this device. Thanks to Russell Lang for doing the work to figure this out. Cc: Russell Lang Signed-off-by: Greg Kroah-Hartman --- drivers/staging/Kconfig | 2 - drivers/staging/Makefile | 1 - drivers/staging/uc2322/Kconfig | 10 - drivers/staging/uc2322/Makefile | 1 - drivers/staging/uc2322/TODO | 7 - drivers/staging/uc2322/aten2011.c | 2430 ------------------------------------- 6 files changed, 2451 deletions(-) delete mode 100644 drivers/staging/uc2322/Kconfig delete mode 100644 drivers/staging/uc2322/Makefile delete mode 100644 drivers/staging/uc2322/TODO delete mode 100644 drivers/staging/uc2322/aten2011.c diff --git a/drivers/staging/Kconfig b/drivers/staging/Kconfig index 348bf61a8fec..975ecddbce30 100644 --- a/drivers/staging/Kconfig +++ b/drivers/staging/Kconfig @@ -103,8 +103,6 @@ source "drivers/staging/pohmelfs/Kconfig" source "drivers/staging/stlc45xx/Kconfig" -source "drivers/staging/uc2322/Kconfig" - source "drivers/staging/b3dfg/Kconfig" source "drivers/staging/phison/Kconfig" diff --git a/drivers/staging/Makefile b/drivers/staging/Makefile index 8d61d7b4debf..2241ae1b21ee 100644 --- a/drivers/staging/Makefile +++ b/drivers/staging/Makefile @@ -34,7 +34,6 @@ obj-$(CONFIG_ANDROID) += android/ obj-$(CONFIG_DST) += dst/ obj-$(CONFIG_POHMELFS) += pohmelfs/ obj-$(CONFIG_STLC45XX) += stlc45xx/ -obj-$(CONFIG_USB_SERIAL_ATEN2011) += uc2322/ obj-$(CONFIG_B3DFG) += b3dfg/ obj-$(CONFIG_IDE_PHISON) += phison/ obj-$(CONFIG_PLAN9AUTH) += p9auth/ diff --git a/drivers/staging/uc2322/Kconfig b/drivers/staging/uc2322/Kconfig deleted file mode 100644 index 2e0c6e79df2b..000000000000 --- a/drivers/staging/uc2322/Kconfig +++ /dev/null @@ -1,10 +0,0 @@ -config USB_SERIAL_ATEN2011 - tristate "ATEN 2011 USB to serial device support" - depends on USB_SERIAL - default N - ---help--- - Say Y here if you want to use a ATEN 2011 dual port USB to serial - adapter. - - To compile this driver as a module, choose M here: the module will be - called aten2011. diff --git a/drivers/staging/uc2322/Makefile b/drivers/staging/uc2322/Makefile deleted file mode 100644 index 49c18d6e579f..000000000000 --- a/drivers/staging/uc2322/Makefile +++ /dev/null @@ -1 +0,0 @@ -obj-$(CONFIG_USB_SERIAL_ATEN2011) += aten2011.o diff --git a/drivers/staging/uc2322/TODO b/drivers/staging/uc2322/TODO deleted file mode 100644 index c189a64c4185..000000000000 --- a/drivers/staging/uc2322/TODO +++ /dev/null @@ -1,7 +0,0 @@ -TODO: - - checkpatch.pl cleanups - - remove dead and useless code (auditing the tty ioctls to - verify that they really are correct and needed.) - -Please send any patches to Greg Kroah-Hartman and -Russell Lang . diff --git a/drivers/staging/uc2322/aten2011.c b/drivers/staging/uc2322/aten2011.c deleted file mode 100644 index 39d0926d1a90..000000000000 --- a/drivers/staging/uc2322/aten2011.c +++ /dev/null @@ -1,2430 +0,0 @@ -/* - * Aten 2011 USB serial driver for 4 port devices - * - * Copyright (C) 2000 Inside Out Networks - * Copyright (C) 2001-2002, 2009 Greg Kroah-Hartman - * Copyright (C) 2009 Novell Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - - -#define ZLP_REG1 0x3A /* Zero_Flag_Reg1 58 */ -#define ZLP_REG2 0x3B /* Zero_Flag_Reg2 59 */ -#define ZLP_REG3 0x3C /* Zero_Flag_Reg3 60 */ -#define ZLP_REG4 0x3D /* Zero_Flag_Reg4 61 */ -#define ZLP_REG5 0x3E /* Zero_Flag_Reg5 62 */ - -/* Interrupt Rotinue Defines */ -#define SERIAL_IIR_RLS 0x06 -#define SERIAL_IIR_RDA 0x04 -#define SERIAL_IIR_CTI 0x0c -#define SERIAL_IIR_THR 0x02 -#define SERIAL_IIR_MS 0x00 - -/* Emulation of the bit mask on the LINE STATUS REGISTER. */ -#define SERIAL_LSR_DR 0x0001 -#define SERIAL_LSR_OE 0x0002 -#define SERIAL_LSR_PE 0x0004 -#define SERIAL_LSR_FE 0x0008 -#define SERIAL_LSR_BI 0x0010 -#define SERIAL_LSR_THRE 0x0020 -#define SERIAL_LSR_TEMT 0x0040 -#define SERIAL_LSR_FIFOERR 0x0080 - -/* MSR bit defines(place holders) */ -#define ATEN_MSR_DELTA_CTS 0x10 -#define ATEN_MSR_DELTA_DSR 0x20 -#define ATEN_MSR_DELTA_RI 0x40 -#define ATEN_MSR_DELTA_CD 0x80 - -/* Serial Port register Address */ -#define RECEIVE_BUFFER_REGISTER ((__u16)(0x00)) -#define TRANSMIT_HOLDING_REGISTER ((__u16)(0x00)) -#define INTERRUPT_ENABLE_REGISTER ((__u16)(0x01)) -#define INTERRUPT_IDENT_REGISTER ((__u16)(0x02)) -#define FIFO_CONTROL_REGISTER ((__u16)(0x02)) -#define LINE_CONTROL_REGISTER ((__u16)(0x03)) -#define MODEM_CONTROL_REGISTER ((__u16)(0x04)) -#define LINE_STATUS_REGISTER ((__u16)(0x05)) -#define MODEM_STATUS_REGISTER ((__u16)(0x06)) -#define SCRATCH_PAD_REGISTER ((__u16)(0x07)) -#define DIVISOR_LATCH_LSB ((__u16)(0x00)) -#define DIVISOR_LATCH_MSB ((__u16)(0x01)) - -#define SP1_REGISTER ((__u16)(0x00)) -#define CONTROL1_REGISTER ((__u16)(0x01)) -#define CLK_MULTI_REGISTER ((__u16)(0x02)) -#define CLK_START_VALUE_REGISTER ((__u16)(0x03)) -#define DCR1_REGISTER ((__u16)(0x04)) -#define GPIO_REGISTER ((__u16)(0x07)) - -#define SERIAL_LCR_DLAB ((__u16)(0x0080)) - -/* - * URB POOL related defines - */ -#define NUM_URBS 16 /* URB Count */ -#define URB_TRANSFER_BUFFER_SIZE 32 /* URB Size */ - -#define USB_VENDOR_ID_ATENINTL 0x0557 -#define ATENINTL_DEVICE_ID_2011 0x2011 -#define ATENINTL_DEVICE_ID_7820 0x7820 - -static struct usb_device_id id_table[] = { - { USB_DEVICE(USB_VENDOR_ID_ATENINTL, ATENINTL_DEVICE_ID_2011) }, - { USB_DEVICE(USB_VENDOR_ID_ATENINTL, ATENINTL_DEVICE_ID_7820) }, - { } /* terminating entry */ -}; -MODULE_DEVICE_TABLE(usb, id_table); - -/* This structure holds all of the local port information */ -struct ATENINTL_port { - int port_num; /*Actual port number in the device(1,2,etc)*/ - __u8 bulk_out_endpoint; /* the bulk out endpoint handle */ - unsigned char *bulk_out_buffer; /* buffer used for the bulk out endpoint */ - struct urb *write_urb; /* write URB for this port */ - __u8 bulk_in_endpoint; /* the bulk in endpoint handle */ - unsigned char *bulk_in_buffer; /* the buffer we use for the bulk in endpoint */ - struct urb *read_urb; /* read URB for this port */ - __u8 shadowLCR; /* last LCR value received */ - __u8 shadowMCR; /* last MCR value received */ - char open; - char chaseResponsePending; - wait_queue_head_t wait_chase; /* for handling sleeping while waiting for chase to finish */ - wait_queue_head_t wait_command; /* for handling sleeping while waiting for command to finish */ - struct async_icount icount; - struct usb_serial_port *port; /* loop back to the owner of this object */ - /*Offsets*/ - __u8 SpRegOffset; - __u8 ControlRegOffset; - __u8 DcrRegOffset; - /* for processing control URBS in interrupt context */ - struct urb *control_urb; - char *ctrl_buf; - int MsrLsr; - - struct urb *write_urb_pool[NUM_URBS]; - /* we pass a pointer to this as the arguement sent to cypress_set_termios old_termios */ - struct ktermios tmp_termios; /* stores the old termios settings */ - spinlock_t lock; /* private lock */ -}; - -/* This structure holds all of the individual serial device information */ -struct ATENINTL_serial { - __u8 interrupt_in_endpoint; /* the interrupt endpoint handle */ - unsigned char *interrupt_in_buffer; /* the buffer we use for the interrupt endpoint */ - struct urb *interrupt_read_urb; /* our interrupt urb */ - __u8 bulk_in_endpoint; /* the bulk in endpoint handle */ - unsigned char *bulk_in_buffer; /* the buffer we use for the bulk in endpoint */ - struct urb *read_urb; /* our bulk read urb */ - __u8 bulk_out_endpoint; /* the bulk out endpoint handle */ - struct usb_serial *serial; /* loop back to the owner of this object */ - int ATEN2011_spectrum_2or4ports; /* this says the number of ports in the device */ - /* Indicates about the no.of opened ports of an individual USB-serial adapater. */ - unsigned int NoOfOpenPorts; - /* a flag for Status endpoint polling */ - unsigned char status_polling_started; -}; - -static void ATEN2011_set_termios(struct tty_struct *tty, - struct usb_serial_port *port, - struct ktermios *old_termios); -static void ATEN2011_change_port_settings(struct tty_struct *tty, - struct ATENINTL_port *ATEN2011_port, - struct ktermios *old_termios); - -/************************************* - * Bit definitions for each register * - *************************************/ -#define LCR_BITS_5 0x00 /* 5 bits/char */ -#define LCR_BITS_6 0x01 /* 6 bits/char */ -#define LCR_BITS_7 0x02 /* 7 bits/char */ -#define LCR_BITS_8 0x03 /* 8 bits/char */ -#define LCR_BITS_MASK 0x03 /* Mask for bits/char field */ - -#define LCR_STOP_1 0x00 /* 1 stop bit */ -#define LCR_STOP_1_5 0x04 /* 1.5 stop bits (if 5 bits/char) */ -#define LCR_STOP_2 0x04 /* 2 stop bits (if 6-8 bits/char) */ -#define LCR_STOP_MASK 0x04 /* Mask for stop bits field */ - -#define LCR_PAR_NONE 0x00 /* No parity */ -#define LCR_PAR_ODD 0x08 /* Odd parity */ -#define LCR_PAR_EVEN 0x18 /* Even parity */ -#define LCR_PAR_MARK 0x28 /* Force parity bit to 1 */ -#define LCR_PAR_SPACE 0x38 /* Force parity bit to 0 */ -#define LCR_PAR_MASK 0x38 /* Mask for parity field */ - -#define LCR_SET_BREAK 0x40 /* Set Break condition */ -#define LCR_DL_ENABLE 0x80 /* Enable access to divisor latch */ - -#define MCR_DTR 0x01 /* Assert DTR */ -#define MCR_RTS 0x02 /* Assert RTS */ -#define MCR_OUT1 0x04 /* Loopback only: Sets state of RI */ -#define MCR_MASTER_IE 0x08 /* Enable interrupt outputs */ -#define MCR_LOOPBACK 0x10 /* Set internal (digital) loopback mode */ -#define MCR_XON_ANY 0x20 /* Enable any char to exit XOFF mode */ - -#define ATEN2011_MSR_CTS 0x10 /* Current state of CTS */ -#define ATEN2011_MSR_DSR 0x20 /* Current state of DSR */ -#define ATEN2011_MSR_RI 0x40 /* Current state of RI */ -#define ATEN2011_MSR_CD 0x80 /* Current state of CD */ - - -static int debug; - -/* - * Version Information - */ -#define DRIVER_VERSION "2.0" -#define DRIVER_DESC "ATENINTL 2011 USB Serial Adapter" - -/* - * Defines used for sending commands to port - */ - -#define ATEN_WDR_TIMEOUT (50) /* default urb timeout */ - -/* Requests */ -#define ATEN_RD_RTYPE 0xC0 -#define ATEN_WR_RTYPE 0x40 -#define ATEN_RDREQ 0x0D -#define ATEN_WRREQ 0x0E -#define ATEN_CTRL_TIMEOUT 500 -#define VENDOR_READ_LENGTH (0x01) - -/* set to 1 for RS485 mode and 0 for RS232 mode */ -/* FIXME make this somehow dynamic and not build time specific */ -static int RS485mode; - -static int set_reg_sync(struct usb_serial_port *port, __u16 reg, __u16 val) -{ - struct usb_device *dev = port->serial->dev; - val = val & 0x00ff; - - dbg("%s: is %x, value %x", __func__, reg, val); - - return usb_control_msg(dev, usb_sndctrlpipe(dev, 0), ATEN_WRREQ, - ATEN_WR_RTYPE, val, reg, NULL, 0, - ATEN_WDR_TIMEOUT); -} - -static int get_reg_sync(struct usb_serial_port *port, __u16 reg, __u16 *val) -{ - struct usb_device *dev = port->serial->dev; - int ret; - - ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), ATEN_RDREQ, - ATEN_RD_RTYPE, 0, reg, val, VENDOR_READ_LENGTH, - ATEN_WDR_TIMEOUT); - dbg("%s: offset is %x, return val %x", __func__, reg, *val); - *val = (*val) & 0x00ff; - return ret; -} - -static int set_uart_reg(struct usb_serial_port *port, __u16 reg, __u16 val) -{ - struct usb_device *dev = port->serial->dev; - struct ATENINTL_serial *a_serial; - __u16 minor; - - a_serial = usb_get_serial_data(port->serial); - minor = port->serial->minor; - if (minor == SERIAL_TTY_NO_MINOR) - minor = 0; - val = val & 0x00ff; - - /* - * For the UART control registers, - * the application number need to be Or'ed - */ - if (a_serial->ATEN2011_spectrum_2or4ports == 4) - val |= (((__u16)port->number - minor) + 1) << 8; - else { - if (((__u16) port->number - minor) == 0) - val |= (((__u16)port->number - minor) + 1) << 8; - else - val |= (((__u16)port->number - minor) + 2) << 8; - } - dbg("%s: application number is %x", __func__, val); - - return usb_control_msg(dev, usb_sndctrlpipe(dev, 0), ATEN_WRREQ, - ATEN_WR_RTYPE, val, reg, NULL, 0, - ATEN_WDR_TIMEOUT); -} - -static int get_uart_reg(struct usb_serial_port *port, __u16 reg, __u16 *val) -{ - struct usb_device *dev = port->serial->dev; - int ret = 0; - __u16 wval; - struct ATENINTL_serial *a_serial; - __u16 minor = port->serial->minor; - - a_serial = usb_get_serial_data(port->serial); - if (minor == SERIAL_TTY_NO_MINOR) - minor = 0; - - /* wval is same as application number */ - if (a_serial->ATEN2011_spectrum_2or4ports == 4) - wval = (((__u16)port->number - minor) + 1) << 8; - else { - if (((__u16) port->number - minor) == 0) - wval = (((__u16) port->number - minor) + 1) << 8; - else - wval = (((__u16) port->number - minor) + 2) << 8; - } - dbg("%s: application number is %x", __func__, wval); - ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), ATEN_RDREQ, - ATEN_RD_RTYPE, wval, reg, val, VENDOR_READ_LENGTH, - ATEN_WDR_TIMEOUT); - *val = (*val) & 0x00ff; - return ret; -} - -static int handle_newMsr(struct ATENINTL_port *port, __u8 newMsr) -{ - struct ATENINTL_port *ATEN2011_port; - struct async_icount *icount; - ATEN2011_port = port; - icount = &ATEN2011_port->icount; - if (newMsr & - (ATEN_MSR_DELTA_CTS | ATEN_MSR_DELTA_DSR | ATEN_MSR_DELTA_RI | - ATEN_MSR_DELTA_CD)) { - icount = &ATEN2011_port->icount; - - /* update input line counters */ - if (newMsr & ATEN_MSR_DELTA_CTS) - icount->cts++; - if (newMsr & ATEN_MSR_DELTA_DSR) - icount->dsr++; - if (newMsr & ATEN_MSR_DELTA_CD) - icount->dcd++; - if (newMsr & ATEN_MSR_DELTA_RI) - icount->rng++; - } - - return 0; -} - -static int handle_newLsr(struct ATENINTL_port *port, __u8 newLsr) -{ - struct async_icount *icount; - - dbg("%s - %02x", __func__, newLsr); - - if (newLsr & SERIAL_LSR_BI) { - /* - * Parity and Framing errors only count if they occur exclusive - * of a break being received. - */ - newLsr &= (__u8) (SERIAL_LSR_OE | SERIAL_LSR_BI); - } - - /* update input line counters */ - icount = &port->icount; - if (newLsr & SERIAL_LSR_BI) - icount->brk++; - if (newLsr & SERIAL_LSR_OE) - icount->overrun++; - if (newLsr & SERIAL_LSR_PE) - icount->parity++; - if (newLsr & SERIAL_LSR_FE) - icount->frame++; - - return 0; -} - -static void ATEN2011_control_callback(struct urb *urb) -{ - unsigned char *data; - struct ATENINTL_port *ATEN2011_port; - __u8 regval = 0x0; - - switch (urb->status) { - case 0: - /* success */ - break; - case -ECONNRESET: - case -ENOENT: - case -ESHUTDOWN: - /* this urb is terminated, clean up */ - dbg("%s - urb shutting down with status: %d", __func__, - urb->status); - return; - default: - dbg("%s - nonzero urb status received: %d", __func__, - urb->status); - goto exit; - } - - ATEN2011_port = (struct ATENINTL_port *)urb->context; - - dbg("%s urb buffer size is %d", __func__, urb->actual_length); - dbg("%s ATEN2011_port->MsrLsr is %d port %d", __func__, - ATEN2011_port->MsrLsr, ATEN2011_port->port_num); - data = urb->transfer_buffer; - regval = (__u8) data[0]; - dbg("%s data is %x", __func__, regval); - if (ATEN2011_port->MsrLsr == 0) - handle_newMsr(ATEN2011_port, regval); - else if (ATEN2011_port->MsrLsr == 1) - handle_newLsr(ATEN2011_port, regval); - -exit: - return; -} - -static int ATEN2011_get_reg(struct ATENINTL_port *ATEN, __u16 Wval, __u16 reg, - __u16 *val) -{ - struct usb_device *dev = ATEN->port->serial->dev; - struct usb_ctrlrequest *dr = NULL; - unsigned char *buffer = NULL; - int ret = 0; - buffer = (__u8 *) ATEN->ctrl_buf; - - dr = (void *)(buffer + 2); - dr->bRequestType = ATEN_RD_RTYPE; - dr->bRequest = ATEN_RDREQ; - dr->wValue = cpu_to_le16(Wval); - dr->wIndex = cpu_to_le16(reg); - dr->wLength = cpu_to_le16(2); - - usb_fill_control_urb(ATEN->control_urb, dev, usb_rcvctrlpipe(dev, 0), - (unsigned char *)dr, buffer, 2, - ATEN2011_control_callback, ATEN); - ATEN->control_urb->transfer_buffer_length = 2; - ret = usb_submit_urb(ATEN->control_urb, GFP_ATOMIC); - return ret; -} - -static void ATEN2011_interrupt_callback(struct urb *urb) -{ - int result; - int length; - struct ATENINTL_port *ATEN2011_port; - struct ATENINTL_serial *ATEN2011_serial; - struct usb_serial *serial; - __u16 Data; - unsigned char *data; - __u8 sp[5], st; - int i; - __u16 wval; - int minor; - - dbg("%s", " : Entering"); - - ATEN2011_serial = (struct ATENINTL_serial *)urb->context; - - switch (urb->status) { - case 0: - /* success */ - break; - case -ECONNRESET: - case -ENOENT: - case -ESHUTDOWN: - /* this urb is terminated, clean up */ - dbg("%s - urb shutting down with status: %d", __func__, - urb->status); - return; - default: - dbg("%s - nonzero urb status received: %d", __func__, - urb->status); - goto exit; - } - length = urb->actual_length; - data = urb->transfer_buffer; - - serial = ATEN2011_serial->serial; - - /* ATENINTL get 5 bytes - * Byte 1 IIR Port 1 (port.number is 0) - * Byte 2 IIR Port 2 (port.number is 1) - * Byte 3 IIR Port 3 (port.number is 2) - * Byte 4 IIR Port 4 (port.number is 3) - * Byte 5 FIFO status for both */ - - if (length && length > 5) { - dbg("%s", "Wrong data !!!"); - return; - } - - /* MATRIX */ - if (ATEN2011_serial->ATEN2011_spectrum_2or4ports == 4) { - sp[0] = (__u8) data[0]; - sp[1] = (__u8) data[1]; - sp[2] = (__u8) data[2]; - sp[3] = (__u8) data[3]; - st = (__u8) data[4]; - } else { - sp[0] = (__u8) data[0]; - sp[1] = (__u8) data[2]; - /* sp[2]=(__u8)data[2]; */ - /* sp[3]=(__u8)data[3]; */ - st = (__u8) data[4]; - - } - for (i = 0; i < serial->num_ports; i++) { - ATEN2011_port = usb_get_serial_port_data(serial->port[i]); - minor = serial->minor; - if (minor == SERIAL_TTY_NO_MINOR) - minor = 0; - if ((ATEN2011_serial->ATEN2011_spectrum_2or4ports == 2) - && (i != 0)) - wval = - (((__u16) serial->port[i]->number - - (__u16) (minor)) + 2) << 8; - else - wval = - (((__u16) serial->port[i]->number - - (__u16) (minor)) + 1) << 8; - if (ATEN2011_port->open != 0) { - if (sp[i] & 0x01) { - dbg("SP%d No Interrupt !!!", i); - } else { - switch (sp[i] & 0x0f) { - case SERIAL_IIR_RLS: - dbg("Serial Port %d: Receiver status error or address bit detected in 9-bit mode", i); - ATEN2011_port->MsrLsr = 1; - ATEN2011_get_reg(ATEN2011_port, wval, - LINE_STATUS_REGISTER, - &Data); - break; - case SERIAL_IIR_MS: - dbg("Serial Port %d: Modem status change", i); - ATEN2011_port->MsrLsr = 0; - ATEN2011_get_reg(ATEN2011_port, wval, - MODEM_STATUS_REGISTER, - &Data); - break; - } - } - } - - } -exit: - if (ATEN2011_serial->status_polling_started == 0) - return; - - result = usb_submit_urb(urb, GFP_ATOMIC); - if (result) { - dev_err(&urb->dev->dev, - "%s - Error %d submitting interrupt urb\n", - __func__, result); - } - - return; -} - -static void ATEN2011_bulk_in_callback(struct urb *urb) -{ - int status; - unsigned char *data; - struct usb_serial *serial; - struct usb_serial_port *port; - struct ATENINTL_serial *ATEN2011_serial; - struct ATENINTL_port *ATEN2011_port; - struct tty_struct *tty; - - if (urb->status) { - dbg("nonzero read bulk status received: %d", urb->status); - return; - } - - ATEN2011_port = (struct ATENINTL_port *)urb->context; - - port = (struct usb_serial_port *)ATEN2011_port->port; - serial = port->serial; - - dbg("%s", "Entering..."); - - data = urb->transfer_buffer; - ATEN2011_serial = usb_get_serial_data(serial); - - if (urb->actual_length) { - tty = tty_port_tty_get(&ATEN2011_port->port->port); - if (tty) { - tty_buffer_request_room(tty, urb->actual_length); - tty_insert_flip_string(tty, data, urb->actual_length); - tty_flip_buffer_push(tty); - tty_kref_put(tty); - } - - ATEN2011_port->icount.rx += urb->actual_length; - dbg("ATEN2011_port->icount.rx is %d:", - ATEN2011_port->icount.rx); - } - - if (!ATEN2011_port->read_urb) { - dbg("%s", "URB KILLED !!!"); - return; - } - - if (ATEN2011_port->read_urb->status != -EINPROGRESS) { - ATEN2011_port->read_urb->dev = serial->dev; - - status = usb_submit_urb(ATEN2011_port->read_urb, GFP_ATOMIC); - if (status) - dbg("usb_submit_urb(read bulk) failed, status = %d", status); - } -} - -static void ATEN2011_bulk_out_data_callback(struct urb *urb) -{ - struct ATENINTL_port *ATEN2011_port; - struct tty_struct *tty; - - if (urb->status) { - dbg("nonzero write bulk status received:%d", urb->status); - return; - } - - ATEN2011_port = (struct ATENINTL_port *)urb->context; - - dbg("%s", "Entering ........."); - - tty = tty_port_tty_get(&ATEN2011_port->port->port); - - if (tty && ATEN2011_port->open) - /* tell the tty driver that something has changed */ - tty_wakeup(tty); - - /* schedule_work(&ATEN2011_port->port->work); */ - tty_kref_put(tty); - -} - -#ifdef ATENSerialProbe -static int ATEN2011_serial_probe(struct usb_serial *serial, - const struct usb_device_id *id) -{ - - /*need to implement the mode_reg reading and updating\ - structures usb_serial_ device_type\ - (i.e num_ports, num_bulkin,bulkout etc) */ - /* Also we can update the changes attach */ - return 1; -} -#endif - -static int ATEN2011_open(struct tty_struct *tty, struct usb_serial_port *port, - struct file *filp) -{ - int response; - int j; - struct usb_serial *serial; - struct urb *urb; - __u16 Data; - int status; - struct ATENINTL_serial *ATEN2011_serial; - struct ATENINTL_port *ATEN2011_port; - struct ktermios tmp_termios; - int minor; - - serial = port->serial; - - ATEN2011_port = usb_get_serial_port_data(port); - - if (ATEN2011_port == NULL) - return -ENODEV; - - ATEN2011_serial = usb_get_serial_data(serial); - if (ATEN2011_serial == NULL) - return -ENODEV; - - /* increment the number of opened ports counter here */ - ATEN2011_serial->NoOfOpenPorts++; - - usb_clear_halt(serial->dev, port->write_urb->pipe); - usb_clear_halt(serial->dev, port->read_urb->pipe); - - /* Initialising the write urb pool */ - for (j = 0; j < NUM_URBS; ++j) { - urb = usb_alloc_urb(0, GFP_ATOMIC); - ATEN2011_port->write_urb_pool[j] = urb; - - if (urb == NULL) { - err("No more urbs???"); - continue; - } - - urb->transfer_buffer = NULL; - urb->transfer_buffer = - kmalloc(URB_TRANSFER_BUFFER_SIZE, GFP_KERNEL); - if (!urb->transfer_buffer) { - err("%s-out of memory for urb buffers.", __func__); - continue; - } - } - -/***************************************************************************** - * Initialize ATEN2011 -- Write Init values to corresponding Registers - * - * Register Index - * 1 : IER - * 2 : FCR - * 3 : LCR - * 4 : MCR - * - * 0x08 : SP1/2 Control Reg - *****************************************************************************/ - -/* NEED to check the fallowing Block */ - - Data = 0x0; - status = get_reg_sync(port, ATEN2011_port->SpRegOffset, &Data); - if (status < 0) { - dbg("Reading Spreg failed"); - return -1; - } - Data |= 0x80; - status = set_reg_sync(port, ATEN2011_port->SpRegOffset, Data); - if (status < 0) { - dbg("writing Spreg failed"); - return -1; - } - - Data &= ~0x80; - status = set_reg_sync(port, ATEN2011_port->SpRegOffset, Data); - if (status < 0) { - dbg("writing Spreg failed"); - return -1; - } - -/* End of block to be checked */ -/**************************CHECK***************************/ - - if (RS485mode == 0) - Data = 0xC0; - else - Data = 0x00; - status = set_uart_reg(port, SCRATCH_PAD_REGISTER, Data); - if (status < 0) { - dbg("Writing SCRATCH_PAD_REGISTER failed status-0x%x", status); - return -1; - } else - dbg("SCRATCH_PAD_REGISTER Writing success status%d", status); - -/**************************CHECK***************************/ - - Data = 0x0; - status = get_reg_sync(port, ATEN2011_port->ControlRegOffset, &Data); - if (status < 0) { - dbg("Reading Controlreg failed"); - return -1; - } - Data |= 0x08; /* Driver done bit */ - Data |= 0x20; /* rx_disable */ - status = 0; - status = - set_reg_sync(port, ATEN2011_port->ControlRegOffset, Data); - if (status < 0) { - dbg("writing Controlreg failed"); - return -1; - } - /* - * do register settings here - * Set all regs to the device default values. - * First Disable all interrupts. - */ - - Data = 0x00; - status = set_uart_reg(port, INTERRUPT_ENABLE_REGISTER, Data); - if (status < 0) { - dbg("disableing interrupts failed"); - return -1; - } - /* Set FIFO_CONTROL_REGISTER to the default value */ - Data = 0x00; - status = set_uart_reg(port, FIFO_CONTROL_REGISTER, Data); - if (status < 0) { - dbg("Writing FIFO_CONTROL_REGISTER failed"); - return -1; - } - - Data = 0xcf; /* chk */ - status = set_uart_reg(port, FIFO_CONTROL_REGISTER, Data); - if (status < 0) { - dbg("Writing FIFO_CONTROL_REGISTER failed"); - return -1; - } - - Data = 0x03; /* LCR_BITS_8 */ - status = set_uart_reg(port, LINE_CONTROL_REGISTER, Data); - ATEN2011_port->shadowLCR = Data; - - Data = 0x0b; /* MCR_DTR|MCR_RTS|MCR_MASTER_IE */ - status = set_uart_reg(port, MODEM_CONTROL_REGISTER, Data); - ATEN2011_port->shadowMCR = Data; - -#ifdef Check - Data = 0x00; - status = get_uart_reg(port, LINE_CONTROL_REGISTER, &Data); - ATEN2011_port->shadowLCR = Data; - - Data |= SERIAL_LCR_DLAB; /* data latch enable in LCR 0x80 */ - status = set_uart_reg(port, LINE_CONTROL_REGISTER, Data); - - Data = 0x0c; - status = set_uart_reg(port, DIVISOR_LATCH_LSB, Data); - - Data = 0x0; - status = set_uart_reg(port, DIVISOR_LATCH_MSB, Data); - - Data = 0x00; - status = get_uart_reg(port, LINE_CONTROL_REGISTER, &Data); - -/* Data = ATEN2011_port->shadowLCR; */ /* data latch disable */ - Data = Data & ~SERIAL_LCR_DLAB; - status = set_uart_reg(port, LINE_CONTROL_REGISTER, Data); - ATEN2011_port->shadowLCR = Data; -#endif - /* clearing Bulkin and Bulkout Fifo */ - Data = 0x0; - status = get_reg_sync(port, ATEN2011_port->SpRegOffset, &Data); - - Data = Data | 0x0c; - status = set_reg_sync(port, ATEN2011_port->SpRegOffset, Data); - - Data = Data & ~0x0c; - status = set_reg_sync(port, ATEN2011_port->SpRegOffset, Data); - /* Finally enable all interrupts */ - Data = 0x0; - Data = 0x0c; - status = set_uart_reg(port, INTERRUPT_ENABLE_REGISTER, Data); - - /* clearing rx_disable */ - Data = 0x0; - status = get_reg_sync(port, ATEN2011_port->ControlRegOffset, &Data); - Data = Data & ~0x20; - status = set_reg_sync(port, ATEN2011_port->ControlRegOffset, Data); - - /* rx_negate */ - Data = 0x0; - status = get_reg_sync(port, ATEN2011_port->ControlRegOffset, &Data); - Data = Data | 0x10; - status = 0; - status = set_reg_sync(port, ATEN2011_port->ControlRegOffset, Data); - - /* - * Check to see if we've set up our endpoint info yet - * (can't set it up in ATEN2011_startup as the structures - * were not set up at that time.) - */ - if (ATEN2011_serial->NoOfOpenPorts == 1) { - /* start the status polling here */ - ATEN2011_serial->status_polling_started = 1; - /* If not yet set, Set here */ - ATEN2011_serial->interrupt_in_buffer = - serial->port[0]->interrupt_in_buffer; - ATEN2011_serial->interrupt_in_endpoint = - serial->port[0]->interrupt_in_endpointAddress; - ATEN2011_serial->interrupt_read_urb = - serial->port[0]->interrupt_in_urb; - - /* set up interrupt urb */ - usb_fill_int_urb(ATEN2011_serial->interrupt_read_urb, - serial->dev, - usb_rcvintpipe(serial->dev, - ATEN2011_serial-> - interrupt_in_endpoint), - ATEN2011_serial->interrupt_in_buffer, - ATEN2011_serial->interrupt_read_urb-> - transfer_buffer_length, - ATEN2011_interrupt_callback, ATEN2011_serial, - ATEN2011_serial->interrupt_read_urb->interval); - - /* start interrupt read for ATEN2011 * - * will continue as long as ATEN2011 is connected */ - - response = - usb_submit_urb(ATEN2011_serial->interrupt_read_urb, - GFP_KERNEL); - if (response) { - dbg("%s - Error %d submitting interrupt urb", - __func__, response); - } - - } - - /* - * See if we've set up our endpoint info yet - * (can't set it up in ATEN2011_startup as the - * structures were not set up at that time.) - */ - - dbg("port number is %d", port->number); - dbg("serial number is %d", port->serial->minor); - dbg("Bulkin endpoint is %d", port->bulk_in_endpointAddress); - dbg("BulkOut endpoint is %d", port->bulk_out_endpointAddress); - dbg("Interrupt endpoint is %d", - port->interrupt_in_endpointAddress); - dbg("port's number in the device is %d", ATEN2011_port->port_num); - ATEN2011_port->bulk_in_buffer = port->bulk_in_buffer; - ATEN2011_port->bulk_in_endpoint = port->bulk_in_endpointAddress; - ATEN2011_port->read_urb = port->read_urb; - ATEN2011_port->bulk_out_endpoint = port->bulk_out_endpointAddress; - - minor = port->serial->minor; - if (minor == SERIAL_TTY_NO_MINOR) - minor = 0; - - /* set up our bulk in urb */ - if ((ATEN2011_serial->ATEN2011_spectrum_2or4ports == 2) - && (((__u16) port->number - (__u16) (minor)) != 0)) { - usb_fill_bulk_urb(ATEN2011_port->read_urb, serial->dev, - usb_rcvbulkpipe(serial->dev, - (port-> - bulk_in_endpointAddress + - 2)), port->bulk_in_buffer, - ATEN2011_port->read_urb-> - transfer_buffer_length, - ATEN2011_bulk_in_callback, ATEN2011_port); - } else - usb_fill_bulk_urb(ATEN2011_port->read_urb, - serial->dev, - usb_rcvbulkpipe(serial->dev, - port-> - bulk_in_endpointAddress), - port->bulk_in_buffer, - ATEN2011_port->read_urb-> - transfer_buffer_length, - ATEN2011_bulk_in_callback, ATEN2011_port); - - dbg("ATEN2011_open: bulkin endpoint is %d", - port->bulk_in_endpointAddress); - response = usb_submit_urb(ATEN2011_port->read_urb, GFP_KERNEL); - if (response) { - err("%s - Error %d submitting control urb", __func__, - response); - } - - /* initialize our wait queues */ - init_waitqueue_head(&ATEN2011_port->wait_chase); - init_waitqueue_head(&ATEN2011_port->wait_command); - - /* initialize our icount structure */ - memset(&(ATEN2011_port->icount), 0x00, sizeof(ATEN2011_port->icount)); - - /* initialize our port settings */ - ATEN2011_port->shadowMCR = MCR_MASTER_IE; /* Must set to enable ints! */ - ATEN2011_port->chaseResponsePending = 0; - /* send a open port command */ - ATEN2011_port->open = 1; - /* ATEN2011_change_port_settings(ATEN2011_port,old_termios); */ - /* Setup termios */ - ATEN2011_set_termios(tty, port, &tmp_termios); - ATEN2011_port->icount.tx = 0; - ATEN2011_port->icount.rx = 0; - - dbg("usb_serial serial:%x ATEN2011_port:%x\nATEN2011_serial:%x usb_serial_port port:%x", - (unsigned int)serial, (unsigned int)ATEN2011_port, - (unsigned int)ATEN2011_serial, (unsigned int)port); - - return 0; - -} - -static int ATEN2011_chars_in_buffer(struct tty_struct *tty) -{ - struct usb_serial_port *port = tty->driver_data; - int i; - int chars = 0; - struct ATENINTL_port *ATEN2011_port; - - /* dbg("%s"," ATEN2011_chars_in_buffer:entering ..........."); */ - - ATEN2011_port = usb_get_serial_port_data(port); - if (ATEN2011_port == NULL) { - dbg("%s", "ATEN2011_break:leaving ..........."); - return -1; - } - - for (i = 0; i < NUM_URBS; ++i) - if (ATEN2011_port->write_urb_pool[i]->status == -EINPROGRESS) - chars += URB_TRANSFER_BUFFER_SIZE; - - dbg("%s - returns %d", __func__, chars); - return chars; - -} - -static void ATEN2011_block_until_tx_empty(struct tty_struct *tty, - struct ATENINTL_port *ATEN2011_port) -{ - int timeout = HZ / 10; - int wait = 30; - int count; - - while (1) { - count = ATEN2011_chars_in_buffer(tty); - - /* Check for Buffer status */ - if (count <= 0) - return; - - /* Block the thread for a while */ - interruptible_sleep_on_timeout(&ATEN2011_port->wait_chase, - timeout); - - /* No activity.. count down section */ - wait--; - if (wait == 0) { - dbg("%s - TIMEOUT", __func__); - return; - } else { - /* Reset timout value back to seconds */ - wait = 30; - } - } -} - -static void ATEN2011_close(struct tty_struct *tty, struct usb_serial_port *port, - struct file *filp) -{ - struct usb_serial *serial; - struct ATENINTL_serial *ATEN2011_serial; - struct ATENINTL_port *ATEN2011_port; - int no_urbs; - __u16 Data; - - dbg("%s", "ATEN2011_close:entering..."); - serial = port->serial; - - /* take the Adpater and port's private data */ - ATEN2011_serial = usb_get_serial_data(serial); - ATEN2011_port = usb_get_serial_port_data(port); - if ((ATEN2011_serial == NULL) || (ATEN2011_port == NULL)) - return; - - if (serial->dev) { - /* flush and block(wait) until tx is empty */ - ATEN2011_block_until_tx_empty(tty, ATEN2011_port); - } - /* kill the ports URB's */ - for (no_urbs = 0; no_urbs < NUM_URBS; no_urbs++) - usb_kill_urb(ATEN2011_port->write_urb_pool[no_urbs]); - /* Freeing Write URBs */ - for (no_urbs = 0; no_urbs < NUM_URBS; ++no_urbs) { - kfree(ATEN2011_port->write_urb_pool[no_urbs]->transfer_buffer); - usb_free_urb(ATEN2011_port->write_urb_pool[no_urbs]); - } - /* While closing port, shutdown all bulk read, write * - * and interrupt read if they exists */ - if (serial->dev) { - if (ATEN2011_port->write_urb) { - dbg("%s", "Shutdown bulk write"); - usb_kill_urb(ATEN2011_port->write_urb); - } - if (ATEN2011_port->read_urb) { - dbg("%s", "Shutdown bulk read"); - usb_kill_urb(ATEN2011_port->read_urb); - } - if ((&ATEN2011_port->control_urb)) { - dbg("%s", "Shutdown control read"); - /* usb_kill_urb (ATEN2011_port->control_urb); */ - - } - } - /* if(ATEN2011_port->ctrl_buf != NULL) */ - /* kfree(ATEN2011_port->ctrl_buf); */ - /* decrement the no.of open ports counter of an individual USB-serial adapter. */ - ATEN2011_serial->NoOfOpenPorts--; - dbg("NoOfOpenPorts in close%d:in port%d", - ATEN2011_serial->NoOfOpenPorts, port->number); - if (ATEN2011_serial->NoOfOpenPorts == 0) { - /* stop the stus polling here */ - ATEN2011_serial->status_polling_started = 0; - if (ATEN2011_serial->interrupt_read_urb) { - dbg("%s", "Shutdown interrupt_read_urb"); - /* ATEN2011_serial->interrupt_in_buffer=NULL; */ - /* usb_kill_urb (ATEN2011_serial->interrupt_read_urb); */ - } - } - if (ATEN2011_port->write_urb) { - /* if this urb had a transfer buffer already (old tx) free it */ - kfree(ATEN2011_port->write_urb->transfer_buffer); - usb_free_urb(ATEN2011_port->write_urb); - } - - /* clear the MCR & IER */ - Data = 0x00; - set_uart_reg(port, MODEM_CONTROL_REGISTER, Data); - Data = 0x00; - set_uart_reg(port, INTERRUPT_ENABLE_REGISTER, Data); - - ATEN2011_port->open = 0; - dbg("%s", "Leaving ............"); - -} - -static void ATEN2011_block_until_chase_response(struct tty_struct *tty, - struct ATENINTL_port - *ATEN2011_port) -{ - int timeout = 1 * HZ; - int wait = 10; - int count; - - while (1) { - count = ATEN2011_chars_in_buffer(tty); - - /* Check for Buffer status */ - if (count <= 0) { - ATEN2011_port->chaseResponsePending = 0; - return; - } - - /* Block the thread for a while */ - interruptible_sleep_on_timeout(&ATEN2011_port->wait_chase, - timeout); - /* No activity.. count down section */ - wait--; - if (wait == 0) { - dbg("%s - TIMEOUT", __func__); - return; - } else { - /* Reset timout value back to seconds */ - wait = 10; - } - } - -} - -static void ATEN2011_break(struct tty_struct *tty, int break_state) -{ - struct usb_serial_port *port = tty->driver_data; - unsigned char data; - struct usb_serial *serial; - struct ATENINTL_serial *ATEN2011_serial; - struct ATENINTL_port *ATEN2011_port; - - dbg("%s", "Entering ..........."); - dbg("ATEN2011_break: Start"); - - serial = port->serial; - - ATEN2011_serial = usb_get_serial_data(serial); - ATEN2011_port = usb_get_serial_port_data(port); - - if ((ATEN2011_serial == NULL) || (ATEN2011_port == NULL)) - return; - - /* flush and chase */ - ATEN2011_port->chaseResponsePending = 1; - - if (serial->dev) { - /* flush and block until tx is empty */ - ATEN2011_block_until_chase_response(tty, ATEN2011_port); - } - - if (break_state == -1) - data = ATEN2011_port->shadowLCR | LCR_SET_BREAK; - else - data = ATEN2011_port->shadowLCR & ~LCR_SET_BREAK; - - ATEN2011_port->shadowLCR = data; - dbg("ATEN2011_break ATEN2011_port->shadowLCR is %x", - ATEN2011_port->shadowLCR); - set_uart_reg(port, LINE_CONTROL_REGISTER, ATEN2011_port->shadowLCR); - - return; -} - -static int ATEN2011_write_room(struct tty_struct *tty) -{ - struct usb_serial_port *port = tty->driver_data; - int i; - int room = 0; - struct ATENINTL_port *ATEN2011_port; - - ATEN2011_port = usb_get_serial_port_data(port); - if (ATEN2011_port == NULL) { - dbg("%s", "ATEN2011_break:leaving ..........."); - return -1; - } - - for (i = 0; i < NUM_URBS; ++i) - if (ATEN2011_port->write_urb_pool[i]->status != -EINPROGRESS) - room += URB_TRANSFER_BUFFER_SIZE; - - dbg("%s - returns %d", __func__, room); - return room; - -} - -static int ATEN2011_write(struct tty_struct *tty, struct usb_serial_port *port, - const unsigned char *data, int count) -{ - int status; - int i; - int bytes_sent = 0; - int transfer_size; - int minor; - - struct ATENINTL_port *ATEN2011_port; - struct usb_serial *serial; - struct ATENINTL_serial *ATEN2011_serial; - struct urb *urb; - const unsigned char *current_position = data; - unsigned char *data1; - dbg("%s", "entering ..........."); - - serial = port->serial; - - ATEN2011_port = usb_get_serial_port_data(port); - if (ATEN2011_port == NULL) { - dbg("%s", "ATEN2011_port is NULL"); - return -1; - } - - ATEN2011_serial = usb_get_serial_data(serial); - if (ATEN2011_serial == NULL) { - dbg("%s", "ATEN2011_serial is NULL"); - return -1; - } - - /* try to find a free urb in the list */ - urb = NULL; - - for (i = 0; i < NUM_URBS; ++i) { - if (ATEN2011_port->write_urb_pool[i]->status != -EINPROGRESS) { - urb = ATEN2011_port->write_urb_pool[i]; - dbg("URB:%d", i); - break; - } - } - - if (urb == NULL) { - dbg("%s - no more free urbs", __func__); - goto exit; - } - - if (urb->transfer_buffer == NULL) { - urb->transfer_buffer = - kmalloc(URB_TRANSFER_BUFFER_SIZE, GFP_KERNEL); - - if (urb->transfer_buffer == NULL) { - err("%s no more kernel memory...", __func__); - goto exit; - } - } - transfer_size = min(count, URB_TRANSFER_BUFFER_SIZE); - - memcpy(urb->transfer_buffer, current_position, transfer_size); - /* usb_serial_debug_data (__FILE__, __func__, transfer_size, urb->transfer_buffer); */ - - /* fill urb with data and submit */ - minor = port->serial->minor; - if (minor == SERIAL_TTY_NO_MINOR) - minor = 0; - if ((ATEN2011_serial->ATEN2011_spectrum_2or4ports == 2) - && (((__u16) port->number - (__u16) (minor)) != 0)) { - usb_fill_bulk_urb(urb, ATEN2011_serial->serial->dev, - usb_sndbulkpipe(ATEN2011_serial->serial->dev, - (port-> - bulk_out_endpointAddress) + - 2), urb->transfer_buffer, - transfer_size, - ATEN2011_bulk_out_data_callback, - ATEN2011_port); - } else - - usb_fill_bulk_urb(urb, - ATEN2011_serial->serial->dev, - usb_sndbulkpipe(ATEN2011_serial->serial->dev, - port-> - bulk_out_endpointAddress), - urb->transfer_buffer, transfer_size, - ATEN2011_bulk_out_data_callback, - ATEN2011_port); - - data1 = urb->transfer_buffer; - dbg("bulkout endpoint is %d", port->bulk_out_endpointAddress); - /* for(i=0;i < urb->actual_length;i++) */ - /* dbg("Data is %c ",data1[i]); */ - - /* send it down the pipe */ - status = usb_submit_urb(urb, GFP_ATOMIC); - - if (status) { - err("%s - usb_submit_urb(write bulk) failed with status = %d", - __func__, status); - bytes_sent = status; - goto exit; - } - bytes_sent = transfer_size; - ATEN2011_port->icount.tx += transfer_size; - dbg("ATEN2011_port->icount.tx is %d:", ATEN2011_port->icount.tx); - -exit: - return bytes_sent; -} - -static void ATEN2011_throttle(struct tty_struct *tty) -{ - struct usb_serial_port *port = tty->driver_data; - struct ATENINTL_port *ATEN2011_port; - int status; - - dbg("- port %d", port->number); - - ATEN2011_port = usb_get_serial_port_data(port); - - if (ATEN2011_port == NULL) - return; - - if (!ATEN2011_port->open) { - dbg("%s", "port not opened"); - return; - } - - dbg("%s", "Entering .......... "); - - if (!tty) { - dbg("%s - no tty available", __func__); - return; - } - - /* if we are implementing XON/XOFF, send the stop character */ - if (I_IXOFF(tty)) { - unsigned char stop_char = STOP_CHAR(tty); - status = ATEN2011_write(tty, port, &stop_char, 1); - if (status <= 0) - return; - } - - /* if we are implementing RTS/CTS, toggle that line */ - if (tty->termios->c_cflag & CRTSCTS) { - ATEN2011_port->shadowMCR &= ~MCR_RTS; - status = set_uart_reg(port, MODEM_CONTROL_REGISTER, - ATEN2011_port->shadowMCR); - if (status < 0) - return; - } - - return; -} - -static void ATEN2011_unthrottle(struct tty_struct *tty) -{ - struct usb_serial_port *port = tty->driver_data; - int status; - struct ATENINTL_port *ATEN2011_port = usb_get_serial_port_data(port); - - if (ATEN2011_port == NULL) - return; - - if (!ATEN2011_port->open) { - dbg("%s - port not opened", __func__); - return; - } - - dbg("%s", "Entering .......... "); - - if (!tty) { - dbg("%s - no tty available", __func__); - return; - } - - /* if we are implementing XON/XOFF, send the start character */ - if (I_IXOFF(tty)) { - unsigned char start_char = START_CHAR(tty); - status = ATEN2011_write(tty, port, &start_char, 1); - if (status <= 0) - return; - } - - /* if we are implementing RTS/CTS, toggle that line */ - if (tty->termios->c_cflag & CRTSCTS) { - ATEN2011_port->shadowMCR |= MCR_RTS; - status = set_uart_reg(port, MODEM_CONTROL_REGISTER, - ATEN2011_port->shadowMCR); - if (status < 0) - return; - } - - return; -} - -static int ATEN2011_tiocmget(struct tty_struct *tty, struct file *file) -{ - struct usb_serial_port *port = tty->driver_data; - struct ATENINTL_port *ATEN2011_port; - unsigned int result; - __u16 msr; - __u16 mcr; - /* unsigned int mcr; */ - int status = 0; - ATEN2011_port = usb_get_serial_port_data(port); - - dbg("%s - port %d", __func__, port->number); - - if (ATEN2011_port == NULL) - return -ENODEV; - - status = get_uart_reg(port, MODEM_STATUS_REGISTER, &msr); - status = get_uart_reg(port, MODEM_CONTROL_REGISTER, &mcr); - /* mcr = ATEN2011_port->shadowMCR; */ - /* COMMENT2: the Fallowing three line are commented for updating only MSR values */ - result = ((mcr & MCR_DTR) ? TIOCM_DTR : 0) - | ((mcr & MCR_RTS) ? TIOCM_RTS : 0) - | ((mcr & MCR_LOOPBACK) ? TIOCM_LOOP : 0) - | ((msr & ATEN2011_MSR_CTS) ? TIOCM_CTS : 0) - | ((msr & ATEN2011_MSR_CD) ? TIOCM_CAR : 0) - | ((msr & ATEN2011_MSR_RI) ? TIOCM_RI : 0) - | ((msr & ATEN2011_MSR_DSR) ? TIOCM_DSR : 0); - - dbg("%s - 0x%04X", __func__, result); - - return result; -} - -static int ATEN2011_tiocmset(struct tty_struct *tty, struct file *file, - unsigned int set, unsigned int clear) -{ - struct usb_serial_port *port = tty->driver_data; - struct ATENINTL_port *ATEN2011_port; - unsigned int mcr; - unsigned int status; - - dbg("%s - port %d", __func__, port->number); - - ATEN2011_port = usb_get_serial_port_data(port); - - if (ATEN2011_port == NULL) - return -ENODEV; - - mcr = ATEN2011_port->shadowMCR; - if (clear & TIOCM_RTS) - mcr &= ~MCR_RTS; - if (clear & TIOCM_DTR) - mcr &= ~MCR_DTR; - if (clear & TIOCM_LOOP) - mcr &= ~MCR_LOOPBACK; - - if (set & TIOCM_RTS) - mcr |= MCR_RTS; - if (set & TIOCM_DTR) - mcr |= MCR_DTR; - if (set & TIOCM_LOOP) - mcr |= MCR_LOOPBACK; - - ATEN2011_port->shadowMCR = mcr; - - status = set_uart_reg(port, MODEM_CONTROL_REGISTER, mcr); - if (status < 0) { - dbg("setting MODEM_CONTROL_REGISTER Failed"); - return -1; - } - - return 0; -} - -static void ATEN2011_set_termios(struct tty_struct *tty, - struct usb_serial_port *port, - struct ktermios *old_termios) -{ - int status; - unsigned int cflag; - struct usb_serial *serial; - struct ATENINTL_port *ATEN2011_port; - - dbg("ATEN2011_set_termios: START"); - - serial = port->serial; - - ATEN2011_port = usb_get_serial_port_data(port); - - if (ATEN2011_port == NULL) - return; - - if (!ATEN2011_port->open) { - dbg("%s - port not opened", __func__); - return; - } - - dbg("%s", "setting termios - "); - - cflag = tty->termios->c_cflag; - - dbg("%s - cflag %08x iflag %08x", __func__, - tty->termios->c_cflag, RELEVANT_IFLAG(tty->termios->c_iflag)); - - if (old_termios) { - dbg("%s - old clfag %08x old iflag %08x", __func__, - old_termios->c_cflag, RELEVANT_IFLAG(old_termios->c_iflag)); - } - - dbg("%s - port %d", __func__, port->number); - - /* change the port settings to the new ones specified */ - - ATEN2011_change_port_settings(tty, ATEN2011_port, old_termios); - - if (!ATEN2011_port->read_urb) { - dbg("%s", "URB KILLED !!!!!"); - return; - } - - if (ATEN2011_port->read_urb->status != -EINPROGRESS) { - ATEN2011_port->read_urb->dev = serial->dev; - status = usb_submit_urb(ATEN2011_port->read_urb, GFP_ATOMIC); - if (status) { - dbg - (" usb_submit_urb(read bulk) failed, status = %d", - status); - } - } - return; -} - -static int get_lsr_info(struct tty_struct *tty, - struct ATENINTL_port *ATEN2011_port, - unsigned int __user *value) -{ - int count; - unsigned int result = 0; - - count = ATEN2011_chars_in_buffer(tty); - if (count == 0) { - dbg("%s -- Empty", __func__); - result = TIOCSER_TEMT; - } - - if (copy_to_user(value, &result, sizeof(int))) - return -EFAULT; - return 0; -} - -static int get_number_bytes_avail(struct tty_struct *tty, - struct ATENINTL_port *ATEN2011_port, - unsigned int __user *value) -{ - unsigned int result = 0; - - if (!tty) - return -ENOIOCTLCMD; - - result = tty->read_cnt; - - dbg("%s(%d) = %d", __func__, ATEN2011_port->port->number, result); - if (copy_to_user(value, &result, sizeof(int))) - return -EFAULT; - - return -ENOIOCTLCMD; -} - -static int set_modem_info(struct ATENINTL_port *ATEN2011_port, unsigned int cmd, - unsigned int __user *value) -{ - unsigned int mcr; - unsigned int arg; - __u16 Data; - int status; - struct usb_serial_port *port; - - if (ATEN2011_port == NULL) - return -1; - - port = (struct usb_serial_port *)ATEN2011_port->port; - - mcr = ATEN2011_port->shadowMCR; - - if (copy_from_user(&arg, value, sizeof(int))) - return -EFAULT; - - switch (cmd) { - case TIOCMBIS: - if (arg & TIOCM_RTS) - mcr |= MCR_RTS; - if (arg & TIOCM_DTR) - mcr |= MCR_RTS; - if (arg & TIOCM_LOOP) - mcr |= MCR_LOOPBACK; - break; - - case TIOCMBIC: - if (arg & TIOCM_RTS) - mcr &= ~MCR_RTS; - if (arg & TIOCM_DTR) - mcr &= ~MCR_RTS; - if (arg & TIOCM_LOOP) - mcr &= ~MCR_LOOPBACK; - break; - - case TIOCMSET: - /* turn off the RTS and DTR and LOOPBACK - * and then only turn on what was asked to */ - mcr &= ~(MCR_RTS | MCR_DTR | MCR_LOOPBACK); - mcr |= ((arg & TIOCM_RTS) ? MCR_RTS : 0); - mcr |= ((arg & TIOCM_DTR) ? MCR_DTR : 0); - mcr |= ((arg & TIOCM_LOOP) ? MCR_LOOPBACK : 0); - break; - } - - ATEN2011_port->shadowMCR = mcr; - - Data = ATEN2011_port->shadowMCR; - status = set_uart_reg(port, MODEM_CONTROL_REGISTER, Data); - if (status < 0) { - dbg("setting MODEM_CONTROL_REGISTER Failed"); - return -1; - } - - return 0; -} - -static int get_modem_info(struct ATENINTL_port *ATEN2011_port, - unsigned int __user *value) -{ - unsigned int result = 0; - __u16 msr; - unsigned int mcr = ATEN2011_port->shadowMCR; - int status; - - status = get_uart_reg(ATEN2011_port->port, MODEM_STATUS_REGISTER, &msr); - result = ((mcr & MCR_DTR) ? TIOCM_DTR : 0) /* 0x002 */ - |((mcr & MCR_RTS) ? TIOCM_RTS : 0) /* 0x004 */ - |((msr & ATEN2011_MSR_CTS) ? TIOCM_CTS : 0) /* 0x020 */ - |((msr & ATEN2011_MSR_CD) ? TIOCM_CAR : 0) /* 0x040 */ - |((msr & ATEN2011_MSR_RI) ? TIOCM_RI : 0) /* 0x080 */ - |((msr & ATEN2011_MSR_DSR) ? TIOCM_DSR : 0); /* 0x100 */ - - dbg("%s -- %x", __func__, result); - - if (copy_to_user(value, &result, sizeof(int))) - return -EFAULT; - return 0; -} - -static int get_serial_info(struct ATENINTL_port *ATEN2011_port, - struct serial_struct __user *retinfo) -{ - struct serial_struct tmp; - - if (ATEN2011_port == NULL) - return -1; - - if (!retinfo) - return -EFAULT; - - memset(&tmp, 0, sizeof(tmp)); - - tmp.type = PORT_16550A; - tmp.line = ATEN2011_port->port->serial->minor; - if (tmp.line == SERIAL_TTY_NO_MINOR) - tmp.line = 0; - tmp.port = ATEN2011_port->port->number; - tmp.irq = 0; - tmp.flags = ASYNC_SKIP_TEST | ASYNC_AUTO_IRQ; - tmp.xmit_fifo_size = NUM_URBS * URB_TRANSFER_BUFFER_SIZE; - tmp.baud_base = 9600; - tmp.close_delay = 5 * HZ; - tmp.closing_wait = 30 * HZ; - - if (copy_to_user(retinfo, &tmp, sizeof(*retinfo))) - return -EFAULT; - return 0; -} - -static int ATEN2011_ioctl(struct tty_struct *tty, struct file *file, - unsigned int cmd, unsigned long arg) -{ - struct usb_serial_port *port = tty->driver_data; - struct ATENINTL_port *ATEN2011_port; - struct async_icount cnow; - struct async_icount cprev; - struct serial_icounter_struct icount; - int ATENret = 0; - unsigned int __user *user_arg = (unsigned int __user *)arg; - - ATEN2011_port = usb_get_serial_port_data(port); - - if (ATEN2011_port == NULL) - return -1; - - dbg("%s - port %d, cmd = 0x%x", __func__, port->number, cmd); - - switch (cmd) { - /* return number of bytes available */ - - case TIOCINQ: - dbg("%s (%d) TIOCINQ", __func__, port->number); - return get_number_bytes_avail(tty, ATEN2011_port, user_arg); - break; - - case TIOCOUTQ: - dbg("%s (%d) TIOCOUTQ", __func__, port->number); - return put_user(ATEN2011_chars_in_buffer(tty), user_arg); - break; - - case TIOCSERGETLSR: - dbg("%s (%d) TIOCSERGETLSR", __func__, port->number); - return get_lsr_info(tty, ATEN2011_port, user_arg); - return 0; - - case TIOCMBIS: - case TIOCMBIC: - case TIOCMSET: - dbg("%s (%d) TIOCMSET/TIOCMBIC/TIOCMSET", __func__, - port->number); - ATENret = set_modem_info(ATEN2011_port, cmd, user_arg); - return ATENret; - - case TIOCMGET: - dbg("%s (%d) TIOCMGET", __func__, port->number); - return get_modem_info(ATEN2011_port, user_arg); - - case TIOCGSERIAL: - dbg("%s (%d) TIOCGSERIAL", __func__, port->number); - return get_serial_info(ATEN2011_port, - (struct serial_struct __user *)arg); - - case TIOCSSERIAL: - dbg("%s (%d) TIOCSSERIAL", __func__, port->number); - break; - - case TIOCMIWAIT: - dbg("%s (%d) TIOCMIWAIT", __func__, port->number); - cprev = ATEN2011_port->icount; - while (1) { - /* see if a signal did it */ - if (signal_pending(current)) - return -ERESTARTSYS; - cnow = ATEN2011_port->icount; - if (cnow.rng == cprev.rng && cnow.dsr == cprev.dsr && - cnow.dcd == cprev.dcd && cnow.cts == cprev.cts) - return -EIO; /* no change => error */ - if (((arg & TIOCM_RNG) && (cnow.rng != cprev.rng)) || - ((arg & TIOCM_DSR) && (cnow.dsr != cprev.dsr)) || - ((arg & TIOCM_CD) && (cnow.dcd != cprev.dcd)) || - ((arg & TIOCM_CTS) && (cnow.cts != cprev.cts))) { - return 0; - } - cprev = cnow; - } - /* NOTREACHED */ - break; - - case TIOCGICOUNT: - cnow = ATEN2011_port->icount; - icount.cts = cnow.cts; - icount.dsr = cnow.dsr; - icount.rng = cnow.rng; - icount.dcd = cnow.dcd; - icount.rx = cnow.rx; - icount.tx = cnow.tx; - icount.frame = cnow.frame; - icount.overrun = cnow.overrun; - icount.parity = cnow.parity; - icount.brk = cnow.brk; - icount.buf_overrun = cnow.buf_overrun; - - dbg("%s (%d) TIOCGICOUNT RX=%d, TX=%d", __func__, - port->number, icount.rx, icount.tx); - if (copy_to_user((void __user *)arg, &icount, sizeof(icount))) - return -EFAULT; - return 0; - - default: - break; - } - - return -ENOIOCTLCMD; -} - -static int ATEN2011_calc_baud_rate_divisor(int baudRate, int *divisor, - __u16 *clk_sel_val) -{ - dbg("%s - %d", __func__, baudRate); - - if (baudRate <= 115200) { - *divisor = 115200 / baudRate; - *clk_sel_val = 0x0; - } - if ((baudRate > 115200) && (baudRate <= 230400)) { - *divisor = 230400 / baudRate; - *clk_sel_val = 0x10; - } else if ((baudRate > 230400) && (baudRate <= 403200)) { - *divisor = 403200 / baudRate; - *clk_sel_val = 0x20; - } else if ((baudRate > 403200) && (baudRate <= 460800)) { - *divisor = 460800 / baudRate; - *clk_sel_val = 0x30; - } else if ((baudRate > 460800) && (baudRate <= 806400)) { - *divisor = 806400 / baudRate; - *clk_sel_val = 0x40; - } else if ((baudRate > 806400) && (baudRate <= 921600)) { - *divisor = 921600 / baudRate; - *clk_sel_val = 0x50; - } else if ((baudRate > 921600) && (baudRate <= 1572864)) { - *divisor = 1572864 / baudRate; - *clk_sel_val = 0x60; - } else if ((baudRate > 1572864) && (baudRate <= 3145728)) { - *divisor = 3145728 / baudRate; - *clk_sel_val = 0x70; - } - return 0; -} - -static int ATEN2011_send_cmd_write_baud_rate(struct ATENINTL_port - *ATEN2011_port, int baudRate) -{ - int divisor = 0; - int status; - __u16 Data; - unsigned char number; - __u16 clk_sel_val; - struct usb_serial_port *port; - int minor; - - if (ATEN2011_port == NULL) - return -1; - - port = (struct usb_serial_port *)ATEN2011_port->port; - - dbg("%s", "Entering .......... "); - - minor = ATEN2011_port->port->serial->minor; - if (minor == SERIAL_TTY_NO_MINOR) - minor = 0; - number = ATEN2011_port->port->number - minor; - - dbg("%s - port = %d, baud = %d", __func__, - ATEN2011_port->port->number, baudRate); - /* reset clk_uart_sel in spregOffset */ - if (baudRate > 115200) { -#ifdef HW_flow_control - /* - * NOTE: need to see the pther register to modify - * setting h/w flow control bit to 1; - */ - /* Data = ATEN2011_port->shadowMCR; */ - Data = 0x2b; - ATEN2011_port->shadowMCR = Data; - status = set_uart_reg(port, MODEM_CONTROL_REGISTER, Data); - if (status < 0) { - dbg("Writing spreg failed in set_serial_baud"); - return -1; - } -#endif - - } else { -#ifdef HW_flow_control - /* setting h/w flow control bit to 0; */ - /* Data = ATEN2011_port->shadowMCR; */ - Data = 0xb; - ATEN2011_port->shadowMCR = Data; - status = set_uart_reg(port, MODEM_CONTROL_REGISTER, Data); - if (status < 0) { - dbg("Writing spreg failed in set_serial_baud"); - return -1; - } -#endif - - } - - if (1) /* baudRate <= 115200) */ { - clk_sel_val = 0x0; - Data = 0x0; - status = - ATEN2011_calc_baud_rate_divisor(baudRate, &divisor, - &clk_sel_val); - status = get_reg_sync(port, ATEN2011_port->SpRegOffset, &Data); - if (status < 0) { - dbg("reading spreg failed in set_serial_baud"); - return -1; - } - Data = (Data & 0x8f) | clk_sel_val; - status = set_reg_sync(port, ATEN2011_port->SpRegOffset, Data); - if (status < 0) { - dbg("Writing spreg failed in set_serial_baud"); - return -1; - } - /* Calculate the Divisor */ - - if (status) { - err("%s - bad baud rate", __func__); - dbg("%s", "bad baud rate"); - return status; - } - /* Enable access to divisor latch */ - Data = ATEN2011_port->shadowLCR | SERIAL_LCR_DLAB; - ATEN2011_port->shadowLCR = Data; - set_uart_reg(port, LINE_CONTROL_REGISTER, Data); - - /* Write the divisor */ - Data = (unsigned char)(divisor & 0xff); - dbg("set_serial_baud Value to write DLL is %x", Data); - set_uart_reg(port, DIVISOR_LATCH_LSB, Data); - - Data = (unsigned char)((divisor & 0xff00) >> 8); - dbg("set_serial_baud Value to write DLM is %x", Data); - set_uart_reg(port, DIVISOR_LATCH_MSB, Data); - - /* Disable access to divisor latch */ - Data = ATEN2011_port->shadowLCR & ~SERIAL_LCR_DLAB; - ATEN2011_port->shadowLCR = Data; - set_uart_reg(port, LINE_CONTROL_REGISTER, Data); - - } - - return status; -} - -static void ATEN2011_change_port_settings(struct tty_struct *tty, - struct ATENINTL_port *ATEN2011_port, - struct ktermios *old_termios) -{ - int baud; - unsigned cflag; - unsigned iflag; - __u8 lData; - __u8 lParity; - __u8 lStop; - int status; - __u16 Data; - struct usb_serial_port *port; - struct usb_serial *serial; - - if (ATEN2011_port == NULL) - return; - - port = (struct usb_serial_port *)ATEN2011_port->port; - - serial = port->serial; - - dbg("%s - port %d", __func__, ATEN2011_port->port->number); - - if (!ATEN2011_port->open) { - dbg("%s - port not opened", __func__); - return; - } - - if ((!tty) || (!tty->termios)) { - dbg("%s - no tty structures", __func__); - return; - } - - dbg("%s", "Entering .......... "); - - lData = LCR_BITS_8; - lStop = LCR_STOP_1; - lParity = LCR_PAR_NONE; - - cflag = tty->termios->c_cflag; - iflag = tty->termios->c_iflag; - - /* Change the number of bits */ - - /* COMMENT1: the below Line"if(cflag & CSIZE)" is added for the errors we get for serial loop data test i.e serial_loopback.pl -v */ - /* if(cflag & CSIZE) */ - { - switch (cflag & CSIZE) { - case CS5: - lData = LCR_BITS_5; - break; - - case CS6: - lData = LCR_BITS_6; - break; - - case CS7: - lData = LCR_BITS_7; - break; - default: - case CS8: - lData = LCR_BITS_8; - break; - } - } - /* Change the Parity bit */ - if (cflag & PARENB) { - if (cflag & PARODD) { - lParity = LCR_PAR_ODD; - dbg("%s - parity = odd", __func__); - } else { - lParity = LCR_PAR_EVEN; - dbg("%s - parity = even", __func__); - } - - } else { - dbg("%s - parity = none", __func__); - } - - if (cflag & CMSPAR) - lParity = lParity | 0x20; - - /* Change the Stop bit */ - if (cflag & CSTOPB) { - lStop = LCR_STOP_2; - dbg("%s - stop bits = 2", __func__); - } else { - lStop = LCR_STOP_1; - dbg("%s - stop bits = 1", __func__); - } - - /* Update the LCR with the correct value */ - ATEN2011_port->shadowLCR &= - ~(LCR_BITS_MASK | LCR_STOP_MASK | LCR_PAR_MASK); - ATEN2011_port->shadowLCR |= (lData | lParity | lStop); - - dbg - ("ATEN2011_change_port_settings ATEN2011_port->shadowLCR is %x", - ATEN2011_port->shadowLCR); - /* Disable Interrupts */ - Data = 0x00; - set_uart_reg(port, INTERRUPT_ENABLE_REGISTER, Data); - - Data = 0x00; - set_uart_reg(port, FIFO_CONTROL_REGISTER, Data); - - Data = 0xcf; - set_uart_reg(port, FIFO_CONTROL_REGISTER, Data); - - /* Send the updated LCR value to the ATEN2011 */ - Data = ATEN2011_port->shadowLCR; - - set_uart_reg(port, LINE_CONTROL_REGISTER, Data); - - Data = 0x00b; - ATEN2011_port->shadowMCR = Data; - set_uart_reg(port, MODEM_CONTROL_REGISTER, Data); - Data = 0x00b; - set_uart_reg(port, MODEM_CONTROL_REGISTER, Data); - - /* set up the MCR register and send it to the ATEN2011 */ - - ATEN2011_port->shadowMCR = MCR_MASTER_IE; - if (cflag & CBAUD) - ATEN2011_port->shadowMCR |= (MCR_DTR | MCR_RTS); - - if (cflag & CRTSCTS) - ATEN2011_port->shadowMCR |= (MCR_XON_ANY); - else - ATEN2011_port->shadowMCR &= ~(MCR_XON_ANY); - - Data = ATEN2011_port->shadowMCR; - set_uart_reg(port, MODEM_CONTROL_REGISTER, Data); - - /* Determine divisor based on baud rate */ - baud = tty_get_baud_rate(tty); - - if (!baud) { - /* pick a default, any default... */ - dbg("%s", "Picked default baud..."); - baud = 9600; - } - - dbg("%s - baud rate = %d", __func__, baud); - status = ATEN2011_send_cmd_write_baud_rate(ATEN2011_port, baud); - - /* Enable Interrupts */ - Data = 0x0c; - set_uart_reg(port, INTERRUPT_ENABLE_REGISTER, Data); - - if (ATEN2011_port->read_urb->status != -EINPROGRESS) { - ATEN2011_port->read_urb->dev = serial->dev; - - status = usb_submit_urb(ATEN2011_port->read_urb, GFP_ATOMIC); - - if (status) { - dbg - (" usb_submit_urb(read bulk) failed, status = %d", - status); - } - } - dbg - ("ATEN2011_change_port_settings ATEN2011_port->shadowLCR is End %x", - ATEN2011_port->shadowLCR); - - return; -} - -static int ATEN2011_calc_num_ports(struct usb_serial *serial) -{ - - __u16 Data = 0x00; - int ret = 0; - int ATEN2011_2or4ports; - ret = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0), - ATEN_RDREQ, ATEN_RD_RTYPE, 0, GPIO_REGISTER, - &Data, VENDOR_READ_LENGTH, ATEN_WDR_TIMEOUT); - -/* ghostgum: here is where the problem appears to bet */ -/* Which of the following are needed? */ -/* Greg used the serial->type->num_ports=2 */ -/* But the code in the ATEN2011_open relies on serial->num_ports=2 */ - if ((Data & 0x01) == 0) { - ATEN2011_2or4ports = 2; - serial->type->num_ports = 2; - serial->num_ports = 2; - } - /* else if(serial->interface->cur_altsetting->desc.bNumEndpoints == 9) */ - else { - ATEN2011_2or4ports = 4; - serial->type->num_ports = 4; - serial->num_ports = 4; - - } - - return ATEN2011_2or4ports; -} - -static int ATEN2011_startup(struct usb_serial *serial) -{ - struct ATENINTL_serial *ATEN2011_serial; - struct ATENINTL_port *ATEN2011_port; - struct usb_device *dev; - int i, status; - int minor; - - __u16 Data; - dbg("%s", " ATEN2011_startup :entering.........."); - - if (!serial) { - dbg("%s", "Invalid Handler"); - return -1; - } - - dev = serial->dev; - - dbg("%s", "Entering..."); - - /* create our private serial structure */ - ATEN2011_serial = kzalloc(sizeof(struct ATENINTL_serial), GFP_KERNEL); - if (ATEN2011_serial == NULL) { - err("%s - Out of memory", __func__); - return -ENOMEM; - } - - /* resetting the private structure field values to zero */ - memset(ATEN2011_serial, 0, sizeof(struct ATENINTL_serial)); - - ATEN2011_serial->serial = serial; - /* initilize status polling flag to 0 */ - ATEN2011_serial->status_polling_started = 0; - - usb_set_serial_data(serial, ATEN2011_serial); - ATEN2011_serial->ATEN2011_spectrum_2or4ports = - ATEN2011_calc_num_ports(serial); - /* we set up the pointers to the endpoints in the ATEN2011_open * - * function, as the structures aren't created yet. */ - - /* set up port private structures */ - for (i = 0; i < serial->num_ports; ++i) { - ATEN2011_port = - kmalloc(sizeof(struct ATENINTL_port), GFP_KERNEL); - if (ATEN2011_port == NULL) { - err("%s - Out of memory", __func__); - usb_set_serial_data(serial, NULL); - kfree(ATEN2011_serial); - return -ENOMEM; - } - memset(ATEN2011_port, 0, sizeof(struct ATENINTL_port)); - - /* - * Initialize all port interrupt end point to port 0 - * int endpoint. Our device has only one interrupt end point - * comman to all port - */ - /* serial->port[i]->interrupt_in_endpointAddress = serial->port[0]->interrupt_in_endpointAddress; */ - - ATEN2011_port->port = serial->port[i]; - usb_set_serial_port_data(serial->port[i], ATEN2011_port); - - minor = serial->port[i]->serial->minor; - if (minor == SERIAL_TTY_NO_MINOR) - minor = 0; - ATEN2011_port->port_num = - ((serial->port[i]->number - minor) + 1); - - if (ATEN2011_port->port_num == 1) { - ATEN2011_port->SpRegOffset = 0x0; - ATEN2011_port->ControlRegOffset = 0x1; - ATEN2011_port->DcrRegOffset = 0x4; - } else if ((ATEN2011_port->port_num == 2) - && (ATEN2011_serial->ATEN2011_spectrum_2or4ports == - 4)) { - ATEN2011_port->SpRegOffset = 0x8; - ATEN2011_port->ControlRegOffset = 0x9; - ATEN2011_port->DcrRegOffset = 0x16; - } else if ((ATEN2011_port->port_num == 2) - && (ATEN2011_serial->ATEN2011_spectrum_2or4ports == - 2)) { - ATEN2011_port->SpRegOffset = 0xa; - ATEN2011_port->ControlRegOffset = 0xb; - ATEN2011_port->DcrRegOffset = 0x19; - } else if ((ATEN2011_port->port_num == 3) - && (ATEN2011_serial->ATEN2011_spectrum_2or4ports == - 4)) { - ATEN2011_port->SpRegOffset = 0xa; - ATEN2011_port->ControlRegOffset = 0xb; - ATEN2011_port->DcrRegOffset = 0x19; - } else if ((ATEN2011_port->port_num == 4) - && (ATEN2011_serial->ATEN2011_spectrum_2or4ports == - 4)) { - ATEN2011_port->SpRegOffset = 0xc; - ATEN2011_port->ControlRegOffset = 0xd; - ATEN2011_port->DcrRegOffset = 0x1c; - } - - usb_set_serial_port_data(serial->port[i], ATEN2011_port); - - /* enable rx_disable bit in control register */ - - status = get_reg_sync(serial->port[i], - ATEN2011_port->ControlRegOffset, &Data); - if (status < 0) { - dbg("Reading ControlReg failed status-0x%x", - status); - break; - } else - dbg - ("ControlReg Reading success val is %x, status%d", - Data, status); - Data |= 0x08; /* setting driver done bit */ - Data |= 0x04; /* sp1_bit to have cts change reflect in modem status reg */ - - /* Data |= 0x20; */ /* rx_disable bit */ - status = set_reg_sync(serial->port[i], - ATEN2011_port->ControlRegOffset, Data); - if (status < 0) { - dbg - ("Writing ControlReg failed(rx_disable) status-0x%x", - status); - break; - } else - dbg - ("ControlReg Writing success(rx_disable) status%d", - status); - - /* - * Write default values in DCR (i.e 0x01 in DCR0, 0x05 in DCR2 - * and 0x24 in DCR3 - */ - Data = 0x01; - status = set_reg_sync(serial->port[i], - (__u16)(ATEN2011_port->DcrRegOffset + 0), - Data); - if (status < 0) { - dbg("Writing DCR0 failed status-0x%x", status); - break; - } else - dbg("DCR0 Writing success status%d", status); - - Data = 0x05; - status = set_reg_sync(serial->port[i], - (__u16)(ATEN2011_port->DcrRegOffset + 1), - Data); - if (status < 0) { - dbg("Writing DCR1 failed status-0x%x", status); - break; - } else - dbg("DCR1 Writing success status%d", status); - - Data = 0x24; - status = set_reg_sync(serial->port[i], - (__u16)(ATEN2011_port->DcrRegOffset + 2), - Data); - if (status < 0) { - dbg("Writing DCR2 failed status-0x%x", status); - break; - } else - dbg("DCR2 Writing success status%d", status); - - /* write values in clkstart0x0 and clkmulti 0x20 */ - Data = 0x0; - status = set_reg_sync(serial->port[i], CLK_START_VALUE_REGISTER, - Data); - if (status < 0) { - dbg - ("Writing CLK_START_VALUE_REGISTER failed status-0x%x", - status); - break; - } else - dbg - ("CLK_START_VALUE_REGISTER Writing success status%d", - status); - - Data = 0x20; - status = set_reg_sync(serial->port[i], CLK_MULTI_REGISTER, - Data); - if (status < 0) { - dbg - ("Writing CLK_MULTI_REGISTER failed status-0x%x", - status); - break; - } else - dbg("CLK_MULTI_REGISTER Writing success status%d", - status); - - /* Zero Length flag register */ - if ((ATEN2011_port->port_num != 1) - && (ATEN2011_serial->ATEN2011_spectrum_2or4ports == 2)) { - - Data = 0xff; - status = set_reg_sync(serial->port[i], - (__u16)(ZLP_REG1 + ((__u16)ATEN2011_port->port_num)), - Data); - dbg("ZLIP offset%x", - (__u16) (ZLP_REG1 + - ((__u16) ATEN2011_port->port_num))); - if (status < 0) { - dbg - ("Writing ZLP_REG%d failed status-0x%x", - i + 2, status); - break; - } else - dbg("ZLP_REG%d Writing success status%d", - i + 2, status); - } else { - Data = 0xff; - status = set_reg_sync(serial->port[i], - (__u16)(ZLP_REG1 + ((__u16)ATEN2011_port->port_num) - 0x1), - Data); - dbg("ZLIP offset%x", - (__u16) (ZLP_REG1 + - ((__u16) ATEN2011_port->port_num) - - 0x1)); - if (status < 0) { - dbg - ("Writing ZLP_REG%d failed status-0x%x", - i + 1, status); - break; - } else - dbg("ZLP_REG%d Writing success status%d", - i + 1, status); - - } - ATEN2011_port->control_urb = usb_alloc_urb(0, GFP_ATOMIC); - ATEN2011_port->ctrl_buf = kmalloc(16, GFP_KERNEL); - - } - - /* Zero Length flag enable */ - Data = 0x0f; - status = set_reg_sync(serial->port[0], ZLP_REG5, Data); - if (status < 0) { - dbg("Writing ZLP_REG5 failed status-0x%x", status); - return -1; - } else - dbg("ZLP_REG5 Writing success status%d", status); - - /* setting configuration feature to one */ - usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), - (__u8) 0x03, 0x00, 0x01, 0x00, NULL, 0x00, 5 * HZ); - return 0; -} - -static void ATEN2011_release(struct usb_serial *serial) -{ - int i; - struct ATENINTL_port *ATEN2011_port; - - /* check for the ports to be closed,close the ports and disconnect */ - - /* free private structure allocated for serial port * - * stop reads and writes on all ports */ - - for (i = 0; i < serial->num_ports; ++i) { - ATEN2011_port = usb_get_serial_port_data(serial->port[i]); - kfree(ATEN2011_port->ctrl_buf); - usb_kill_urb(ATEN2011_port->control_urb); - kfree(ATEN2011_port); - usb_set_serial_port_data(serial->port[i], NULL); - } - - /* free private structure allocated for serial device */ - - kfree(usb_get_serial_data(serial)); - usb_set_serial_data(serial, NULL); -} - -static struct usb_serial_driver aten_serial_driver = { - .driver = { - .owner = THIS_MODULE, - .name = "aten2011", - }, - .description = DRIVER_DESC, - .id_table = id_table, - .open = ATEN2011_open, - .close = ATEN2011_close, - .write = ATEN2011_write, - .write_room = ATEN2011_write_room, - .chars_in_buffer = ATEN2011_chars_in_buffer, - .throttle = ATEN2011_throttle, - .unthrottle = ATEN2011_unthrottle, - .calc_num_ports = ATEN2011_calc_num_ports, - - .ioctl = ATEN2011_ioctl, - .set_termios = ATEN2011_set_termios, - .break_ctl = ATEN2011_break, - .tiocmget = ATEN2011_tiocmget, - .tiocmset = ATEN2011_tiocmset, - .attach = ATEN2011_startup, - .release = ATEN2011_release, - .read_bulk_callback = ATEN2011_bulk_in_callback, - .read_int_callback = ATEN2011_interrupt_callback, -}; - -static struct usb_driver aten_driver = { - .name = "aten2011", - .probe = usb_serial_probe, - .disconnect = usb_serial_disconnect, - .id_table = id_table, -}; - -static int __init aten_init(void) -{ - int retval; - - /* Register with the usb serial */ - retval = usb_serial_register(&aten_serial_driver); - if (retval) - return retval; - - printk(KERN_INFO KBUILD_MODNAME ":" - DRIVER_DESC " " DRIVER_VERSION "\n"); - - /* Register with the usb */ - retval = usb_register(&aten_driver); - if (retval) - usb_serial_deregister(&aten_serial_driver); - - return retval; -} - -static void __exit aten_exit(void) -{ - usb_deregister(&aten_driver); - usb_serial_deregister(&aten_serial_driver); -} - -module_init(aten_init); -module_exit(aten_exit); - -/* Module information */ -MODULE_DESCRIPTION(DRIVER_DESC); -MODULE_LICENSE("GPL"); - -MODULE_PARM_DESC(debug, "Debug enabled or not"); -- cgit v1.2.3 From fb29900217bd89370974870d47cab07bad3e5ac4 Mon Sep 17 00:00:00 2001 From: Amit Kucheria Date: Mon, 27 Jul 2009 12:01:03 +0300 Subject: staging: udlfb: Add vmalloc.h include Required for vmalloc_32 and vfree declarations on non-x86 platforms. Signed-off-by: Amit Kucheria Signed-off-by: Greg Kroah-Hartman --- drivers/staging/udlfb/udlfb.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/staging/udlfb/udlfb.c b/drivers/staging/udlfb/udlfb.c index 0ab9d15f3439..f5416af1e902 100644 --- a/drivers/staging/udlfb/udlfb.c +++ b/drivers/staging/udlfb/udlfb.c @@ -21,6 +21,7 @@ #include #include #include +#include #include "udlfb.h" -- cgit v1.2.3 From f99aa3f9b67ca8c29dc29ef3fc453f0343206c46 Mon Sep 17 00:00:00 2001 From: "Carlos R. Mafra" Date: Mon, 13 Jul 2009 21:45:03 +0200 Subject: USB: option: Remove unused variable After commit f092c240494f2d807401d93f95f683909b90af96 ("USB: option: remove unnecessary and erroneous code") the variable 'serial' becomes unused, as gcc-4.3.2 points out: drivers/usb/serial/option.c: In function 'option_instat_callback': drivers/usb/serial/option.c:834: warning: unused variable 'serial' drivers/usb/serial/option.c: In function 'option_open': drivers/usb/serial/option.c:930: warning: unused variable 'serial' So I removed it. Signed-off-by: Carlos R. Mafra Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/option.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index 98262dd552bb..77b9563ec43e 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -831,7 +831,6 @@ static void option_instat_callback(struct urb *urb) int status = urb->status; struct usb_serial_port *port = urb->context; struct option_port_private *portdata = usb_get_serial_port_data(port); - struct usb_serial *serial = port->serial; dbg("%s", __func__); dbg("%s: urb %p port %p has data %p", __func__, urb, port, portdata); @@ -927,7 +926,6 @@ static int option_open(struct tty_struct *tty, struct usb_serial_port *port, struct file *filp) { struct option_port_private *portdata; - struct usb_serial *serial = port->serial; int i, err; struct urb *urb; -- cgit v1.2.3 From 5f4fab91f2b12c12f0506b4da49ed199db8c64ed Mon Sep 17 00:00:00 2001 From: Oliver Neukum Date: Mon, 13 Jul 2009 23:24:10 +0200 Subject: USB: let the option driver compile without CONFIG_PM This is needed for compilation without CONFIG_PM. Signed-off-by: Oliver Neukum Acked-by: Randy Dunlap Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/option.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index 77b9563ec43e..7638d2632ff8 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -66,8 +66,10 @@ static int option_tiocmget(struct tty_struct *tty, struct file *file); static int option_tiocmset(struct tty_struct *tty, struct file *file, unsigned int set, unsigned int clear); static int option_send_setup(struct usb_serial_port *port); +#ifdef CONFIG_PM static int option_suspend(struct usb_serial *serial, pm_message_t message); static int option_resume(struct usb_serial *serial); +#endif /* Vendor and product IDs */ #define OPTION_VENDOR_ID 0x0AF0 @@ -555,8 +557,10 @@ static struct usb_driver option_driver = { .name = "option", .probe = usb_serial_probe, .disconnect = usb_serial_disconnect, +#ifdef CONFIG_PM .suspend = usb_serial_suspend, .resume = usb_serial_resume, +#endif .id_table = option_ids, .no_dynamic_id = 1, }; @@ -588,8 +592,10 @@ static struct usb_serial_driver option_1port_device = { .disconnect = option_disconnect, .release = option_release, .read_int_callback = option_instat_callback, +#ifdef CONFIG_PM .suspend = option_suspend, .resume = option_resume, +#endif }; static int debug; @@ -1185,6 +1191,7 @@ static void option_release(struct usb_serial *serial) } } +#ifdef CONFIG_PM static int option_suspend(struct usb_serial *serial, pm_message_t message) { dbg("%s entered", __func__); @@ -1243,6 +1250,7 @@ static int option_resume(struct usb_serial *serial) } return 0; } +#endif MODULE_AUTHOR(DRIVER_AUTHOR); MODULE_DESCRIPTION(DRIVER_DESC); -- cgit v1.2.3 From 7a777919bbeec3eac1d7904a728a60e9c2bb9c67 Mon Sep 17 00:00:00 2001 From: Giacomo Lozito Date: Mon, 13 Jul 2009 23:23:33 +0200 Subject: USB: storage: raise timeout in usb_stor_Bulk_max_lun Requests to get max LUN, for certain USB storage devices, require a longer timeout before a correct reply is returned. This happens for a Realtek USB Card Reader (0bda:0152), which has a max LUN of 3 but is set to 0, thus losing functionality, because of the timeout occurring too quickly. Raising the timeout value fixes the issue and might help other devices to return a correct max LUN value as well. Signed-off-by: Giacomo Lozito Acked-by: Alan Stern Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/usb/storage/transport.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/storage/transport.c b/drivers/usb/storage/transport.c index fcb320217218..e20dc525d177 100644 --- a/drivers/usb/storage/transport.c +++ b/drivers/usb/storage/transport.c @@ -961,7 +961,7 @@ int usb_stor_Bulk_max_lun(struct us_data *us) US_BULK_GET_MAX_LUN, USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE, - 0, us->ifnum, us->iobuf, 1, HZ); + 0, us->ifnum, us->iobuf, 1, 10*HZ); US_DEBUGP("GetMaxLUN command result is %d, data is %d\n", result, us->iobuf[0]); -- cgit v1.2.3 From 715bfc22ce952a14fac0b9200fd70d81c1951091 Mon Sep 17 00:00:00 2001 From: Anand Gadiyar Date: Tue, 14 Jul 2009 16:41:00 +0530 Subject: USB: OMAP: OHCI: hc_driver's stop method should call ohci_stop OMAP: OHCI: hc_driver's stop method should call ohci_stop Without this, the ohci-omap driver will not cleanup the debugfs nodes when the driver is unloaded. So the next insmod will fail, if CONFIG_DEBUG_FS and CONFIG_USB_DEBUG are both selected. Reported-by: vikram pandita Cc: David Brownell Signed-off-by: Anand Gadiyar Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ohci-omap.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/usb/host/ohci-omap.c b/drivers/usb/host/ohci-omap.c index f3aaba35e912..83cbecd2a1ed 100644 --- a/drivers/usb/host/ohci-omap.c +++ b/drivers/usb/host/ohci-omap.c @@ -282,6 +282,7 @@ static int ohci_omap_init(struct usb_hcd *hcd) static void ohci_omap_stop(struct usb_hcd *hcd) { dev_dbg(hcd->self.controller, "stopping USB Controller\n"); + ohci_stop(hcd); omap_ohci_clock_power(0); } -- cgit v1.2.3 From fca4404c55ab44c7413769f1d9c66451103711a5 Mon Sep 17 00:00:00 2001 From: Ville Sundberg Date: Wed, 15 Jul 2009 00:27:28 +0300 Subject: USB: ftdi_sio: Add support for GN Otometrics Aurical USB Audiometer The patch adds support for the GN Otometrics Aurical USB Audiometer (FT232BM-based). A new VID and a new PID is added. Signed-off-by: Ville Sundberg Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/ftdi_sio.c | 1 + drivers/usb/serial/ftdi_sio.h | 7 +++++++ 2 files changed, 8 insertions(+) diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index 60c64cc5be2a..b574878c78b2 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c @@ -698,6 +698,7 @@ static struct usb_device_id id_table_combined [] = { { USB_DEVICE(MARVELL_VID, MARVELL_SHEEVAPLUG_PID), .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk }, { USB_DEVICE(LARSENBRUSGAARD_VID, LB_ALTITRACK_PID) }, + { USB_DEVICE(GN_OTOMETRICS_VID, AURICAL_USB_PID) }, { }, /* Optional parameter entry */ { } /* Terminating entry */ }; diff --git a/drivers/usb/serial/ftdi_sio.h b/drivers/usb/serial/ftdi_sio.h index c9fbd7415092..24dbd99e87d7 100644 --- a/drivers/usb/serial/ftdi_sio.h +++ b/drivers/usb/serial/ftdi_sio.h @@ -946,6 +946,13 @@ #define FTDI_TURTELIZER_PID 0xBDC8 /* JTAG/RS-232 adapter by egnite GmBH */ +/* + * GN Otometrics (http://www.otometrics.com) + * Submitted by Ville Sundberg. + */ +#define GN_OTOMETRICS_VID 0x0c33 /* Vendor ID */ +#define AURICAL_USB_PID 0x0010 /* Aurical USB Audiometer */ + /* * BmRequestType: 1100 0000b * bRequest: FTDI_E2_READ -- cgit v1.2.3 From 8bf16ba7c8ea9d067914e270764c14020a26232f Mon Sep 17 00:00:00 2001 From: Craig Shelley Date: Sun, 12 Jul 2009 21:52:33 +0100 Subject: USB: CP210x Add new device IDs Signed-off-by: Craig Shelley Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/cp210x.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/usb/serial/cp210x.c b/drivers/usb/serial/cp210x.c index e9a40b820fd4..985cbcf48bda 100644 --- a/drivers/usb/serial/cp210x.c +++ b/drivers/usb/serial/cp210x.c @@ -80,6 +80,7 @@ static struct usb_device_id id_table [] = { { USB_DEVICE(0x10C4, 0x80F6) }, /* Suunto sports instrument */ { USB_DEVICE(0x10C4, 0x8115) }, /* Arygon NFC/Mifare Reader */ { USB_DEVICE(0x10C4, 0x813D) }, /* Burnside Telecom Deskmobile */ + { USB_DEVICE(0x10C4, 0x813F) }, /* Tams Master Easy Control */ { USB_DEVICE(0x10C4, 0x814A) }, /* West Mountain Radio RIGblaster P&P */ { USB_DEVICE(0x10C4, 0x814B) }, /* West Mountain Radio RIGtalk */ { USB_DEVICE(0x10C4, 0x815E) }, /* Helicomm IP-Link 1220-DVM */ @@ -96,7 +97,9 @@ static struct usb_device_id id_table [] = { { USB_DEVICE(0x10c4, 0x8293) }, /* Telegesys ETRX2USB */ { USB_DEVICE(0x10C4, 0x82F9) }, /* Procyon AVS */ { USB_DEVICE(0x10C4, 0x8341) }, /* Siemens MC35PU GPRS Modem */ + { USB_DEVICE(0x10C4, 0x8382) }, /* Cygnal Integrated Products, Inc. */ { USB_DEVICE(0x10C4, 0x83A8) }, /* Amber Wireless AMB2560 */ + { USB_DEVICE(0x10C4, 0x8411) }, /* Kyocera GPS Module */ { USB_DEVICE(0x10C4, 0x846E) }, /* BEI USB Sensor Interface (VCP) */ { USB_DEVICE(0x10C4, 0xEA60) }, /* Silicon Labs factory default */ { USB_DEVICE(0x10C4, 0xEA61) }, /* Silicon Labs factory default */ -- cgit v1.2.3 From bcfa4e68d8d0ea617bde4203b2b3848f5a49a423 Mon Sep 17 00:00:00 2001 From: Simon Kagstrom Date: Mon, 13 Jul 2009 08:25:09 +0200 Subject: USB: ehci-orion: Call ehci_reset before ehci_halt I noticed that USB initialization didn't setup correctly on my kirkwood based board (OpenRD base) if I hadn't initialized USB in U-boot first. The error message looks like this: ehci_hcd: USB 2.0 'Enhanced' Host Controller (EHCI) Driver orion-ehci orion-ehci.0: Marvell Orion EHCI orion-ehci orion-ehci.0: new USB bus registered, assigned bus number 1 orion-ehci orion-ehci.0: can't setup orion-ehci orion-ehci.0: USB bus 1 deregistered orion-ehci orion-ehci.0: init orion-ehci.0 fail, -110 orion-ehci: probe of orion-ehci.0 failed with error -110 which is caused by ehci_halt() timing out in the handshake() call. I noticed that U-boot does a reset before calling handshake(), so this patch does the same thing for Linux. USB now works for me. Signed-off-by: Simon Kagstrom Acked-by: Nicolas Pitre Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ehci-orion.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/host/ehci-orion.c b/drivers/usb/host/ehci-orion.c index dc2ac613a9d1..1d283e1b2b8d 100644 --- a/drivers/usb/host/ehci-orion.c +++ b/drivers/usb/host/ehci-orion.c @@ -105,6 +105,7 @@ static int ehci_orion_setup(struct usb_hcd *hcd) struct ehci_hcd *ehci = hcd_to_ehci(hcd); int retval; + ehci_reset(ehci); retval = ehci_halt(ehci); if (retval) return retval; @@ -118,7 +119,6 @@ static int ehci_orion_setup(struct usb_hcd *hcd) hcd->has_tt = 1; - ehci_reset(ehci); ehci_port_power(ehci, 0); return retval; -- cgit v1.2.3 From c420befde6b2747ebc2b8f015687a5dbd6e167ca Mon Sep 17 00:00:00 2001 From: Herton Ronaldo Krzesinski Date: Wed, 15 Jul 2009 17:10:26 -0300 Subject: USB: option: add ZTE device ids and remove ONDA ids Current listed Onda ids are ZTE devices. Replace them with ZTE id define and add more ZTE device ids. Also remove 19d2:2000, this is the id when device is first plugged in and is a CD-only device, before the switch using eject. These changes are based on a previous patch by Ming Zhao Signed-off-by: Herton Ronaldo Krzesinski Cc: Ming Zhao Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/option.c | 113 ++++++++++++++++++++++++++------------------ 1 file changed, 68 insertions(+), 45 deletions(-) diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index 7638d2632ff8..5640f38fdb3a 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -261,11 +261,6 @@ static int option_resume(struct usb_serial *serial); #define AXESSTEL_VENDOR_ID 0x1726 #define AXESSTEL_PRODUCT_MV110H 0x1000 -#define ONDA_VENDOR_ID 0x19d2 -#define ONDA_PRODUCT_MSA501HS 0x0001 -#define ONDA_PRODUCT_ET502HS 0x0002 -#define ONDA_PRODUCT_MT503HS 0x2000 - #define BANDRICH_VENDOR_ID 0x1A8D #define BANDRICH_PRODUCT_C100_1 0x1002 #define BANDRICH_PRODUCT_C100_2 0x1003 @@ -476,42 +471,6 @@ static struct usb_device_id option_ids[] = { { USB_DEVICE(ANYDATA_VENDOR_ID, ANYDATA_PRODUCT_ADU_500A) }, { USB_DEVICE(ANYDATA_VENDOR_ID, ANYDATA_PRODUCT_ADU_620UW) }, { USB_DEVICE(AXESSTEL_VENDOR_ID, AXESSTEL_PRODUCT_MV110H) }, - { USB_DEVICE(ONDA_VENDOR_ID, ONDA_PRODUCT_MSA501HS) }, - { USB_DEVICE(ONDA_VENDOR_ID, ONDA_PRODUCT_ET502HS) }, - { USB_DEVICE(ONDA_VENDOR_ID, 0x0003) }, - { USB_DEVICE(ONDA_VENDOR_ID, 0x0004) }, - { USB_DEVICE(ONDA_VENDOR_ID, 0x0005) }, - { USB_DEVICE(ONDA_VENDOR_ID, 0x0006) }, - { USB_DEVICE(ONDA_VENDOR_ID, 0x0007) }, - { USB_DEVICE(ONDA_VENDOR_ID, 0x0008) }, - { USB_DEVICE(ONDA_VENDOR_ID, 0x0009) }, - { USB_DEVICE(ONDA_VENDOR_ID, 0x000a) }, - { USB_DEVICE(ONDA_VENDOR_ID, 0x000b) }, - { USB_DEVICE(ONDA_VENDOR_ID, 0x000c) }, - { USB_DEVICE(ONDA_VENDOR_ID, 0x000d) }, - { USB_DEVICE(ONDA_VENDOR_ID, 0x000e) }, - { USB_DEVICE(ONDA_VENDOR_ID, 0x000f) }, - { USB_DEVICE(ONDA_VENDOR_ID, 0x0010) }, - { USB_DEVICE(ONDA_VENDOR_ID, 0x0011) }, - { USB_DEVICE(ONDA_VENDOR_ID, 0x0012) }, - { USB_DEVICE(ONDA_VENDOR_ID, 0x0013) }, - { USB_DEVICE(ONDA_VENDOR_ID, 0x0014) }, - { USB_DEVICE(ONDA_VENDOR_ID, 0x0015) }, - { USB_DEVICE(ONDA_VENDOR_ID, 0x0016) }, - { USB_DEVICE(ONDA_VENDOR_ID, 0x0017) }, - { USB_DEVICE(ONDA_VENDOR_ID, 0x0018) }, - { USB_DEVICE(ONDA_VENDOR_ID, 0x0019) }, - { USB_DEVICE(ONDA_VENDOR_ID, 0x0020) }, - { USB_DEVICE(ONDA_VENDOR_ID, 0x0021) }, - { USB_DEVICE(ONDA_VENDOR_ID, 0x0022) }, - { USB_DEVICE(ONDA_VENDOR_ID, 0x0023) }, - { USB_DEVICE(ONDA_VENDOR_ID, 0x0024) }, - { USB_DEVICE(ONDA_VENDOR_ID, 0x0025) }, - { USB_DEVICE(ONDA_VENDOR_ID, 0x0026) }, - { USB_DEVICE(ONDA_VENDOR_ID, 0x0027) }, - { USB_DEVICE(ONDA_VENDOR_ID, 0x0028) }, - { USB_DEVICE(ONDA_VENDOR_ID, 0x0029) }, - { USB_DEVICE(ONDA_VENDOR_ID, ONDA_PRODUCT_MT503HS) }, { USB_DEVICE(YISO_VENDOR_ID, YISO_PRODUCT_U893) }, { USB_DEVICE(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_C100_1) }, { USB_DEVICE(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_C100_2) }, @@ -536,10 +495,74 @@ static struct usb_device_id option_ids[] = { { USB_DEVICE(QUALCOMM_VENDOR_ID, 0x6613)}, /* Onda H600/ZTE MF330 */ { USB_DEVICE(MAXON_VENDOR_ID, 0x6280) }, /* BP3-USB & BP3-EXT HSDPA */ { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_UC864E) }, - { USB_DEVICE(ZTE_VENDOR_ID, ZTE_PRODUCT_MF622) }, - { USB_DEVICE(ZTE_VENDOR_ID, ZTE_PRODUCT_MF626) }, - { USB_DEVICE(ZTE_VENDOR_ID, ZTE_PRODUCT_MF628) }, - { USB_DEVICE(ZTE_VENDOR_ID, ZTE_PRODUCT_CDMA_TECH) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_MF622, 0xff, 0xff, 0xff) }, /* ZTE WCDMA products */ + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0002, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0003, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0004, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0005, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0006, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0007, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0008, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0009, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x000a, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x000b, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x000c, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x000d, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x000e, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x000f, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0010, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0011, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0012, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0013, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_MF628, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0016, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0017, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0018, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0019, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0020, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0021, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0022, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0023, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0024, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0025, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0026, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0028, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0029, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0030, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_MF626, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0032, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0033, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0037, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0039, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0042, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0043, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0048, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0049, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0051, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0052, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0054, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0055, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0057, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0058, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0061, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0062, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0063, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0064, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0066, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0069, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0076, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0078, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0082, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0086, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x2002, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x2003, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0014, 0xff, 0xff, 0xff) }, /* ZTE CDMA products */ + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0027, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0059, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0060, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0070, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0073, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_CDMA_TECH, 0xff, 0xff, 0xff) }, { USB_DEVICE(BENQ_VENDOR_ID, BENQ_PRODUCT_H10) }, { USB_DEVICE(DLINK_VENDOR_ID, DLINK_PRODUCT_DWM_652) }, { USB_DEVICE(QISDA_VENDOR_ID, QISDA_PRODUCT_H21_4512) }, -- cgit v1.2.3 From f1469fc3ef1d5a8a67146c1c72021f012a59dea6 Mon Sep 17 00:00:00 2001 From: Tim Gardner Date: Fri, 17 Jul 2009 07:55:36 -0600 Subject: USB: option: Add USB ID for Novatel MC727/U727/USB727 refresh BugLink: https://bugs.launchpad.net/bugs/365291 Signed-off-by: Tim Gardner Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/option.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index 5640f38fdb3a..ff61f89918e4 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -207,6 +207,7 @@ static int option_resume(struct usb_serial *serial); #define NOVATELWIRELESS_PRODUCT_MC727 0x4100 #define NOVATELWIRELESS_PRODUCT_MC950D 0x4400 #define NOVATELWIRELESS_PRODUCT_U727 0x5010 +#define NOVATELWIRELESS_PRODUCT_MC727_NEW 0x5100 #define NOVATELWIRELESS_PRODUCT_MC760 0x6000 #define NOVATELWIRELESS_PRODUCT_OVMC760 0x6002 @@ -435,6 +436,7 @@ static struct usb_device_id option_ids[] = { { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_EU870D) }, /* Novatel EU850D/EU860D/EU870D */ { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_MC950D) }, /* Novatel MC930D/MC950D */ { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_MC727) }, /* Novatel MC727/U727/USB727 */ + { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_MC727_NEW) }, /* Novatel MC727/U727/USB727 refresh */ { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_U727) }, /* Novatel MC727/U727/USB727 */ { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_MC760) }, /* Novatel MC760/U760/USB760 */ { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_OVMC760) }, /* Novatel Ovation MC760 */ -- cgit v1.2.3 From 9d498beafc0a66ce333f0d9067af0aa5dedd4c8e Mon Sep 17 00:00:00 2001 From: Russell Lang Date: Fri, 17 Jul 2009 19:29:20 +1000 Subject: USB: aten uc2324 is really a moschip 7840 I've opened up the case, and the chips in the ATEN UC2324 are: Moschip MCS7840CV-AA 69507-6B1 0650 (USB to 4-port serial) (logo with AF kerned together) 0748 24BC02 SINGLP (unknown 8-pin chip) (logo looks like 3 or Z in circle) ZT3243LEEA 0752 B7A16420.T (4 chips, so this will be RS232 line driver) (Probably equivalent of Sipex SP3243) So the ATEN 2324 (aten2011.c driver), is definitely the Moschip 7840, and should use the mos7840.c driver. I expect you will remove the aten2011.c driver from the staging area. From the aten2011.c source code, the device ID for the UC2322 (2 port serial) is 0x7820, just like the Moschip evaluation board. This value should be added to the device id table of mos7840.c. Here's a patch that adds these devices to the driver. From: Russell Lang Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/mos7840.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/drivers/usb/serial/mos7840.c b/drivers/usb/serial/mos7840.c index c31940a307f8..270009afdf77 100644 --- a/drivers/usb/serial/mos7840.c +++ b/drivers/usb/serial/mos7840.c @@ -124,10 +124,13 @@ #define BANDB_DEVICE_ID_USOPTL4_4 0xAC44 #define BANDB_DEVICE_ID_USOPTL4_2 0xAC42 -/* This driver also supports the ATEN UC2324 device since it is mos7840 based - * - if I knew the device id it would also support the ATEN UC2322 */ +/* This driver also supports + * ATEN UC2324 device using Moschip MCS7840 + * ATEN UC2322 device using Moschip MCS7820 + */ #define USB_VENDOR_ID_ATENINTL 0x0557 #define ATENINTL_DEVICE_ID_UC2324 0x2011 +#define ATENINTL_DEVICE_ID_UC2322 0x7820 /* Interrupt Routine Defines */ @@ -177,6 +180,7 @@ static struct usb_device_id moschip_port_id_table[] = { {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USOPTL4_4)}, {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USOPTL4_2)}, {USB_DEVICE(USB_VENDOR_ID_ATENINTL, ATENINTL_DEVICE_ID_UC2324)}, + {USB_DEVICE(USB_VENDOR_ID_ATENINTL, ATENINTL_DEVICE_ID_UC2322)}, {} /* terminating entry */ }; @@ -186,6 +190,7 @@ static __devinitdata struct usb_device_id moschip_id_table_combined[] = { {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USOPTL4_4)}, {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USOPTL4_2)}, {USB_DEVICE(USB_VENDOR_ID_ATENINTL, ATENINTL_DEVICE_ID_UC2324)}, + {USB_DEVICE(USB_VENDOR_ID_ATENINTL, ATENINTL_DEVICE_ID_UC2322)}, {} /* terminating entry */ }; -- cgit v1.2.3 From 183791588efd416fc35a71819683b32dee92615b Mon Sep 17 00:00:00 2001 From: Peng Huang Date: Wed, 22 Jul 2009 11:54:48 +0200 Subject: USB: serial: option: Add ZTE AC8710 usb modem device. Signed-off-by: Peng Huang Cc: Jiri Kosina Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/option.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index ff61f89918e4..b6de085bc784 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -299,6 +299,7 @@ static int option_resume(struct usb_serial *serial); #define ZTE_PRODUCT_MF628 0x0015 #define ZTE_PRODUCT_MF626 0x0031 #define ZTE_PRODUCT_CDMA_TECH 0xfffe +#define ZTE_PRODUCT_AC8710 0xfff1 #define BENQ_VENDOR_ID 0x04a5 #define BENQ_PRODUCT_H10 0x4068 @@ -565,6 +566,7 @@ static struct usb_device_id option_ids[] = { { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0070, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0073, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_CDMA_TECH, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_AC8710, 0xff, 0xff, 0xff) }, { USB_DEVICE(BENQ_VENDOR_ID, BENQ_PRODUCT_H10) }, { USB_DEVICE(DLINK_VENDOR_ID, DLINK_PRODUCT_DWM_652) }, { USB_DEVICE(QISDA_VENDOR_ID, QISDA_PRODUCT_H21_4512) }, -- cgit v1.2.3 From 48c348cc939aaa3a07d4938669f2f315152e895e Mon Sep 17 00:00:00 2001 From: Javier Martin Date: Thu, 23 Jul 2009 04:03:43 +0200 Subject: USB: option.c to support Alcatel X060S/X200 broadband modems Added support for the Alcatel X060S/X200 broadband modems to the option driver. The device starts in cd-rom emulation mode (1bbb:f000) and requires the use of the usb_modeswitch tool to switch it to modem mode (1bbb:0000). Signed-off-by: Javier Martin Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/option.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index b6de085bc784..c784ddbe7b61 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -321,6 +321,11 @@ static int option_resume(struct usb_serial *serial); #define ALINK_VENDOR_ID 0x1e0e #define ALINK_PRODUCT_3GU 0x9200 +/* ALCATEL PRODUCTS */ +#define ALCATEL_VENDOR_ID 0x1bbb +#define ALCATEL_PRODUCT_X060S 0x0000 + + static struct usb_device_id option_ids[] = { { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_COLT) }, { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_RICOLA) }, @@ -576,6 +581,7 @@ static struct usb_device_id option_ids[] = { { USB_DEVICE(TOSHIBA_VENDOR_ID, TOSHIBA_PRODUCT_HSDPA_MINICARD ) }, /* Toshiba 3G HSDPA == Novatel Expedite EU870D MiniCard */ { USB_DEVICE(ALINK_VENDOR_ID, 0x9000) }, { USB_DEVICE_AND_INTERFACE_INFO(ALINK_VENDOR_ID, ALINK_PRODUCT_3GU, 0xff, 0xff, 0xff) }, + { USB_DEVICE(ALCATEL_VENDOR_ID, ALCATEL_PRODUCT_X060S) }, { } /* Terminating entry */ }; MODULE_DEVICE_TABLE(usb, option_ids); -- cgit v1.2.3 From f01b017d198486ee3553bee6841f788263cf2c23 Mon Sep 17 00:00:00 2001 From: Sergei Shtylyov Date: Fri, 17 Jul 2009 17:30:03 +0300 Subject: USB: musb_gadget_ep0: fix typo in service_zero_data_request() This function uses wrong bit mask to prevent clearing RXCSR status bits when halting an endpoint -- which results in clearing SentStall and RxPktRdy bits (that the code actually tries to avoid); must be a result of cut-and-paste... Signed-off-by: Sergei Shtylyov Acked-by: David Brownell Signed-off-by: Greg Kroah-Hartman --- drivers/usb/musb/musb_gadget_ep0.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/musb/musb_gadget_ep0.c b/drivers/usb/musb/musb_gadget_ep0.c index 40ed50ecedff..7a6778675ad3 100644 --- a/drivers/usb/musb/musb_gadget_ep0.c +++ b/drivers/usb/musb/musb_gadget_ep0.c @@ -407,7 +407,7 @@ stall: csr |= MUSB_RXCSR_P_SENDSTALL | MUSB_RXCSR_FLUSHFIFO | MUSB_RXCSR_CLRDATATOG - | MUSB_TXCSR_P_WZC_BITS; + | MUSB_RXCSR_P_WZC_BITS; musb_writew(regs, MUSB_RXCSR, csr); } -- cgit v1.2.3 From 3a9f5bd82dc986d496d8484ff54b107b4515f43f Mon Sep 17 00:00:00 2001 From: Amit Kucheria Date: Mon, 27 Jul 2009 12:03:19 +0300 Subject: USB: musb: Refer to musb_otg_timer_func under correct #ifdef musb_otg_timer_func() is defined under #ifdef CONFIG_USB_MUSB_OTG. Make sure any reference to it is also under the same #ifdef. Without this fix, the driver failes to compile when USB_OTG is defined but USB_MUSB_OTG isn't. Signed-off-by: Amit Kucheria Cc: Felipe Balbi Cc: David Brownell Signed-off-by: Greg Kroah-Hartman --- drivers/usb/musb/musb_core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c index 554a414f65d1..642a4e25f7d9 100644 --- a/drivers/usb/musb/musb_core.c +++ b/drivers/usb/musb/musb_core.c @@ -1990,7 +1990,7 @@ bad_config: if (status < 0) goto fail2; -#ifdef CONFIG_USB_OTG +#ifdef CONFIG_USB_MUSB_OTG setup_timer(&musb->otg_timer, musb_otg_timer_func, (unsigned long) musb); #endif -- cgit v1.2.3 From 2bbff7b742d55b094ed1467702efe146cd60c64f Mon Sep 17 00:00:00 2001 From: Ajay Kumar Gupta Date: Mon, 27 Jul 2009 14:32:15 -0700 Subject: USB: musb: fix CONFIGDATA register read issue INDEX register has to be set to '0' before reading CONFIGDATA register which is only present in TI musb platforms. Currently the default register access mode is set to FLAT_MODE thus INDEX register is not getting set properly with musb_ep_select() which is just a nop operation in FLAT_MODE.This invalid register read is causing module reinset failure. Fixing the issue by moving INDEX register write part to musb_read_configdata() function itself. Signed-off-by: Vikram Pandita Signed-off-by: Anand Gadiyar Signed-off-by: Ajay Kumar Gupta Acked-by: David Brownell Signed-off-by: Greg Kroah-Hartman --- drivers/usb/musb/musb_core.c | 1 - drivers/usb/musb/musb_regs.h | 1 + 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c index 642a4e25f7d9..c7c1ca0494cd 100644 --- a/drivers/usb/musb/musb_core.c +++ b/drivers/usb/musb/musb_core.c @@ -1326,7 +1326,6 @@ static int __init musb_core_init(u16 musb_type, struct musb *musb) int i; /* log core options (read using indexed model) */ - musb_ep_select(mbase, 0); reg = musb_read_configdata(mbase); strcpy(aInfo, (reg & MUSB_CONFIGDATA_UTMIDW) ? "UTMI-16" : "UTMI-8"); diff --git a/drivers/usb/musb/musb_regs.h b/drivers/usb/musb/musb_regs.h index de3b2f18db44..fbfd3fd9ce1f 100644 --- a/drivers/usb/musb/musb_regs.h +++ b/drivers/usb/musb/musb_regs.h @@ -323,6 +323,7 @@ static inline void musb_write_rxfifoadd(void __iomem *mbase, u16 c_off) static inline u8 musb_read_configdata(void __iomem *mbase) { + musb_writeb(mbase, MUSB_INDEX, 0); return musb_readb(mbase, 0x10 + MUSB_CONFIGDATA); } -- cgit v1.2.3 From 0f157ef3a1284f41d9804ecb87fdcc8ea946b9fa Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Tue, 28 Jul 2009 11:56:17 -0400 Subject: USB: usbtest: no need for USB_DEVICEFS THis patch (as1270) allows the usbtest module to be built even when USB_DEVICEFS isn't configured. Tests can be performed without USB_DEVICEFS, using the /dev/bus/usb/*/* device files. Signed-off-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/misc/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/misc/Kconfig b/drivers/usb/misc/Kconfig index a68d91a11bee..abe3aa67ed00 100644 --- a/drivers/usb/misc/Kconfig +++ b/drivers/usb/misc/Kconfig @@ -220,7 +220,7 @@ config USB_IOWARRIOR config USB_TEST tristate "USB testing driver" - depends on USB && USB_DEVICEFS + depends on USB help This driver is for testing host controller software. It is used with specialized device firmware for regression and stress testing, -- cgit v1.2.3 From d8f1a5ed52a81a953918d4aebe185ba008a7be34 Mon Sep 17 00:00:00 2001 From: Roel Kluin Date: Mon, 13 Jul 2009 00:23:47 +0200 Subject: USB: xhci: fix less- and greater than confusion Without this change the loops won't start Signed-off-by: Roel Kluin Cc: Sarah Sharp Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/xhci-dbg.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/usb/host/xhci-dbg.c b/drivers/usb/host/xhci-dbg.c index 2501c571f855..56032f2d84e8 100644 --- a/drivers/usb/host/xhci-dbg.c +++ b/drivers/usb/host/xhci-dbg.c @@ -419,7 +419,7 @@ void xhci_dbg_ctx(struct xhci_hcd *xhci, struct xhci_device_control *ctx, dma_ad &ctx->add_flags, (unsigned long long)dma, ctx->add_flags); dma += field_size; - for (i = 0; i > 6; ++i) { + for (i = 0; i < 6; ++i) { xhci_dbg(xhci, "@%p (virt) @%08llx (dma) %#08x - rsvd[%d]\n", &ctx->rsvd[i], (unsigned long long)dma, ctx->rsvd[i], i); @@ -443,7 +443,7 @@ void xhci_dbg_ctx(struct xhci_hcd *xhci, struct xhci_device_control *ctx, dma_ad &ctx->slot.dev_state, (unsigned long long)dma, ctx->slot.dev_state); dma += field_size; - for (i = 0; i > 4; ++i) { + for (i = 0; i < 4; ++i) { xhci_dbg(xhci, "@%p (virt) @%08llx (dma) %#08x - rsvd[%d]\n", &ctx->slot.reserved[i], (unsigned long long)dma, ctx->slot.reserved[i], i); -- cgit v1.2.3 From f9dc68fe7ad390428c6bc5d7ff582cdb5d92fcb8 Mon Sep 17 00:00:00 2001 From: Sarah Sharp Date: Mon, 27 Jul 2009 12:03:07 -0700 Subject: USB: xhci: Set TD size in transfer TRB. The 0.95 xHCI specification requires software to set the "TD size" field in each transaction request block (TRB). This field gives the host controller an indication of how much data is remaining in the TD (including the buffer in the current TRB). Set this field in bulk TRBs and data stage TRBs for control transfers. Signed-off-by: Sarah Sharp Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/xhci-ring.c | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c index 02d81985c454..d5b952997423 100644 --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c @@ -1285,6 +1285,7 @@ static int queue_bulk_sg_tx(struct xhci_hcd *xhci, gfp_t mem_flags, /* Queue the first TRB, even if it's zero-length */ do { u32 field = 0; + u32 length_field = 0; /* Don't change the cycle bit of the first TRB until later */ if (first_trb) @@ -1314,10 +1315,13 @@ static int queue_bulk_sg_tx(struct xhci_hcd *xhci, gfp_t mem_flags, (unsigned int) (addr + TRB_MAX_BUFF_SIZE) & ~(TRB_MAX_BUFF_SIZE - 1), (unsigned int) addr + trb_buff_len); } + length_field = TRB_LEN(trb_buff_len) | + TD_REMAINDER(urb->transfer_buffer_length - running_total) | + TRB_INTR_TARGET(0); queue_trb(xhci, ep_ring, false, (u32) addr, (u32) ((u64) addr >> 32), - TRB_LEN(trb_buff_len) | TRB_INTR_TARGET(0), + length_field, /* We always want to know if the TRB was short, * or we won't get an event when it completes. * (Unless we use event data TRBs, which are a @@ -1365,7 +1369,7 @@ int xhci_queue_bulk_tx(struct xhci_hcd *xhci, gfp_t mem_flags, struct xhci_generic_trb *start_trb; bool first_trb; int start_cycle; - u32 field; + u32 field, length_field; int running_total, trb_buff_len, ret; u64 addr; @@ -1443,10 +1447,13 @@ int xhci_queue_bulk_tx(struct xhci_hcd *xhci, gfp_t mem_flags, td->last_trb = ep_ring->enqueue; field |= TRB_IOC; } + length_field = TRB_LEN(trb_buff_len) | + TD_REMAINDER(urb->transfer_buffer_length - running_total) | + TRB_INTR_TARGET(0); queue_trb(xhci, ep_ring, false, (u32) addr, (u32) ((u64) addr >> 32), - TRB_LEN(trb_buff_len) | TRB_INTR_TARGET(0), + length_field, /* We always want to know if the TRB was short, * or we won't get an event when it completes. * (Unless we use event data TRBs, which are a @@ -1478,7 +1485,7 @@ int xhci_queue_ctrl_tx(struct xhci_hcd *xhci, gfp_t mem_flags, struct usb_ctrlrequest *setup; struct xhci_generic_trb *start_trb; int start_cycle; - u32 field; + u32 field, length_field; struct xhci_td *td; ep_ring = xhci->devs[slot_id]->ep_rings[ep_index]; @@ -1528,13 +1535,16 @@ int xhci_queue_ctrl_tx(struct xhci_hcd *xhci, gfp_t mem_flags, /* If there's data, queue data TRBs */ field = 0; + length_field = TRB_LEN(urb->transfer_buffer_length) | + TD_REMAINDER(urb->transfer_buffer_length) | + TRB_INTR_TARGET(0); if (urb->transfer_buffer_length > 0) { if (setup->bRequestType & USB_DIR_IN) field |= TRB_DIR_IN; queue_trb(xhci, ep_ring, false, lower_32_bits(urb->transfer_dma), upper_32_bits(urb->transfer_dma), - TRB_LEN(urb->transfer_buffer_length) | TRB_INTR_TARGET(0), + length_field, /* Event on short tx */ field | TRB_ISP | TRB_TYPE(TRB_DATA) | ep_ring->cycle_state); } -- cgit v1.2.3 From a1587d97ce3e53816c88b513a2038f6c5e5babd7 Mon Sep 17 00:00:00 2001 From: Sarah Sharp Date: Mon, 27 Jul 2009 12:03:15 -0700 Subject: USB: xhci: Deal with stalled endpoints. When an endpoint on a device under an xHCI host controller stalls, the host controller driver must let the hardware know that the USB core has successfully cleared the halt condition. The HCD submits a Reset Endpoint Command, which will clear the toggle bit for USB 2.0 devices, and set the sequence number to zero for USB 3.0 devices. The xHCI urb_enqueue will accept new URBs while the endpoint is halted, and will queue them to the hardware rings. However, the endpoint doorbell will not be rung until the Reset Endpoint Command completes. Don't queue a reset endpoint command for root hubs. khubd clears halt conditions on the roothub during the initialization process, but the roothub isn't a real device, so the xHCI host controller doesn't need to know about the cleared halt. Signed-off-by: Sarah Sharp Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/xhci-hcd.c | 44 +++++++++++++++++++++++++++++++++++++++++++- drivers/usb/host/xhci-pci.c | 1 + drivers/usb/host/xhci-ring.c | 36 +++++++++++++++++++++++++++++++++++- drivers/usb/host/xhci.h | 8 ++++++-- 4 files changed, 85 insertions(+), 4 deletions(-) diff --git a/drivers/usb/host/xhci-hcd.c b/drivers/usb/host/xhci-hcd.c index dba3e07ccd09..1c5901ad6eb8 100644 --- a/drivers/usb/host/xhci-hcd.c +++ b/drivers/usb/host/xhci-hcd.c @@ -787,8 +787,11 @@ int xhci_add_endpoint(struct usb_hcd *hcd, struct usb_device *udev, int ret = 0; ret = xhci_check_args(hcd, udev, ep, 1, __func__); - if (ret <= 0) + if (ret <= 0) { + /* So we won't queue a reset ep command for a root hub */ + ep->hcpriv = NULL; return ret; + } xhci = hcd_to_xhci(hcd); added_ctxs = xhci_get_endpoint_flag(&ep->desc); @@ -851,6 +854,9 @@ int xhci_add_endpoint(struct usb_hcd *hcd, struct usb_device *udev, } new_slot_info = in_ctx->slot.dev_info; + /* Store the usb_device pointer for later use */ + ep->hcpriv = udev; + xhci_dbg(xhci, "add ep 0x%x, slot id %d, new drop flags = %#x, new add flags = %#x, new slot info = %#x\n", (unsigned int) ep->desc.bEndpointAddress, udev->slot_id, @@ -1026,6 +1032,42 @@ void xhci_reset_bandwidth(struct usb_hcd *hcd, struct usb_device *udev) xhci_zero_in_ctx(virt_dev); } +/* Deal with stalled endpoints. The core should have sent the control message + * to clear the halt condition. However, we need to make the xHCI hardware + * reset its sequence number, since a device will expect a sequence number of + * zero after the halt condition is cleared. + * Context: in_interrupt + */ +void xhci_endpoint_reset(struct usb_hcd *hcd, + struct usb_host_endpoint *ep) +{ + struct xhci_hcd *xhci; + struct usb_device *udev; + unsigned int ep_index; + unsigned long flags; + int ret; + + xhci = hcd_to_xhci(hcd); + udev = (struct usb_device *) ep->hcpriv; + /* Called with a root hub endpoint (or an endpoint that wasn't added + * with xhci_add_endpoint() + */ + if (!ep->hcpriv) + return; + ep_index = xhci_get_endpoint_index(&ep->desc); + + xhci_dbg(xhci, "Queueing reset endpoint command\n"); + spin_lock_irqsave(&xhci->lock, flags); + ret = xhci_queue_reset_ep(xhci, udev->slot_id, ep_index); + if (!ret) { + xhci_ring_cmd_db(xhci); + } + spin_unlock_irqrestore(&xhci->lock, flags); + + if (ret) + xhci_warn(xhci, "FIXME allocate a new ring segment\n"); +} + /* * At this point, the struct usb_device is about to go away, the device has * disconnected, and all traffic has been stopped and the endpoints have been diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c index 1462709e26c0..592fe7e623f7 100644 --- a/drivers/usb/host/xhci-pci.c +++ b/drivers/usb/host/xhci-pci.c @@ -117,6 +117,7 @@ static const struct hc_driver xhci_pci_hc_driver = { .free_dev = xhci_free_dev, .add_endpoint = xhci_add_endpoint, .drop_endpoint = xhci_drop_endpoint, + .endpoint_reset = xhci_endpoint_reset, .check_bandwidth = xhci_check_bandwidth, .reset_bandwidth = xhci_reset_bandwidth, .address_device = xhci_address_device, diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c index d5b952997423..d672ba14ff80 100644 --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c @@ -279,7 +279,8 @@ static void ring_ep_doorbell(struct xhci_hcd *xhci, /* Don't ring the doorbell for this endpoint if there are pending * cancellations because the we don't want to interrupt processing. */ - if (!ep_ring->cancels_pending && !(ep_ring->state & SET_DEQ_PENDING)) { + if (!ep_ring->cancels_pending && !(ep_ring->state & SET_DEQ_PENDING) + && !(ep_ring->state & EP_HALTED)) { field = xhci_readl(xhci, db_addr) & DB_MASK; xhci_writel(xhci, field | EPI_TO_DB(ep_index), db_addr); /* Flush PCI posted writes - FIXME Matthew Wilcox says this @@ -603,6 +604,25 @@ static void handle_set_deq_completion(struct xhci_hcd *xhci, ring_ep_doorbell(xhci, slot_id, ep_index); } +static void handle_reset_ep_completion(struct xhci_hcd *xhci, + struct xhci_event_cmd *event, + union xhci_trb *trb) +{ + int slot_id; + unsigned int ep_index; + + slot_id = TRB_TO_SLOT_ID(trb->generic.field[3]); + ep_index = TRB_TO_EP_INDEX(trb->generic.field[3]); + /* This command will only fail if the endpoint wasn't halted, + * but we don't care. + */ + xhci_dbg(xhci, "Ignoring reset ep completion code of %u\n", + (unsigned int) GET_COMP_CODE(event->status)); + + /* Clear our internal halted state and restart the ring */ + xhci->devs[slot_id]->ep_rings[ep_index]->state &= ~EP_HALTED; + ring_ep_doorbell(xhci, slot_id, ep_index); +} static void handle_cmd_completion(struct xhci_hcd *xhci, struct xhci_event_cmd *event) @@ -653,6 +673,9 @@ static void handle_cmd_completion(struct xhci_hcd *xhci, case TRB_TYPE(TRB_CMD_NOOP): ++xhci->noops_handled; break; + case TRB_TYPE(TRB_RESET_EP): + handle_reset_ep_completion(xhci, event, xhci->cmd_ring->dequeue); + break; default: /* Skip over unknown commands on the event ring */ xhci->error_bitmask |= 1 << 6; @@ -823,6 +846,7 @@ static int handle_tx_event(struct xhci_hcd *xhci, break; case COMP_STALL: xhci_warn(xhci, "WARN: Stalled endpoint\n"); + ep_ring->state |= EP_HALTED; status = -EPIPE; break; case COMP_TRB_ERR: @@ -1656,3 +1680,13 @@ static int queue_set_tr_deq(struct xhci_hcd *xhci, int slot_id, return queue_command(xhci, (u32) addr | cycle_state, 0, 0, trb_slot_id | trb_ep_index | type); } + +int xhci_queue_reset_ep(struct xhci_hcd *xhci, int slot_id, + unsigned int ep_index) +{ + u32 trb_slot_id = SLOT_ID_FOR_TRB(slot_id); + u32 trb_ep_index = EP_ID_FOR_TRB(ep_index); + u32 type = TRB_TYPE(TRB_RESET_EP); + + return queue_command(xhci, 0, 0, 0, trb_slot_id | trb_ep_index | type); +} diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h index 8936eeb5588b..cde648a524f5 100644 --- a/drivers/usb/host/xhci.h +++ b/drivers/usb/host/xhci.h @@ -848,8 +848,8 @@ union xhci_trb { #define TRB_CONFIG_EP 12 /* Evaluate Context Command */ #define TRB_EVAL_CONTEXT 13 -/* Reset Transfer Ring Command */ -#define TRB_RESET_RING 14 +/* Reset Endpoint Command */ +#define TRB_RESET_EP 14 /* Stop Transfer Ring Command */ #define TRB_STOP_RING 15 /* Set Transfer Ring Dequeue Pointer Command */ @@ -929,6 +929,7 @@ struct xhci_ring { unsigned int cancels_pending; unsigned int state; #define SET_DEQ_PENDING (1 << 0) +#define EP_HALTED (1 << 1) /* The TRB that was last reported in a stopped endpoint ring */ union xhci_trb *stopped_trb; struct xhci_td *stopped_td; @@ -1128,6 +1129,7 @@ int xhci_urb_enqueue(struct usb_hcd *hcd, struct urb *urb, gfp_t mem_flags); int xhci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status); int xhci_add_endpoint(struct usb_hcd *hcd, struct usb_device *udev, struct usb_host_endpoint *ep); int xhci_drop_endpoint(struct usb_hcd *hcd, struct usb_device *udev, struct usb_host_endpoint *ep); +void xhci_endpoint_reset(struct usb_hcd *hcd, struct usb_host_endpoint *ep); int xhci_check_bandwidth(struct usb_hcd *hcd, struct usb_device *udev); void xhci_reset_bandwidth(struct usb_hcd *hcd, struct usb_device *udev); @@ -1148,6 +1150,8 @@ int xhci_queue_bulk_tx(struct xhci_hcd *xhci, gfp_t mem_flags, struct urb *urb, int slot_id, unsigned int ep_index); int xhci_queue_configure_endpoint(struct xhci_hcd *xhci, dma_addr_t in_ctx_ptr, u32 slot_id); +int xhci_queue_reset_ep(struct xhci_hcd *xhci, int slot_id, + unsigned int ep_index); /* xHCI roothub code */ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, u16 wIndex, -- cgit v1.2.3 From b11069f5f6ce6e359f853e908b0917303fcdec8f Mon Sep 17 00:00:00 2001 From: Sarah Sharp Date: Mon, 27 Jul 2009 12:03:23 -0700 Subject: USB: xhci: Use GFP_ATOMIC while holding spinlocks. The xHCI functions to queue an URB onto the hardware rings must be called with the xhci spinlock held. Those functions will allocate memory, and take a gfp_t memory flags argument. We must pass them the GFP_ATOMIC flag, since we don't want the memory allocation to attempt to sleep while waiting for more memory to become available. Signed-off-by: Sarah Sharp Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/xhci-hcd.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/usb/host/xhci-hcd.c b/drivers/usb/host/xhci-hcd.c index 1c5901ad6eb8..ff99365cae42 100644 --- a/drivers/usb/host/xhci-hcd.c +++ b/drivers/usb/host/xhci-hcd.c @@ -601,10 +601,13 @@ int xhci_urb_enqueue(struct usb_hcd *hcd, struct urb *urb, gfp_t mem_flags) goto exit; } if (usb_endpoint_xfer_control(&urb->ep->desc)) - ret = xhci_queue_ctrl_tx(xhci, mem_flags, urb, + /* We have a spinlock and interrupts disabled, so we must pass + * atomic context to this function, which may allocate memory. + */ + ret = xhci_queue_ctrl_tx(xhci, GFP_ATOMIC, urb, slot_id, ep_index); else if (usb_endpoint_xfer_bulk(&urb->ep->desc)) - ret = xhci_queue_bulk_tx(xhci, mem_flags, urb, + ret = xhci_queue_bulk_tx(xhci, GFP_ATOMIC, urb, slot_id, ep_index); else ret = -EINVAL; -- cgit v1.2.3 From 8e595a5d30a5ee4bb745d4da6439d73ed7d91054 Mon Sep 17 00:00:00 2001 From: Sarah Sharp Date: Mon, 27 Jul 2009 12:03:31 -0700 Subject: USB: xhci: Represent 64-bit addresses with one u64. There are several xHCI data structures that use two 32-bit fields to represent a 64-bit address. Since some architectures don't support 64-bit PCI writes, the fields need to be written in two 32-bit writes. The xHCI specification says that if a platform is incapable of generating 64-bit writes, software must write the low 32-bits first, then the high 32-bits. Hardware that supports 64-bit addressing will wait for the high 32-bit write before reading the revised value, and hardware that only supports 32-bit writes will ignore the high 32-bit write. Previous xHCI code represented 64-bit addresses with two u32 values. This lead to buggy code that would write the 32-bits in the wrong order, or forget to write the upper 32-bits. Change the two u32s to one u64 and create a function call to write all 64-bit addresses in the proper order. This new function could be modified in the future if all platforms support 64-bit writes. Signed-off-by: Sarah Sharp Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/xhci-dbg.c | 67 +++++++++++++++++--------------------------- drivers/usb/host/xhci-hcd.c | 43 +++++++++++++--------------- drivers/usb/host/xhci-mem.c | 61 ++++++++++++++++------------------------ drivers/usb/host/xhci-ring.c | 49 +++++++++++++++----------------- drivers/usb/host/xhci.h | 65 +++++++++++++++++++++++++++++------------- 5 files changed, 137 insertions(+), 148 deletions(-) diff --git a/drivers/usb/host/xhci-dbg.c b/drivers/usb/host/xhci-dbg.c index 56032f2d84e8..6d62e4abe3c6 100644 --- a/drivers/usb/host/xhci-dbg.c +++ b/drivers/usb/host/xhci-dbg.c @@ -173,6 +173,7 @@ void xhci_print_ir_set(struct xhci_hcd *xhci, struct xhci_intr_reg *ir_set, int { void *addr; u32 temp; + u64 temp_64; addr = &ir_set->irq_pending; temp = xhci_readl(xhci, addr); @@ -200,25 +201,15 @@ void xhci_print_ir_set(struct xhci_hcd *xhci, struct xhci_intr_reg *ir_set, int xhci_dbg(xhci, " WARN: %p: ir_set.rsvd = 0x%x\n", addr, (unsigned int)temp); - addr = &ir_set->erst_base[0]; - temp = xhci_readl(xhci, addr); - xhci_dbg(xhci, " %p: ir_set.erst_base[0] = 0x%x\n", - addr, (unsigned int) temp); - - addr = &ir_set->erst_base[1]; - temp = xhci_readl(xhci, addr); - xhci_dbg(xhci, " %p: ir_set.erst_base[1] = 0x%x\n", - addr, (unsigned int) temp); - - addr = &ir_set->erst_dequeue[0]; - temp = xhci_readl(xhci, addr); - xhci_dbg(xhci, " %p: ir_set.erst_dequeue[0] = 0x%x\n", - addr, (unsigned int) temp); + addr = &ir_set->erst_base; + temp_64 = xhci_read_64(xhci, addr); + xhci_dbg(xhci, " %p: ir_set.erst_base = @%08llx\n", + addr, temp_64); - addr = &ir_set->erst_dequeue[1]; - temp = xhci_readl(xhci, addr); - xhci_dbg(xhci, " %p: ir_set.erst_dequeue[1] = 0x%x\n", - addr, (unsigned int) temp); + addr = &ir_set->erst_dequeue; + temp_64 = xhci_read_64(xhci, addr); + xhci_dbg(xhci, " %p: ir_set.erst_dequeue = @%08llx\n", + addr, temp_64); } void xhci_print_run_regs(struct xhci_hcd *xhci) @@ -268,8 +259,7 @@ void xhci_debug_trb(struct xhci_hcd *xhci, union xhci_trb *trb) xhci_dbg(xhci, "Link TRB:\n"); xhci_print_trb_offsets(xhci, trb); - address = trb->link.segment_ptr[0] + - (((u64) trb->link.segment_ptr[1]) << 32); + address = trb->link.segment_ptr; xhci_dbg(xhci, "Next ring segment DMA address = 0x%llx\n", address); xhci_dbg(xhci, "Interrupter target = 0x%x\n", @@ -282,8 +272,7 @@ void xhci_debug_trb(struct xhci_hcd *xhci, union xhci_trb *trb) (unsigned int) (trb->link.control & TRB_NO_SNOOP)); break; case TRB_TYPE(TRB_TRANSFER): - address = trb->trans_event.buffer[0] + - (((u64) trb->trans_event.buffer[1]) << 32); + address = trb->trans_event.buffer; /* * FIXME: look at flags to figure out if it's an address or if * the data is directly in the buffer field. @@ -291,8 +280,7 @@ void xhci_debug_trb(struct xhci_hcd *xhci, union xhci_trb *trb) xhci_dbg(xhci, "DMA address or buffer contents= %llu\n", address); break; case TRB_TYPE(TRB_COMPLETION): - address = trb->event_cmd.cmd_trb[0] + - (((u64) trb->event_cmd.cmd_trb[1]) << 32); + address = trb->event_cmd.cmd_trb; xhci_dbg(xhci, "Command TRB pointer = %llu\n", address); xhci_dbg(xhci, "Completion status = %u\n", (unsigned int) GET_COMP_CODE(trb->event_cmd.status)); @@ -328,8 +316,8 @@ void xhci_debug_segment(struct xhci_hcd *xhci, struct xhci_segment *seg) for (i = 0; i < TRBS_PER_SEGMENT; ++i) { trb = &seg->trbs[i]; xhci_dbg(xhci, "@%08x %08x %08x %08x %08x\n", addr, - (unsigned int) trb->link.segment_ptr[0], - (unsigned int) trb->link.segment_ptr[1], + lower_32_bits(trb->link.segment_ptr), + upper_32_bits(trb->link.segment_ptr), (unsigned int) trb->link.intr_target, (unsigned int) trb->link.control); addr += sizeof(*trb); @@ -386,8 +374,8 @@ void xhci_dbg_erst(struct xhci_hcd *xhci, struct xhci_erst *erst) entry = &erst->entries[i]; xhci_dbg(xhci, "@%08x %08x %08x %08x %08x\n", (unsigned int) addr, - (unsigned int) entry->seg_addr[0], - (unsigned int) entry->seg_addr[1], + lower_32_bits(entry->seg_addr), + upper_32_bits(entry->seg_addr), (unsigned int) entry->seg_size, (unsigned int) entry->rsvd); addr += sizeof(*entry); @@ -396,12 +384,13 @@ void xhci_dbg_erst(struct xhci_hcd *xhci, struct xhci_erst *erst) void xhci_dbg_cmd_ptrs(struct xhci_hcd *xhci) { - u32 val; + u64 val; - val = xhci_readl(xhci, &xhci->op_regs->cmd_ring[0]); - xhci_dbg(xhci, "// xHC command ring deq ptr low bits + flags = 0x%x\n", val); - val = xhci_readl(xhci, &xhci->op_regs->cmd_ring[1]); - xhci_dbg(xhci, "// xHC command ring deq ptr high bits = 0x%x\n", val); + val = xhci_read_64(xhci, &xhci->op_regs->cmd_ring); + xhci_dbg(xhci, "// xHC command ring deq ptr low bits + flags = @%08x\n", + lower_32_bits(val)); + xhci_dbg(xhci, "// xHC command ring deq ptr high bits = @%08x\n", + upper_32_bits(val)); } void xhci_dbg_ctx(struct xhci_hcd *xhci, struct xhci_device_control *ctx, dma_addr_t dma, unsigned int last_ep) @@ -462,14 +451,10 @@ void xhci_dbg_ctx(struct xhci_hcd *xhci, struct xhci_device_control *ctx, dma_ad &ctx->ep[i].ep_info2, (unsigned long long)dma, ctx->ep[i].ep_info2); dma += field_size; - xhci_dbg(xhci, "@%p (virt) @%08llx (dma) %#08x - deq[0]\n", - &ctx->ep[i].deq[0], - (unsigned long long)dma, ctx->ep[i].deq[0]); - dma += field_size; - xhci_dbg(xhci, "@%p (virt) @%08llx (dma) %#08x - deq[1]\n", - &ctx->ep[i].deq[1], - (unsigned long long)dma, ctx->ep[i].deq[1]); - dma += field_size; + xhci_dbg(xhci, "@%p (virt) @%08llx (dma) %#08llx - deq\n", + &ctx->ep[i].deq, + (unsigned long long)dma, ctx->ep[i].deq); + dma += 2*field_size; xhci_dbg(xhci, "@%p (virt) @%08llx (dma) %#08x - tx_info\n", &ctx->ep[i].tx_info, (unsigned long long)dma, ctx->ep[i].tx_info); diff --git a/drivers/usb/host/xhci-hcd.c b/drivers/usb/host/xhci-hcd.c index ff99365cae42..e15773598e4e 100644 --- a/drivers/usb/host/xhci-hcd.c +++ b/drivers/usb/host/xhci-hcd.c @@ -226,6 +226,7 @@ int xhci_init(struct usb_hcd *hcd) static void xhci_work(struct xhci_hcd *xhci) { u32 temp; + u64 temp_64; /* * Clear the op reg interrupt status first, @@ -249,8 +250,8 @@ static void xhci_work(struct xhci_hcd *xhci) xhci_handle_event(xhci); /* Clear the event handler busy flag; the event ring should be empty. */ - temp = xhci_readl(xhci, &xhci->ir_set->erst_dequeue[0]); - xhci_writel(xhci, temp & ~ERST_EHB, &xhci->ir_set->erst_dequeue[0]); + temp_64 = xhci_read_64(xhci, &xhci->ir_set->erst_dequeue); + xhci_write_64(xhci, temp_64 & ~ERST_EHB, &xhci->ir_set->erst_dequeue); /* Flush posted writes -- FIXME is this necessary? */ xhci_readl(xhci, &xhci->ir_set->irq_pending); } @@ -295,6 +296,7 @@ void xhci_event_ring_work(unsigned long arg) { unsigned long flags; int temp; + u64 temp_64; struct xhci_hcd *xhci = (struct xhci_hcd *) arg; int i, j; @@ -311,9 +313,9 @@ void xhci_event_ring_work(unsigned long arg) xhci_dbg(xhci, "Event ring:\n"); xhci_debug_segment(xhci, xhci->event_ring->deq_seg); xhci_dbg_ring_ptrs(xhci, xhci->event_ring); - temp = xhci_readl(xhci, &xhci->ir_set->erst_dequeue[0]); - temp &= ERST_PTR_MASK; - xhci_dbg(xhci, "ERST deq = 0x%x\n", temp); + temp_64 = xhci_read_64(xhci, &xhci->ir_set->erst_dequeue); + temp_64 &= ~ERST_PTR_MASK; + xhci_dbg(xhci, "ERST deq = 64'h%0lx\n", (long unsigned int) temp_64); xhci_dbg(xhci, "Command ring:\n"); xhci_debug_segment(xhci, xhci->cmd_ring->deq_seg); xhci_dbg_ring_ptrs(xhci, xhci->cmd_ring); @@ -356,6 +358,7 @@ void xhci_event_ring_work(unsigned long arg) int xhci_run(struct usb_hcd *hcd) { u32 temp; + u64 temp_64; struct xhci_hcd *xhci = hcd_to_xhci(hcd); void (*doorbell)(struct xhci_hcd *) = NULL; @@ -416,11 +419,9 @@ int xhci_run(struct usb_hcd *hcd) xhci_dbg(xhci, "Event ring:\n"); xhci_debug_ring(xhci, xhci->event_ring); xhci_dbg_ring_ptrs(xhci, xhci->event_ring); - temp = xhci_readl(xhci, &xhci->ir_set->erst_dequeue[0]); - temp &= ERST_PTR_MASK; - xhci_dbg(xhci, "ERST deq = 0x%x\n", temp); - temp = xhci_readl(xhci, &xhci->ir_set->erst_dequeue[1]); - xhci_dbg(xhci, "ERST deq upper = 0x%x\n", temp); + temp_64 = xhci_read_64(xhci, &xhci->ir_set->erst_dequeue); + temp_64 &= ~ERST_PTR_MASK; + xhci_dbg(xhci, "ERST deq = 64'h%0lx\n", (long unsigned int) temp_64); temp = xhci_readl(xhci, &xhci->op_regs->command); temp |= (CMD_RUN); @@ -888,8 +889,7 @@ static void xhci_zero_in_ctx(struct xhci_virt_device *virt_dev) ep_ctx = &virt_dev->in_ctx->ep[i]; ep_ctx->ep_info = 0; ep_ctx->ep_info2 = 0; - ep_ctx->deq[0] = 0; - ep_ctx->deq[1] = 0; + ep_ctx->deq = 0; ep_ctx->tx_info = 0; } } @@ -1165,7 +1165,7 @@ int xhci_address_device(struct usb_hcd *hcd, struct usb_device *udev) struct xhci_virt_device *virt_dev; int ret = 0; struct xhci_hcd *xhci = hcd_to_xhci(hcd); - u32 temp; + u64 temp_64; if (!udev->slot_id) { xhci_dbg(xhci, "Bad Slot ID %d\n", udev->slot_id); @@ -1227,18 +1227,13 @@ int xhci_address_device(struct usb_hcd *hcd, struct usb_device *udev) if (ret) { return ret; } - temp = xhci_readl(xhci, &xhci->op_regs->dcbaa_ptr[0]); - xhci_dbg(xhci, "Op regs DCBAA ptr[0] = %#08x\n", temp); - temp = xhci_readl(xhci, &xhci->op_regs->dcbaa_ptr[1]); - xhci_dbg(xhci, "Op regs DCBAA ptr[1] = %#08x\n", temp); - xhci_dbg(xhci, "Slot ID %d dcbaa entry[0] @%p = %#08x\n", - udev->slot_id, - &xhci->dcbaa->dev_context_ptrs[2*udev->slot_id], - xhci->dcbaa->dev_context_ptrs[2*udev->slot_id]); - xhci_dbg(xhci, "Slot ID %d dcbaa entry[1] @%p = %#08x\n", + temp_64 = xhci_read_64(xhci, &xhci->op_regs->dcbaa_ptr); + xhci_dbg(xhci, "Op regs DCBAA ptr = %#016llx\n", temp_64); + xhci_dbg(xhci, "Slot ID %d dcbaa entry @%p = %#016llx\n", udev->slot_id, - &xhci->dcbaa->dev_context_ptrs[2*udev->slot_id+1], - xhci->dcbaa->dev_context_ptrs[2*udev->slot_id+1]); + &xhci->dcbaa->dev_context_ptrs[udev->slot_id], + (unsigned long long) + xhci->dcbaa->dev_context_ptrs[udev->slot_id]); xhci_dbg(xhci, "Output Context DMA address = %#08llx\n", (unsigned long long)virt_dev->out_ctx_dma); xhci_dbg(xhci, "Slot ID %d Input Context:\n", udev->slot_id); diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c index c8a72de1c508..ec825f16dcee 100644 --- a/drivers/usb/host/xhci-mem.c +++ b/drivers/usb/host/xhci-mem.c @@ -88,7 +88,7 @@ static void xhci_link_segments(struct xhci_hcd *xhci, struct xhci_segment *prev, return; prev->next = next; if (link_trbs) { - prev->trbs[TRBS_PER_SEGMENT-1].link.segment_ptr[0] = next->dma; + prev->trbs[TRBS_PER_SEGMENT-1].link.segment_ptr = next->dma; /* Set the last TRB in the segment to have a TRB type ID of Link TRB */ val = prev->trbs[TRBS_PER_SEGMENT-1].link.control; @@ -200,8 +200,7 @@ void xhci_free_virt_device(struct xhci_hcd *xhci, int slot_id) return; dev = xhci->devs[slot_id]; - xhci->dcbaa->dev_context_ptrs[2*slot_id] = 0; - xhci->dcbaa->dev_context_ptrs[2*slot_id + 1] = 0; + xhci->dcbaa->dev_context_ptrs[slot_id] = 0; if (!dev) return; @@ -265,13 +264,12 @@ int xhci_alloc_virt_device(struct xhci_hcd *xhci, int slot_id, * Point to output device context in dcbaa; skip the output control * context, which is eight 32 bit fields (or 32 bytes long) */ - xhci->dcbaa->dev_context_ptrs[2*slot_id] = + xhci->dcbaa->dev_context_ptrs[slot_id] = (u32) dev->out_ctx_dma + (32); xhci_dbg(xhci, "Set slot id %d dcbaa entry %p to 0x%llx\n", slot_id, - &xhci->dcbaa->dev_context_ptrs[2*slot_id], + &xhci->dcbaa->dev_context_ptrs[slot_id], (unsigned long long)dev->out_ctx_dma); - xhci->dcbaa->dev_context_ptrs[2*slot_id + 1] = 0; return 1; fail: @@ -360,10 +358,9 @@ int xhci_setup_addressable_virt_dev(struct xhci_hcd *xhci, struct usb_device *ud ep0_ctx->ep_info2 |= MAX_BURST(0); ep0_ctx->ep_info2 |= ERROR_COUNT(3); - ep0_ctx->deq[0] = + ep0_ctx->deq = dev->ep_rings[0]->first_seg->dma; - ep0_ctx->deq[0] |= dev->ep_rings[0]->cycle_state; - ep0_ctx->deq[1] = 0; + ep0_ctx->deq |= dev->ep_rings[0]->cycle_state; /* Steps 7 and 8 were done in xhci_alloc_virt_device() */ @@ -477,8 +474,7 @@ int xhci_endpoint_init(struct xhci_hcd *xhci, if (!virt_dev->new_ep_rings[ep_index]) return -ENOMEM; ep_ring = virt_dev->new_ep_rings[ep_index]; - ep_ctx->deq[0] = ep_ring->first_seg->dma | ep_ring->cycle_state; - ep_ctx->deq[1] = 0; + ep_ctx->deq = ep_ring->first_seg->dma | ep_ring->cycle_state; ep_ctx->ep_info = xhci_get_endpoint_interval(udev, ep); @@ -535,8 +531,7 @@ void xhci_endpoint_zero(struct xhci_hcd *xhci, ep_ctx->ep_info = 0; ep_ctx->ep_info2 = 0; - ep_ctx->deq[0] = 0; - ep_ctx->deq[1] = 0; + ep_ctx->deq = 0; ep_ctx->tx_info = 0; /* Don't free the endpoint ring until the set interface or configuration * request succeeds. @@ -551,10 +546,8 @@ void xhci_mem_cleanup(struct xhci_hcd *xhci) /* Free the Event Ring Segment Table and the actual Event Ring */ xhci_writel(xhci, 0, &xhci->ir_set->erst_size); - xhci_writel(xhci, 0, &xhci->ir_set->erst_base[0]); - xhci_writel(xhci, 0, &xhci->ir_set->erst_base[1]); - xhci_writel(xhci, 0, &xhci->ir_set->erst_dequeue[0]); - xhci_writel(xhci, 0, &xhci->ir_set->erst_dequeue[1]); + xhci_write_64(xhci, 0, &xhci->ir_set->erst_base); + xhci_write_64(xhci, 0, &xhci->ir_set->erst_dequeue); size = sizeof(struct xhci_erst_entry)*(xhci->erst.num_entries); if (xhci->erst.entries) pci_free_consistent(pdev, size, @@ -566,8 +559,7 @@ void xhci_mem_cleanup(struct xhci_hcd *xhci) xhci->event_ring = NULL; xhci_dbg(xhci, "Freed event ring\n"); - xhci_writel(xhci, 0, &xhci->op_regs->cmd_ring[0]); - xhci_writel(xhci, 0, &xhci->op_regs->cmd_ring[1]); + xhci_write_64(xhci, 0, &xhci->op_regs->cmd_ring); if (xhci->cmd_ring) xhci_ring_free(xhci, xhci->cmd_ring); xhci->cmd_ring = NULL; @@ -586,8 +578,7 @@ void xhci_mem_cleanup(struct xhci_hcd *xhci) xhci->device_pool = NULL; xhci_dbg(xhci, "Freed device context pool\n"); - xhci_writel(xhci, 0, &xhci->op_regs->dcbaa_ptr[0]); - xhci_writel(xhci, 0, &xhci->op_regs->dcbaa_ptr[1]); + xhci_write_64(xhci, 0, &xhci->op_regs->dcbaa_ptr); if (xhci->dcbaa) pci_free_consistent(pdev, sizeof(*xhci->dcbaa), xhci->dcbaa, xhci->dcbaa->dma); @@ -602,6 +593,7 @@ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags) dma_addr_t dma; struct device *dev = xhci_to_hcd(xhci)->self.controller; unsigned int val, val2; + u64 val_64; struct xhci_segment *seg; u32 page_size; int i; @@ -647,8 +639,7 @@ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags) xhci->dcbaa->dma = dma; xhci_dbg(xhci, "// Device context base array address = 0x%llx (DMA), %p (virt)\n", (unsigned long long)xhci->dcbaa->dma, xhci->dcbaa); - xhci_writel(xhci, dma, &xhci->op_regs->dcbaa_ptr[0]); - xhci_writel(xhci, (u32) 0, &xhci->op_regs->dcbaa_ptr[1]); + xhci_write_64(xhci, dma, &xhci->op_regs->dcbaa_ptr); /* * Initialize the ring segment pool. The ring must be a contiguous @@ -675,14 +666,12 @@ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags) (unsigned long long)xhci->cmd_ring->first_seg->dma); /* Set the address in the Command Ring Control register */ - val = xhci_readl(xhci, &xhci->op_regs->cmd_ring[0]); - val = (val & ~CMD_RING_ADDR_MASK) | - (xhci->cmd_ring->first_seg->dma & CMD_RING_ADDR_MASK) | + val_64 = xhci_read_64(xhci, &xhci->op_regs->cmd_ring); + val_64 = (val_64 & (u64) CMD_RING_RSVD_BITS) | + (xhci->cmd_ring->first_seg->dma & (u64) ~CMD_RING_RSVD_BITS) | xhci->cmd_ring->cycle_state; - xhci_dbg(xhci, "// Setting command ring address low bits to 0x%x\n", val); - xhci_writel(xhci, val, &xhci->op_regs->cmd_ring[0]); - xhci_dbg(xhci, "// Setting command ring address high bits to 0x0\n"); - xhci_writel(xhci, (u32) 0, &xhci->op_regs->cmd_ring[1]); + xhci_dbg(xhci, "// Setting command ring address to 0x%x\n", val); + xhci_write_64(xhci, val_64, &xhci->op_regs->cmd_ring); xhci_dbg_cmd_ptrs(xhci); val = xhci_readl(xhci, &xhci->cap_regs->db_off); @@ -722,8 +711,7 @@ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags) /* set ring base address and size for each segment table entry */ for (val = 0, seg = xhci->event_ring->first_seg; val < ERST_NUM_SEGS; val++) { struct xhci_erst_entry *entry = &xhci->erst.entries[val]; - entry->seg_addr[0] = seg->dma; - entry->seg_addr[1] = 0; + entry->seg_addr = seg->dma; entry->seg_size = TRBS_PER_SEGMENT; entry->rsvd = 0; seg = seg->next; @@ -741,11 +729,10 @@ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags) /* set the segment table base address */ xhci_dbg(xhci, "// Set ERST base address for ir_set 0 = 0x%llx\n", (unsigned long long)xhci->erst.erst_dma_addr); - val = xhci_readl(xhci, &xhci->ir_set->erst_base[0]); - val &= ERST_PTR_MASK; - val |= (xhci->erst.erst_dma_addr & ~ERST_PTR_MASK); - xhci_writel(xhci, val, &xhci->ir_set->erst_base[0]); - xhci_writel(xhci, 0, &xhci->ir_set->erst_base[1]); + val_64 = xhci_read_64(xhci, &xhci->ir_set->erst_base); + val_64 &= ERST_PTR_MASK; + val_64 |= (xhci->erst.erst_dma_addr & (u64) ~ERST_PTR_MASK); + xhci_write_64(xhci, val_64, &xhci->ir_set->erst_base); /* Set the event ring dequeue address */ xhci_set_hc_event_deq(xhci); diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c index d672ba14ff80..588686fca471 100644 --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c @@ -237,7 +237,7 @@ static int room_on_ring(struct xhci_hcd *xhci, struct xhci_ring *ring, void xhci_set_hc_event_deq(struct xhci_hcd *xhci) { - u32 temp; + u64 temp; dma_addr_t deq; deq = xhci_trb_virt_to_dma(xhci->event_ring->deq_seg, @@ -246,13 +246,12 @@ void xhci_set_hc_event_deq(struct xhci_hcd *xhci) xhci_warn(xhci, "WARN something wrong with SW event ring " "dequeue ptr.\n"); /* Update HC event ring dequeue pointer */ - temp = xhci_readl(xhci, &xhci->ir_set->erst_dequeue[0]); + temp = xhci_read_64(xhci, &xhci->ir_set->erst_dequeue); temp &= ERST_PTR_MASK; if (!in_interrupt()) xhci_dbg(xhci, "// Write event ring dequeue pointer\n"); - xhci_writel(xhci, 0, &xhci->ir_set->erst_dequeue[1]); - xhci_writel(xhci, (deq & ~ERST_PTR_MASK) | temp, - &xhci->ir_set->erst_dequeue[0]); + xhci_write_64(xhci, ((u64) deq & (u64) ~ERST_PTR_MASK) | temp, + &xhci->ir_set->erst_dequeue); } /* Ring the host controller doorbell after placing a command on the ring */ @@ -352,7 +351,7 @@ static void find_new_dequeue_state(struct xhci_hcd *xhci, if (!state->new_deq_seg) BUG(); /* Dig out the cycle state saved by the xHC during the stop ep cmd */ - state->new_cycle_state = 0x1 & dev->out_ctx->ep[ep_index].deq[0]; + state->new_cycle_state = 0x1 & dev->out_ctx->ep[ep_index].deq; state->new_deq_ptr = cur_td->last_trb; state->new_deq_seg = find_trb_seg(state->new_deq_seg, @@ -594,10 +593,8 @@ static void handle_set_deq_completion(struct xhci_hcd *xhci, * cancelling URBs, which might not be an error... */ } else { - xhci_dbg(xhci, "Successful Set TR Deq Ptr cmd, deq[0] = 0x%x, " - "deq[1] = 0x%x.\n", - dev->out_ctx->ep[ep_index].deq[0], - dev->out_ctx->ep[ep_index].deq[1]); + xhci_dbg(xhci, "Successful Set TR Deq Ptr cmd, deq = @%08llx\n", + dev->out_ctx->ep[ep_index].deq); } ep_ring->state &= ~SET_DEQ_PENDING; @@ -631,7 +628,7 @@ static void handle_cmd_completion(struct xhci_hcd *xhci, u64 cmd_dma; dma_addr_t cmd_dequeue_dma; - cmd_dma = (((u64) event->cmd_trb[1]) << 32) + event->cmd_trb[0]; + cmd_dma = event->cmd_trb; cmd_dequeue_dma = xhci_trb_virt_to_dma(xhci->cmd_ring->deq_seg, xhci->cmd_ring->dequeue); /* Is the command ring deq ptr out of sync with the deq seg ptr? */ @@ -794,10 +791,7 @@ static int handle_tx_event(struct xhci_hcd *xhci, return -ENODEV; } - event_dma = event->buffer[0]; - if (event->buffer[1] != 0) - xhci_warn(xhci, "WARN ignoring upper 32-bits of 64-bit TRB dma address\n"); - + event_dma = event->buffer; /* This TRB should be in the TD at the head of this ring's TD list */ if (list_empty(&ep_ring->td_list)) { xhci_warn(xhci, "WARN Event TRB for slot %d ep %d with no TDs queued?\n", @@ -821,10 +815,10 @@ static int handle_tx_event(struct xhci_hcd *xhci, event_trb = &event_seg->trbs[(event_dma - event_seg->dma) / sizeof(*event_trb)]; xhci_dbg(xhci, "Event TRB with TRB type ID %u\n", (unsigned int) (event->flags & TRB_TYPE_BITMASK)>>10); - xhci_dbg(xhci, "Offset 0x00 (buffer[0]) = 0x%x\n", - (unsigned int) event->buffer[0]); - xhci_dbg(xhci, "Offset 0x04 (buffer[0]) = 0x%x\n", - (unsigned int) event->buffer[1]); + xhci_dbg(xhci, "Offset 0x00 (buffer lo) = 0x%x\n", + lower_32_bits(event->buffer)); + xhci_dbg(xhci, "Offset 0x04 (buffer hi) = 0x%x\n", + upper_32_bits(event->buffer)); xhci_dbg(xhci, "Offset 0x08 (transfer length) = 0x%x\n", (unsigned int) event->transfer_len); xhci_dbg(xhci, "Offset 0x0C (flags) = 0x%x\n", @@ -1343,8 +1337,8 @@ static int queue_bulk_sg_tx(struct xhci_hcd *xhci, gfp_t mem_flags, TD_REMAINDER(urb->transfer_buffer_length - running_total) | TRB_INTR_TARGET(0); queue_trb(xhci, ep_ring, false, - (u32) addr, - (u32) ((u64) addr >> 32), + lower_32_bits(addr), + upper_32_bits(addr), length_field, /* We always want to know if the TRB was short, * or we won't get an event when it completes. @@ -1475,8 +1469,8 @@ int xhci_queue_bulk_tx(struct xhci_hcd *xhci, gfp_t mem_flags, TD_REMAINDER(urb->transfer_buffer_length - running_total) | TRB_INTR_TARGET(0); queue_trb(xhci, ep_ring, false, - (u32) addr, - (u32) ((u64) addr >> 32), + lower_32_bits(addr), + upper_32_bits(addr), length_field, /* We always want to know if the TRB was short, * or we won't get an event when it completes. @@ -1637,7 +1631,8 @@ int xhci_queue_slot_control(struct xhci_hcd *xhci, u32 trb_type, u32 slot_id) int xhci_queue_address_device(struct xhci_hcd *xhci, dma_addr_t in_ctx_ptr, u32 slot_id) { - return queue_command(xhci, in_ctx_ptr, 0, 0, + return queue_command(xhci, lower_32_bits(in_ctx_ptr), + upper_32_bits(in_ctx_ptr), 0, TRB_TYPE(TRB_ADDR_DEV) | SLOT_ID_FOR_TRB(slot_id)); } @@ -1645,7 +1640,8 @@ int xhci_queue_address_device(struct xhci_hcd *xhci, dma_addr_t in_ctx_ptr, int xhci_queue_configure_endpoint(struct xhci_hcd *xhci, dma_addr_t in_ctx_ptr, u32 slot_id) { - return queue_command(xhci, in_ctx_ptr, 0, 0, + return queue_command(xhci, lower_32_bits(in_ctx_ptr), + upper_32_bits(in_ctx_ptr), 0, TRB_TYPE(TRB_CONFIG_EP) | SLOT_ID_FOR_TRB(slot_id)); } @@ -1677,7 +1673,8 @@ static int queue_set_tr_deq(struct xhci_hcd *xhci, int slot_id, xhci_warn(xhci, "WARN Cannot submit Set TR Deq Ptr\n"); xhci_warn(xhci, "WARN deq seg = %p, deq pt = %p\n", deq_seg, deq_ptr); - return queue_command(xhci, (u32) addr | cycle_state, 0, 0, + return queue_command(xhci, lower_32_bits(addr) | cycle_state, + upper_32_bits(addr), 0, trb_slot_id | trb_ep_index | type); } diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h index cde648a524f5..60770c89132b 100644 --- a/drivers/usb/host/xhci.h +++ b/drivers/usb/host/xhci.h @@ -25,6 +25,7 @@ #include #include +#include #include "../core/hcd.h" /* Code sharing between pci-quirks and xhci hcd */ @@ -42,14 +43,6 @@ * xHCI register interface. * This corresponds to the eXtensible Host Controller Interface (xHCI) * Revision 0.95 specification - * - * Registers should always be accessed with double word or quad word accesses. - * - * Some xHCI implementations may support 64-bit address pointers. Registers - * with 64-bit address pointers should be written to with dword accesses by - * writing the low dword first (ptr[0]), then the high dword (ptr[1]) second. - * xHCI implementations that do not support 64-bit address pointers will ignore - * the high dword, and write order is irrelevant. */ /** @@ -166,10 +159,10 @@ struct xhci_op_regs { u32 reserved1; u32 reserved2; u32 dev_notification; - u32 cmd_ring[2]; + u64 cmd_ring; /* rsvd: offset 0x20-2F */ u32 reserved3[4]; - u32 dcbaa_ptr[2]; + u64 dcbaa_ptr; u32 config_reg; /* rsvd: offset 0x3C-3FF */ u32 reserved4[241]; @@ -254,7 +247,7 @@ struct xhci_op_regs { #define CMD_RING_RUNNING (1 << 3) /* bits 4:5 reserved and should be preserved */ /* Command Ring pointer - bit mask for the lower 32 bits. */ -#define CMD_RING_ADDR_MASK (0xffffffc0) +#define CMD_RING_RSVD_BITS (0x3f) /* CONFIG - Configure Register - config_reg bitmasks */ /* bits 0:7 - maximum number of device slots enabled (NumSlotsEn) */ @@ -382,8 +375,8 @@ struct xhci_intr_reg { u32 irq_control; u32 erst_size; u32 rsvd; - u32 erst_base[2]; - u32 erst_dequeue[2]; + u64 erst_base; + u64 erst_dequeue; }; /* irq_pending bitmasks */ @@ -538,7 +531,7 @@ struct xhci_slot_ctx { struct xhci_ep_ctx { u32 ep_info; u32 ep_info2; - u32 deq[2]; + u64 deq; u32 tx_info; /* offset 0x14 - 0x1f reserved for HC internal use */ u32 reserved[3]; @@ -641,7 +634,7 @@ struct xhci_virt_device { */ struct xhci_device_context_array { /* 64-bit device addresses; we only write 32-bit addresses */ - u32 dev_context_ptrs[2*MAX_HC_SLOTS]; + u64 dev_context_ptrs[MAX_HC_SLOTS]; /* private xHCD pointers */ dma_addr_t dma; }; @@ -654,7 +647,7 @@ struct xhci_device_context_array { struct xhci_stream_ctx { /* 64-bit stream ring address, cycle state, and stream type */ - u32 stream_ring[2]; + u64 stream_ring; /* offset 0x14 - 0x1f reserved for HC internal use */ u32 reserved[2]; }; @@ -662,7 +655,7 @@ struct xhci_stream_ctx { struct xhci_transfer_event { /* 64-bit buffer address, or immediate data */ - u32 buffer[2]; + u64 buffer; u32 transfer_len; /* This field is interpreted differently based on the type of TRB */ u32 flags; @@ -744,7 +737,7 @@ struct xhci_transfer_event { struct xhci_link_trb { /* 64-bit segment pointer*/ - u32 segment_ptr[2]; + u64 segment_ptr; u32 intr_target; u32 control; }; @@ -755,7 +748,7 @@ struct xhci_link_trb { /* Command completion event TRB */ struct xhci_event_cmd { /* Pointer to command TRB, or the value passed by the event data trb */ - u32 cmd_trb[2]; + u64 cmd_trb; u32 status; u32 flags; }; @@ -943,7 +936,7 @@ struct xhci_ring { struct xhci_erst_entry { /* 64-bit event ring segment address */ - u32 seg_addr[2]; + u64 seg_addr; u32 seg_size; /* Set to zero */ u32 rsvd; @@ -1079,6 +1072,38 @@ static inline void xhci_writel(struct xhci_hcd *xhci, writel(val, regs); } +/* + * Registers should always be accessed with double word or quad word accesses. + * + * Some xHCI implementations may support 64-bit address pointers. Registers + * with 64-bit address pointers should be written to with dword accesses by + * writing the low dword first (ptr[0]), then the high dword (ptr[1]) second. + * xHCI implementations that do not support 64-bit address pointers will ignore + * the high dword, and write order is irrelevant. + */ +static inline u64 xhci_read_64(const struct xhci_hcd *xhci, + __u64 __iomem *regs) +{ + __u32 __iomem *ptr = (__u32 __iomem *) regs; + u64 val_lo = readl(ptr); + u64 val_hi = readl(ptr + 1); + return val_lo + (val_hi << 32); +} +static inline void xhci_write_64(struct xhci_hcd *xhci, + const u64 val, __u64 __iomem *regs) +{ + __u32 __iomem *ptr = (__u32 __iomem *) regs; + u32 val_lo = lower_32_bits(val); + u32 val_hi = upper_32_bits(val); + + if (!in_interrupt()) + xhci_dbg(xhci, + "`MEM_WRITE_DWORD(3'b000, 64'h%p, 64'h%0lx, 4'hf);\n", + regs, (long unsigned int) val); + writel(val_lo, ptr); + writel(val_hi, ptr + 1); +} + /* xHCI debugging */ void xhci_print_ir_set(struct xhci_hcd *xhci, struct xhci_intr_reg *ir_set, int set_num); void xhci_print_registers(struct xhci_hcd *xhci); -- cgit v1.2.3 From 62889610f5591005bed9517360e17531684f72d0 Mon Sep 17 00:00:00 2001 From: Sarah Sharp Date: Mon, 27 Jul 2009 12:03:36 -0700 Subject: USB: xhci: Handle short control packets correctly. When there is a short packet on a control transfer, the xHCI host controller hardware will generate two events. The first event will be for the data stage TD with a completion code for a short packet. The second event will be for the status stage with a successful completion code. Before this patch, the xHCI driver would giveback the short control URB when it received the event for the data stage TD. Then it would become confused when it saw a status stage event for the endpoint for an URB it had already finished processing. Change the xHCI host controller driver to wait for the status stage event when it receives a short transfer completion code for a data stage TD. Signed-off-by: Sarah Sharp Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/xhci-ring.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c index 588686fca471..5dd3b1fd71c0 100644 --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c @@ -892,15 +892,23 @@ static int handle_tx_event(struct xhci_hcd *xhci, if (event_trb != ep_ring->dequeue) { /* The event was for the status stage */ if (event_trb == td->last_trb) { - td->urb->actual_length = - td->urb->transfer_buffer_length; + /* Did we already see a short data stage? */ + if (td->urb->actual_length != 0) + status = -EREMOTEIO; + else + td->urb->actual_length = + td->urb->transfer_buffer_length; } else { /* Maybe the event was for the data stage? */ - if (GET_COMP_CODE(event->transfer_len) != COMP_STOP_INVAL) + if (GET_COMP_CODE(event->transfer_len) != COMP_STOP_INVAL) { /* We didn't stop on a link TRB in the middle */ td->urb->actual_length = td->urb->transfer_buffer_length - TRB_LEN(event->transfer_len); + xhci_dbg(xhci, "Waiting for status stage event\n"); + urb = NULL; + goto cleanup; + } } } } else { -- cgit v1.2.3 From 2d83109be62edd9647c45d7ed2b916b03974a7ec Mon Sep 17 00:00:00 2001 From: Sarah Sharp Date: Mon, 27 Jul 2009 12:03:40 -0700 Subject: USB: xhci: Correct Event Handler Busy flag usage. The Event Handler Busy bit in the event ring dequeue pointer is write 1 to clear. Fix the interrupt service routine to clear that bit after the event handler has run. xhci_set_hc_event_deq() is designed to update the event ring dequeue pointer without changing any of the four reserved bits in the lower nibble. The event handler busy (EHB) bit is write one to clear, so the new value must always contain a zero in that bit in order to preserve the EHB value. Signed-off-by: Sarah Sharp Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/xhci-hcd.c | 4 ++-- drivers/usb/host/xhci-ring.c | 6 +++++- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/drivers/usb/host/xhci-hcd.c b/drivers/usb/host/xhci-hcd.c index e15773598e4e..2e8e5bf6b6ca 100644 --- a/drivers/usb/host/xhci-hcd.c +++ b/drivers/usb/host/xhci-hcd.c @@ -249,9 +249,9 @@ static void xhci_work(struct xhci_hcd *xhci) /* FIXME this should be a delayed service routine that clears the EHB */ xhci_handle_event(xhci); - /* Clear the event handler busy flag; the event ring should be empty. */ + /* Clear the event handler busy flag (RW1C); the event ring should be empty. */ temp_64 = xhci_read_64(xhci, &xhci->ir_set->erst_dequeue); - xhci_write_64(xhci, temp_64 & ~ERST_EHB, &xhci->ir_set->erst_dequeue); + xhci_write_64(xhci, temp_64 | ERST_EHB, &xhci->ir_set->erst_dequeue); /* Flush posted writes -- FIXME is this necessary? */ xhci_readl(xhci, &xhci->ir_set->irq_pending); } diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c index 5dd3b1fd71c0..fe9541a89a3d 100644 --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c @@ -248,8 +248,12 @@ void xhci_set_hc_event_deq(struct xhci_hcd *xhci) /* Update HC event ring dequeue pointer */ temp = xhci_read_64(xhci, &xhci->ir_set->erst_dequeue); temp &= ERST_PTR_MASK; + /* Don't clear the EHB bit (which is RW1C) because + * there might be more events to service. + */ + temp &= ~ERST_EHB; if (!in_interrupt()) - xhci_dbg(xhci, "// Write event ring dequeue pointer\n"); + xhci_dbg(xhci, "// Write event ring dequeue pointer, preserving EHB bit\n"); xhci_write_64(xhci, ((u64) deq & (u64) ~ERST_PTR_MASK) | temp, &xhci->ir_set->erst_dequeue); } -- cgit v1.2.3 From 66e49d8774fa03539713e8f91169c37c05df1e94 Mon Sep 17 00:00:00 2001 From: Sarah Sharp Date: Mon, 27 Jul 2009 12:03:46 -0700 Subject: USB: xhci: Make debugging more verbose. Add more debugging to the irq handler, slot context initialization, ring operations, URB cancellation, and MMIO writes. Signed-off-by: Sarah Sharp Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/xhci-hcd.c | 47 +++++++++++++++++++++++++++++++------------- drivers/usb/host/xhci-ring.c | 35 +++++++++++++++++++++++++++++++-- drivers/usb/host/xhci.h | 14 ++++++------- 3 files changed, 72 insertions(+), 24 deletions(-) diff --git a/drivers/usb/host/xhci-hcd.c b/drivers/usb/host/xhci-hcd.c index 2e8e5bf6b6ca..764995fd59ef 100644 --- a/drivers/usb/host/xhci-hcd.c +++ b/drivers/usb/host/xhci-hcd.c @@ -267,8 +267,10 @@ irqreturn_t xhci_irq(struct usb_hcd *hcd) { struct xhci_hcd *xhci = hcd_to_xhci(hcd); u32 temp, temp2; + union xhci_trb *trb; spin_lock(&xhci->lock); + trb = xhci->event_ring->dequeue; /* Check if the xHC generated the interrupt, or the irq is shared */ temp = xhci_readl(xhci, &xhci->op_regs->status); temp2 = xhci_readl(xhci, &xhci->ir_set->irq_pending); @@ -276,6 +278,15 @@ irqreturn_t xhci_irq(struct usb_hcd *hcd) spin_unlock(&xhci->lock); return IRQ_NONE; } + xhci_dbg(xhci, "op reg status = %08x\n", temp); + xhci_dbg(xhci, "ir set irq_pending = %08x\n", temp2); + xhci_dbg(xhci, "Event ring dequeue ptr:\n"); + xhci_dbg(xhci, "@%llx %08x %08x %08x %08x\n", + (unsigned long long)xhci_trb_virt_to_dma(xhci->event_ring->deq_seg, trb), + lower_32_bits(trb->link.segment_ptr), + upper_32_bits(trb->link.segment_ptr), + (unsigned int) trb->link.intr_target, + (unsigned int) trb->link.control); if (temp & STS_FATAL) { xhci_warn(xhci, "WARNING: Host System Error\n"); @@ -385,6 +396,20 @@ int xhci_run(struct usb_hcd *hcd) add_timer(&xhci->event_ring_timer); #endif + xhci_dbg(xhci, "Command ring memory map follows:\n"); + xhci_debug_ring(xhci, xhci->cmd_ring); + xhci_dbg_ring_ptrs(xhci, xhci->cmd_ring); + xhci_dbg_cmd_ptrs(xhci); + + xhci_dbg(xhci, "ERST memory map follows:\n"); + xhci_dbg_erst(xhci, &xhci->erst); + xhci_dbg(xhci, "Event ring:\n"); + xhci_debug_ring(xhci, xhci->event_ring); + xhci_dbg_ring_ptrs(xhci, xhci->event_ring); + temp_64 = xhci_read_64(xhci, &xhci->ir_set->erst_dequeue); + temp_64 &= ~ERST_PTR_MASK; + xhci_dbg(xhci, "ERST deq = 64'h%0lx\n", (long unsigned int) temp_64); + xhci_dbg(xhci, "// Set the interrupt modulation register\n"); temp = xhci_readl(xhci, &xhci->ir_set->irq_control); temp &= ~ER_IRQ_INTERVAL_MASK; @@ -409,20 +434,6 @@ int xhci_run(struct usb_hcd *hcd) if (NUM_TEST_NOOPS > 0) doorbell = xhci_setup_one_noop(xhci); - xhci_dbg(xhci, "Command ring memory map follows:\n"); - xhci_debug_ring(xhci, xhci->cmd_ring); - xhci_dbg_ring_ptrs(xhci, xhci->cmd_ring); - xhci_dbg_cmd_ptrs(xhci); - - xhci_dbg(xhci, "ERST memory map follows:\n"); - xhci_dbg_erst(xhci, &xhci->erst); - xhci_dbg(xhci, "Event ring:\n"); - xhci_debug_ring(xhci, xhci->event_ring); - xhci_dbg_ring_ptrs(xhci, xhci->event_ring); - temp_64 = xhci_read_64(xhci, &xhci->ir_set->erst_dequeue); - temp_64 &= ~ERST_PTR_MASK; - xhci_dbg(xhci, "ERST deq = 64'h%0lx\n", (long unsigned int) temp_64); - temp = xhci_readl(xhci, &xhci->op_regs->command); temp |= (CMD_RUN); xhci_dbg(xhci, "// Turn on HC, cmd = 0x%x.\n", @@ -665,8 +676,12 @@ int xhci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status) goto done; xhci_dbg(xhci, "Cancel URB %p\n", urb); + xhci_dbg(xhci, "Event ring:\n"); + xhci_debug_ring(xhci, xhci->event_ring); ep_index = xhci_get_endpoint_index(&urb->ep->desc); ep_ring = xhci->devs[urb->dev->slot_id]->ep_rings[ep_index]; + xhci_dbg(xhci, "Endpoint ring:\n"); + xhci_debug_ring(xhci, ep_ring); td = (struct xhci_td *) urb->hcpriv; ep_ring->cancels_pending++; @@ -1178,6 +1193,8 @@ int xhci_address_device(struct usb_hcd *hcd, struct usb_device *udev) if (!udev->config) xhci_setup_addressable_virt_dev(xhci, udev); /* Otherwise, assume the core has the device configured how it wants */ + xhci_dbg(xhci, "Slot ID %d Input Context:\n", udev->slot_id); + xhci_dbg_ctx(xhci, virt_dev->in_ctx, virt_dev->in_ctx_dma, 2); spin_lock_irqsave(&xhci->lock, flags); ret = xhci_queue_address_device(xhci, virt_dev->in_ctx_dma, @@ -1221,6 +1238,8 @@ int xhci_address_device(struct usb_hcd *hcd, struct usb_device *udev) default: xhci_err(xhci, "ERROR: unexpected command completion " "code 0x%x.\n", virt_dev->cmd_status); + xhci_dbg(xhci, "Slot ID %d Output Context:\n", udev->slot_id); + xhci_dbg_ctx(xhci, virt_dev->out_ctx, virt_dev->out_ctx_dma, 2); ret = -EINVAL; break; } diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c index fe9541a89a3d..1fc0decfa0ac 100644 --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c @@ -135,6 +135,7 @@ static void next_trb(struct xhci_hcd *xhci, static void inc_deq(struct xhci_hcd *xhci, struct xhci_ring *ring, bool consumer) { union xhci_trb *next = ++(ring->dequeue); + unsigned long long addr; ring->deq_updates++; /* Update the dequeue pointer further if that was a link TRB or we're at @@ -152,6 +153,13 @@ static void inc_deq(struct xhci_hcd *xhci, struct xhci_ring *ring, bool consumer ring->dequeue = ring->deq_seg->trbs; next = ring->dequeue; } + addr = (unsigned long long) xhci_trb_virt_to_dma(ring->deq_seg, ring->dequeue); + if (ring == xhci->event_ring) + xhci_dbg(xhci, "Event ring deq = 0x%llx (DMA)\n", addr); + else if (ring == xhci->cmd_ring) + xhci_dbg(xhci, "Command ring deq = 0x%llx (DMA)\n", addr); + else + xhci_dbg(xhci, "Ring deq = 0x%llx (DMA)\n", addr); } /* @@ -171,6 +179,7 @@ static void inc_enq(struct xhci_hcd *xhci, struct xhci_ring *ring, bool consumer { u32 chain; union xhci_trb *next; + unsigned long long addr; chain = ring->enqueue->generic.field[3] & TRB_CHAIN; next = ++(ring->enqueue); @@ -204,6 +213,13 @@ static void inc_enq(struct xhci_hcd *xhci, struct xhci_ring *ring, bool consumer ring->enqueue = ring->enq_seg->trbs; next = ring->enqueue; } + addr = (unsigned long long) xhci_trb_virt_to_dma(ring->enq_seg, ring->enqueue); + if (ring == xhci->event_ring) + xhci_dbg(xhci, "Event ring enq = 0x%llx (DMA)\n", addr); + else if (ring == xhci->cmd_ring) + xhci_dbg(xhci, "Command ring enq = 0x%llx (DMA)\n", addr); + else + xhci_dbg(xhci, "Ring enq = 0x%llx (DMA)\n", addr); } /* @@ -252,8 +268,7 @@ void xhci_set_hc_event_deq(struct xhci_hcd *xhci) * there might be more events to service. */ temp &= ~ERST_EHB; - if (!in_interrupt()) - xhci_dbg(xhci, "// Write event ring dequeue pointer, preserving EHB bit\n"); + xhci_dbg(xhci, "// Write event ring dequeue pointer, preserving EHB bit\n"); xhci_write_64(xhci, ((u64) deq & (u64) ~ERST_PTR_MASK) | temp, &xhci->ir_set->erst_dequeue); } @@ -781,6 +796,7 @@ static int handle_tx_event(struct xhci_hcd *xhci, struct urb *urb = 0; int status = -EINPROGRESS; + xhci_dbg(xhci, "In %s\n", __func__); xdev = xhci->devs[TRB_TO_SLOT_ID(event->flags)]; if (!xdev) { xhci_err(xhci, "ERROR Transfer event pointed to bad slot\n"); @@ -789,6 +805,7 @@ static int handle_tx_event(struct xhci_hcd *xhci, /* Endpoint ID is 1 based, our index is zero based */ ep_index = TRB_TO_EP_ID(event->flags) - 1; + xhci_dbg(xhci, "%s - ep index = %d\n", __func__, ep_index); ep_ring = xdev->ep_rings[ep_index]; if (!ep_ring || (xdev->out_ctx->ep[ep_index].ep_info & EP_STATE_MASK) == EP_STATE_DISABLED) { xhci_err(xhci, "ERROR Transfer event pointed to disabled endpoint\n"); @@ -797,6 +814,7 @@ static int handle_tx_event(struct xhci_hcd *xhci, event_dma = event->buffer; /* This TRB should be in the TD at the head of this ring's TD list */ + xhci_dbg(xhci, "%s - checking for list empty\n", __func__); if (list_empty(&ep_ring->td_list)) { xhci_warn(xhci, "WARN Event TRB for slot %d ep %d with no TDs queued?\n", TRB_TO_SLOT_ID(event->flags), ep_index); @@ -806,11 +824,14 @@ static int handle_tx_event(struct xhci_hcd *xhci, urb = NULL; goto cleanup; } + xhci_dbg(xhci, "%s - getting list entry\n", __func__); td = list_entry(ep_ring->td_list.next, struct xhci_td, td_list); /* Is this a TRB in the currently executing TD? */ + xhci_dbg(xhci, "%s - looking for TD\n", __func__); event_seg = trb_in_td(ep_ring->deq_seg, ep_ring->dequeue, td->last_trb, event_dma); + xhci_dbg(xhci, "%s - found event_seg = %p\n", __func__, event_seg); if (!event_seg) { /* HC is busted, give up! */ xhci_err(xhci, "ERROR Transfer event TRB DMA ptr not part of current TD\n"); @@ -1027,6 +1048,8 @@ cleanup: /* FIXME for multi-TD URBs (who have buffers bigger than 64MB) */ if (urb) { usb_hcd_unlink_urb_from_ep(xhci_to_hcd(xhci), urb); + xhci_dbg(xhci, "Giveback URB %p, len = %d, status = %d\n", + urb, td->urb->actual_length, status); spin_unlock(&xhci->lock); usb_hcd_giveback_urb(xhci_to_hcd(xhci), urb, status); spin_lock(&xhci->lock); @@ -1044,6 +1067,7 @@ void xhci_handle_event(struct xhci_hcd *xhci) int update_ptrs = 1; int ret; + xhci_dbg(xhci, "In %s\n", __func__); if (!xhci->event_ring || !xhci->event_ring->dequeue) { xhci->error_bitmask |= 1 << 1; return; @@ -1056,18 +1080,25 @@ void xhci_handle_event(struct xhci_hcd *xhci) xhci->error_bitmask |= 1 << 2; return; } + xhci_dbg(xhci, "%s - OS owns TRB\n", __func__); /* FIXME: Handle more event types. */ switch ((event->event_cmd.flags & TRB_TYPE_BITMASK)) { case TRB_TYPE(TRB_COMPLETION): + xhci_dbg(xhci, "%s - calling handle_cmd_completion\n", __func__); handle_cmd_completion(xhci, &event->event_cmd); + xhci_dbg(xhci, "%s - returned from handle_cmd_completion\n", __func__); break; case TRB_TYPE(TRB_PORT_STATUS): + xhci_dbg(xhci, "%s - calling handle_port_status\n", __func__); handle_port_status(xhci, event); + xhci_dbg(xhci, "%s - returned from handle_port_status\n", __func__); update_ptrs = 0; break; case TRB_TYPE(TRB_TRANSFER): + xhci_dbg(xhci, "%s - calling handle_tx_event\n", __func__); ret = handle_tx_event(xhci, &event->trans_event); + xhci_dbg(xhci, "%s - returned from handle_tx_event\n", __func__); if (ret < 0) xhci->error_bitmask |= 1 << 9; else diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h index 60770c89132b..074728e10225 100644 --- a/drivers/usb/host/xhci.h +++ b/drivers/usb/host/xhci.h @@ -1065,10 +1065,9 @@ static inline unsigned int xhci_readl(const struct xhci_hcd *xhci, static inline void xhci_writel(struct xhci_hcd *xhci, const unsigned int val, __u32 __iomem *regs) { - if (!in_interrupt()) - xhci_dbg(xhci, - "`MEM_WRITE_DWORD(3'b000, 32'h%p, 32'h%0x, 4'hf);\n", - regs, val); + xhci_dbg(xhci, + "`MEM_WRITE_DWORD(3'b000, 32'h%p, 32'h%0x, 4'hf);\n", + regs, val); writel(val, regs); } @@ -1096,10 +1095,9 @@ static inline void xhci_write_64(struct xhci_hcd *xhci, u32 val_lo = lower_32_bits(val); u32 val_hi = upper_32_bits(val); - if (!in_interrupt()) - xhci_dbg(xhci, - "`MEM_WRITE_DWORD(3'b000, 64'h%p, 64'h%0lx, 4'hf);\n", - regs, (long unsigned int) val); + xhci_dbg(xhci, + "`MEM_WRITE_DWORD(3'b000, 64'h%p, 64'h%0lx, 4'hf);\n", + regs, (long unsigned int) val); writel(val_lo, ptr); writel(val_hi, ptr + 1); } -- cgit v1.2.3 From d3512f63494678dc58e44a20c56278718fd58969 Mon Sep 17 00:00:00 2001 From: Sarah Sharp Date: Mon, 27 Jul 2009 12:03:50 -0700 Subject: USB: xhci: Don't oops if the host doesn't halt. Signed-off-by: Sarah Sharp Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/xhci-hcd.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/usb/host/xhci-hcd.c b/drivers/usb/host/xhci-hcd.c index 764995fd59ef..8c3a074a95cd 100644 --- a/drivers/usb/host/xhci-hcd.c +++ b/drivers/usb/host/xhci-hcd.c @@ -103,7 +103,10 @@ int xhci_reset(struct xhci_hcd *xhci) u32 state; state = xhci_readl(xhci, &xhci->op_regs->status); - BUG_ON((state & STS_HALT) == 0); + if ((state & STS_HALT) == 0) { + xhci_warn(xhci, "Host controller not halted, aborting reset.\n"); + return 0; + } xhci_dbg(xhci, "// Reset the HC\n"); command = xhci_readl(xhci, &xhci->op_regs->command); -- cgit v1.2.3 From fcf8f576beafb8c5db8aee8a73eb73763fa7b0ad Mon Sep 17 00:00:00 2001 From: Sarah Sharp Date: Mon, 27 Jul 2009 12:04:01 -0700 Subject: USB: xhci: Check if the host controller died in IRQ handler. Signed-off-by: Sarah Sharp Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/xhci-hcd.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/usb/host/xhci-hcd.c b/drivers/usb/host/xhci-hcd.c index 8c3a074a95cd..008326d5bc52 100644 --- a/drivers/usb/host/xhci-hcd.c +++ b/drivers/usb/host/xhci-hcd.c @@ -277,6 +277,9 @@ irqreturn_t xhci_irq(struct usb_hcd *hcd) /* Check if the xHC generated the interrupt, or the irq is shared */ temp = xhci_readl(xhci, &xhci->op_regs->status); temp2 = xhci_readl(xhci, &xhci->ir_set->irq_pending); + if (temp == 0xffffffff && temp2 == 0xffffffff) + goto hw_died; + if (!(temp & STS_EINT) && !ER_IRQ_PENDING(temp2)) { spin_unlock(&xhci->lock); return IRQ_NONE; @@ -294,6 +297,7 @@ irqreturn_t xhci_irq(struct usb_hcd *hcd) if (temp & STS_FATAL) { xhci_warn(xhci, "WARNING: Host System Error\n"); xhci_halt(xhci); +hw_died: xhci_to_hcd(xhci)->state = HC_STATE_HALT; spin_unlock(&xhci->lock); return -ESHUTDOWN; -- cgit v1.2.3 From 47692d179f7a88794bcd302e53ca7899d7592db9 Mon Sep 17 00:00:00 2001 From: Sarah Sharp Date: Mon, 27 Jul 2009 12:04:27 -0700 Subject: USB: xhci: Setup HW retries correctly. The xHCI host controller can be programmed to retry a transfer a certain number of times per endpoint before it passes back an error condition to the host controller driver. The xHC will return an error code when the error count transitions from 1 to 0. Programming an error count of 3 means the xHC tries the transfer 3 times, programming it with a 1 means it tries to transfer once, and programming it with 0 means the HW tries the transfer infinitely. We want isochronous transfers to only be tried once, so set the error count to one. Signed-off-by: Sarah Sharp Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/xhci-mem.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c index ec825f16dcee..075e1036bcb4 100644 --- a/drivers/usb/host/xhci-mem.c +++ b/drivers/usb/host/xhci-mem.c @@ -480,11 +480,13 @@ int xhci_endpoint_init(struct xhci_hcd *xhci, /* FIXME dig Mult and streams info out of ep companion desc */ - /* Allow 3 retries for everything but isoc */ + /* Allow 3 retries for everything but isoc; + * error count = 0 means infinite retries. + */ if (!usb_endpoint_xfer_isoc(&ep->desc)) ep_ctx->ep_info2 = ERROR_COUNT(3); else - ep_ctx->ep_info2 = ERROR_COUNT(0); + ep_ctx->ep_info2 = ERROR_COUNT(1); ep_ctx->ep_info2 |= xhci_get_endpoint_type(udev, ep); -- cgit v1.2.3 From 4a73143ced467868e92d7914d9f8bf797640927b Mon Sep 17 00:00:00 2001 From: Sarah Sharp Date: Mon, 27 Jul 2009 12:04:32 -0700 Subject: USB: xhci: Handle babble errors on transfers. Pass back a babble error when this error code is seen in the transfer event TRB. Signed-off-by: Sarah Sharp Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/xhci-ring.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c index 1fc0decfa0ac..0903e98989ec 100644 --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c @@ -876,6 +876,10 @@ static int handle_tx_event(struct xhci_hcd *xhci, xhci_warn(xhci, "WARN: transfer error on endpoint\n"); status = -EPROTO; break; + case COMP_BABBLE: + xhci_warn(xhci, "WARN: babble error on endpoint\n"); + status = -EOVERFLOW; + break; case COMP_DB_ERR: xhci_warn(xhci, "WARN: HC couldn't access mem fast enough\n"); status = -ENOSR; -- cgit v1.2.3 From b7d6d99896a6cf38dc354d673afd3fbde10b86c2 Mon Sep 17 00:00:00 2001 From: Sarah Sharp Date: Mon, 27 Jul 2009 12:04:38 -0700 Subject: USB: xhci: Fail gracefully if there's no SS ep companion descriptor. This is a work around for a bug in the SuperSpeed Endpoint Companion Descriptor parsing code. It fails in some corner cases, which means ep->ss_ep_comp may be NULL. Signed-off-by: Sarah Sharp Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/xhci-mem.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c index 075e1036bcb4..41aca003ee82 100644 --- a/drivers/usb/host/xhci-mem.c +++ b/drivers/usb/host/xhci-mem.c @@ -496,7 +496,12 @@ int xhci_endpoint_init(struct xhci_hcd *xhci, max_packet = ep->desc.wMaxPacketSize; ep_ctx->ep_info2 |= MAX_PACKET(max_packet); /* dig out max burst from ep companion desc */ - max_packet = ep->ss_ep_comp->desc.bMaxBurst; + if (!ep->ss_ep_comp) { + xhci_warn(xhci, "WARN no SS endpoint companion descriptor.\n"); + max_packet = 0; + } else { + max_packet = ep->ss_ep_comp->desc.bMaxBurst; + } ep_ctx->ep_info2 |= MAX_BURST(max_packet); break; case USB_SPEED_HIGH: -- cgit v1.2.3 From 9f8e443816976edd68f415ea25c0223ea921e88c Mon Sep 17 00:00:00 2001 From: Sarah Sharp Date: Mon, 27 Jul 2009 12:04:52 -0700 Subject: USB: Fix parsing of SuperSpeed Endpoint Companion descriptor. usb_parse_ss_endpoint_companion() was supposed to allocate a structure to hold the SuperSpeed Endpoint Companion descriptor, and either copy the values the device returned, or fill in default values if the device descriptor did not include the companion descriptor. However, the previous code would miss the last endpoint in a configuration with no descriptors after it. Make usb_parse_endpoint() allocate the SS endpoint companion descriptor and fill it with default values, even if we've run out of buffer space in this configuration descriptor. Signed-off-by: Sarah Sharp Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/config.c | 48 ++++++++++++++++++++++++++--------------------- 1 file changed, 27 insertions(+), 21 deletions(-) diff --git a/drivers/usb/core/config.c b/drivers/usb/core/config.c index 24dfb33f90cb..a16c538d0132 100644 --- a/drivers/usb/core/config.c +++ b/drivers/usb/core/config.c @@ -80,38 +80,18 @@ static int usb_parse_ss_endpoint_companion(struct device *ddev, int cfgno, int max_tx; int i; - /* Allocate space for the SS endpoint companion descriptor */ - ep->ss_ep_comp = kzalloc(sizeof(struct usb_host_ss_ep_comp), - GFP_KERNEL); - if (!ep->ss_ep_comp) - return -ENOMEM; desc = (struct usb_ss_ep_comp_descriptor *) buffer; if (desc->bDescriptorType != USB_DT_SS_ENDPOINT_COMP) { dev_warn(ddev, "No SuperSpeed endpoint companion for config %d " " interface %d altsetting %d ep %d: " "using minimum values\n", cfgno, inum, asnum, ep->desc.bEndpointAddress); - ep->ss_ep_comp->desc.bLength = USB_DT_SS_EP_COMP_SIZE; - ep->ss_ep_comp->desc.bDescriptorType = USB_DT_SS_ENDPOINT_COMP; - ep->ss_ep_comp->desc.bMaxBurst = 0; - /* - * Leave bmAttributes as zero, which will mean no streams for - * bulk, and isoc won't support multiple bursts of packets. - * With bursts of only one packet, and a Mult of 1, the max - * amount of data moved per endpoint service interval is one - * packet. - */ - if (usb_endpoint_xfer_isoc(&ep->desc) || - usb_endpoint_xfer_int(&ep->desc)) - ep->ss_ep_comp->desc.wBytesPerInterval = - ep->desc.wMaxPacketSize; /* * The next descriptor is for an Endpoint or Interface, * no extra descriptors to copy into the companion structure, * and we didn't eat up any of the buffer. */ - retval = 0; - goto valid; + return 0; } memcpy(&ep->ss_ep_comp->desc, desc, USB_DT_SS_EP_COMP_SIZE); desc = &ep->ss_ep_comp->desc; @@ -320,6 +300,28 @@ static int usb_parse_endpoint(struct device *ddev, int cfgno, int inum, buffer += i; size -= i; + /* Allocate space for the SS endpoint companion descriptor */ + endpoint->ss_ep_comp = kzalloc(sizeof(struct usb_host_ss_ep_comp), + GFP_KERNEL); + if (!endpoint->ss_ep_comp) + return -ENOMEM; + + /* Fill in some default values (may be overwritten later) */ + endpoint->ss_ep_comp->desc.bLength = USB_DT_SS_EP_COMP_SIZE; + endpoint->ss_ep_comp->desc.bDescriptorType = USB_DT_SS_ENDPOINT_COMP; + endpoint->ss_ep_comp->desc.bMaxBurst = 0; + /* + * Leave bmAttributes as zero, which will mean no streams for + * bulk, and isoc won't support multiple bursts of packets. + * With bursts of only one packet, and a Mult of 1, the max + * amount of data moved per endpoint service interval is one + * packet. + */ + if (usb_endpoint_xfer_isoc(&endpoint->desc) || + usb_endpoint_xfer_int(&endpoint->desc)) + endpoint->ss_ep_comp->desc.wBytesPerInterval = + endpoint->desc.wMaxPacketSize; + if (size > 0) { retval = usb_parse_ss_endpoint_companion(ddev, cfgno, inum, asnum, endpoint, num_ep, buffer, @@ -329,6 +331,10 @@ static int usb_parse_endpoint(struct device *ddev, int cfgno, int inum, retval = buffer - buffer0; } } else { + dev_warn(ddev, "config %d interface %d altsetting %d " + "endpoint 0x%X has no " + "SuperSpeed companion descriptor\n", + cfgno, inum, asnum, d->bEndpointAddress); retval = buffer - buffer0; } } else { -- cgit v1.2.3 From 254c80a3a0eb811489f7410c3291f01a60e8e42f Mon Sep 17 00:00:00 2001 From: John Youn Date: Mon, 27 Jul 2009 12:05:03 -0700 Subject: USB: xhci: Scratchpad buffer allocation Allocates and initializes the scratchpad buffer array (XHCI 4.20). This is an array of 64-bit DMA addresses to scratch pages that the controller may use during operation. The number of pages is specified in the "Max Scratchpad Buffers" field of HCSPARAMS2. The DMA address of this array is written into slot 0 of the DCBAA. Signed-off-by: John Youn Acked-by: Sarah Sharp Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/xhci-mem.c | 102 ++++++++++++++++++++++++++++++++++++++++++++ drivers/usb/host/xhci.h | 11 +++++ 2 files changed, 113 insertions(+) diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c index 41aca003ee82..71121d99235d 100644 --- a/drivers/usb/host/xhci-mem.c +++ b/drivers/usb/host/xhci-mem.c @@ -545,6 +545,103 @@ void xhci_endpoint_zero(struct xhci_hcd *xhci, */ } +/* Set up the scratchpad buffer array and scratchpad buffers, if needed. */ +static int scratchpad_alloc(struct xhci_hcd *xhci, gfp_t flags) +{ + int i; + struct device *dev = xhci_to_hcd(xhci)->self.controller; + int num_sp = HCS_MAX_SCRATCHPAD(xhci->hcs_params2); + + xhci_dbg(xhci, "Allocating %d scratchpad buffers\n", num_sp); + + if (!num_sp) + return 0; + + xhci->scratchpad = kzalloc(sizeof(*xhci->scratchpad), flags); + if (!xhci->scratchpad) + goto fail_sp; + + xhci->scratchpad->sp_array = + pci_alloc_consistent(to_pci_dev(dev), + num_sp * sizeof(u64), + &xhci->scratchpad->sp_dma); + if (!xhci->scratchpad->sp_array) + goto fail_sp2; + + xhci->scratchpad->sp_buffers = kzalloc(sizeof(void *) * num_sp, flags); + if (!xhci->scratchpad->sp_buffers) + goto fail_sp3; + + xhci->scratchpad->sp_dma_buffers = + kzalloc(sizeof(dma_addr_t) * num_sp, flags); + + if (!xhci->scratchpad->sp_dma_buffers) + goto fail_sp4; + + xhci->dcbaa->dev_context_ptrs[0] = xhci->scratchpad->sp_dma; + for (i = 0; i < num_sp; i++) { + dma_addr_t dma; + void *buf = pci_alloc_consistent(to_pci_dev(dev), + xhci->page_size, &dma); + if (!buf) + goto fail_sp5; + + xhci->scratchpad->sp_array[i] = dma; + xhci->scratchpad->sp_buffers[i] = buf; + xhci->scratchpad->sp_dma_buffers[i] = dma; + } + + return 0; + + fail_sp5: + for (i = i - 1; i >= 0; i--) { + pci_free_consistent(to_pci_dev(dev), xhci->page_size, + xhci->scratchpad->sp_buffers[i], + xhci->scratchpad->sp_dma_buffers[i]); + } + kfree(xhci->scratchpad->sp_dma_buffers); + + fail_sp4: + kfree(xhci->scratchpad->sp_buffers); + + fail_sp3: + pci_free_consistent(to_pci_dev(dev), num_sp * sizeof(u64), + xhci->scratchpad->sp_array, + xhci->scratchpad->sp_dma); + + fail_sp2: + kfree(xhci->scratchpad); + xhci->scratchpad = NULL; + + fail_sp: + return -ENOMEM; +} + +static void scratchpad_free(struct xhci_hcd *xhci) +{ + int num_sp; + int i; + struct pci_dev *pdev = to_pci_dev(xhci_to_hcd(xhci)->self.controller); + + if (!xhci->scratchpad) + return; + + num_sp = HCS_MAX_SCRATCHPAD(xhci->hcs_params2); + + for (i = 0; i < num_sp; i++) { + pci_free_consistent(pdev, xhci->page_size, + xhci->scratchpad->sp_buffers[i], + xhci->scratchpad->sp_dma_buffers[i]); + } + kfree(xhci->scratchpad->sp_dma_buffers); + kfree(xhci->scratchpad->sp_buffers); + pci_free_consistent(pdev, num_sp * sizeof(u64), + xhci->scratchpad->sp_array, + xhci->scratchpad->sp_dma); + kfree(xhci->scratchpad); + xhci->scratchpad = NULL; +} + void xhci_mem_cleanup(struct xhci_hcd *xhci) { struct pci_dev *pdev = to_pci_dev(xhci_to_hcd(xhci)->self.controller); @@ -593,6 +690,7 @@ void xhci_mem_cleanup(struct xhci_hcd *xhci) xhci->page_size = 0; xhci->page_shift = 0; + scratchpad_free(xhci); } int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags) @@ -755,7 +853,11 @@ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags) for (i = 0; i < MAX_HC_SLOTS; ++i) xhci->devs[i] = 0; + if (scratchpad_alloc(xhci, flags)) + goto fail; + return 0; + fail: xhci_warn(xhci, "Couldn't initialize memory\n"); xhci_mem_cleanup(xhci); diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h index 074728e10225..5a09b9a26e0d 100644 --- a/drivers/usb/host/xhci.h +++ b/drivers/usb/host/xhci.h @@ -89,6 +89,7 @@ struct xhci_cap_regs { #define HCS_ERST_MAX(p) (((p) >> 4) & 0xf) /* bit 26 Scratchpad restore - for save/restore HW state - not used yet */ /* bits 27:31 number of Scratchpad buffers SW must allocate for the HW */ +#define HCS_MAX_SCRATCHPAD(p) (((p) >> 27) & 0x1f) /* HCSPARAMS3 - hcs_params3 - bitmasks */ /* bits 0:7, Max U1 to U0 latency for the roothub ports */ @@ -951,6 +952,13 @@ struct xhci_erst { unsigned int erst_size; }; +struct xhci_scratchpad { + u64 *sp_array; + dma_addr_t sp_dma; + void **sp_buffers; + dma_addr_t *sp_dma_buffers; +}; + /* * Each segment table entry is 4*32bits long. 1K seems like an ok size: * (1K bytes * 8bytes/bit) / (4*32 bits) = 64 segment entries in the table, @@ -1005,6 +1013,9 @@ struct xhci_hcd { struct xhci_ring *cmd_ring; struct xhci_ring *event_ring; struct xhci_erst erst; + /* Scratchpad */ + struct xhci_scratchpad *scratchpad; + /* slot enabling and address device helpers */ struct completion addr_dev; int slot_id; -- cgit v1.2.3 From 28c2d2efb48dec2f0b050affae6d5787d6449e47 Mon Sep 17 00:00:00 2001 From: Sarah Sharp Date: Mon, 27 Jul 2009 12:05:08 -0700 Subject: USB: xhci: Always align output device contexts to 64 bytes. Make sure the xHCI output device context is 64-byte aligned. Previous code was using the same structure for both the output device context and the input control context. Since the structure had 32 bytes of flags before the device context, the output device context wouldn't be 64-byte aligned. Define a new structure to use for the output device context and clean up the debugging for these two structures. The copy of the device context in the input control context does *not* need to be 64-byte aligned. Signed-off-by: Sarah Sharp Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/xhci-dbg.c | 101 +++++++++++++++++++++++++++----------------- drivers/usb/host/xhci-hcd.c | 7 +-- drivers/usb/host/xhci-mem.c | 15 +++---- drivers/usb/host/xhci.h | 19 ++++++++- 4 files changed, 89 insertions(+), 53 deletions(-) diff --git a/drivers/usb/host/xhci-dbg.c b/drivers/usb/host/xhci-dbg.c index 6d62e4abe3c6..d77f8de11256 100644 --- a/drivers/usb/host/xhci-dbg.c +++ b/drivers/usb/host/xhci-dbg.c @@ -393,78 +393,103 @@ void xhci_dbg_cmd_ptrs(struct xhci_hcd *xhci) upper_32_bits(val)); } -void xhci_dbg_ctx(struct xhci_hcd *xhci, struct xhci_device_control *ctx, dma_addr_t dma, unsigned int last_ep) +dma_addr_t xhci_dbg_slot_ctx(struct xhci_hcd *xhci, struct xhci_slot_ctx *slot, dma_addr_t dma) { - int i, j; - int last_ep_ctx = 31; /* Fields are 32 bits wide, DMA addresses are in bytes */ int field_size = 32 / 8; - - xhci_dbg(xhci, "@%p (virt) @%08llx (dma) %#08x - drop flags\n", - &ctx->drop_flags, (unsigned long long)dma, - ctx->drop_flags); - dma += field_size; - xhci_dbg(xhci, "@%p (virt) @%08llx (dma) %#08x - add flags\n", - &ctx->add_flags, (unsigned long long)dma, - ctx->add_flags); - dma += field_size; - for (i = 0; i < 6; ++i) { - xhci_dbg(xhci, "@%p (virt) @%08llx (dma) %#08x - rsvd[%d]\n", - &ctx->rsvd[i], (unsigned long long)dma, - ctx->rsvd[i], i); - dma += field_size; - } + int i; xhci_dbg(xhci, "Slot Context:\n"); xhci_dbg(xhci, "@%p (virt) @%08llx (dma) %#08x - dev_info\n", - &ctx->slot.dev_info, - (unsigned long long)dma, ctx->slot.dev_info); + &slot->dev_info, + (unsigned long long)dma, slot->dev_info); dma += field_size; xhci_dbg(xhci, "@%p (virt) @%08llx (dma) %#08x - dev_info2\n", - &ctx->slot.dev_info2, - (unsigned long long)dma, ctx->slot.dev_info2); + &slot->dev_info2, + (unsigned long long)dma, slot->dev_info2); dma += field_size; xhci_dbg(xhci, "@%p (virt) @%08llx (dma) %#08x - tt_info\n", - &ctx->slot.tt_info, - (unsigned long long)dma, ctx->slot.tt_info); + &slot->tt_info, + (unsigned long long)dma, slot->tt_info); dma += field_size; xhci_dbg(xhci, "@%p (virt) @%08llx (dma) %#08x - dev_state\n", - &ctx->slot.dev_state, - (unsigned long long)dma, ctx->slot.dev_state); + &slot->dev_state, + (unsigned long long)dma, slot->dev_state); dma += field_size; for (i = 0; i < 4; ++i) { xhci_dbg(xhci, "@%p (virt) @%08llx (dma) %#08x - rsvd[%d]\n", - &ctx->slot.reserved[i], (unsigned long long)dma, - ctx->slot.reserved[i], i); + &slot->reserved[i], (unsigned long long)dma, + slot->reserved[i], i); dma += field_size; } + return dma; +} + +dma_addr_t xhci_dbg_ep_ctx(struct xhci_hcd *xhci, struct xhci_ep_ctx *ep, dma_addr_t dma, unsigned int last_ep) +{ + int i, j; + int last_ep_ctx = 31; + /* Fields are 32 bits wide, DMA addresses are in bytes */ + int field_size = 32 / 8; + if (last_ep < 31) last_ep_ctx = last_ep + 1; for (i = 0; i < last_ep_ctx; ++i) { xhci_dbg(xhci, "Endpoint %02d Context:\n", i); xhci_dbg(xhci, "@%p (virt) @%08llx (dma) %#08x - ep_info\n", - &ctx->ep[i].ep_info, - (unsigned long long)dma, ctx->ep[i].ep_info); + &ep[i].ep_info, + (unsigned long long)dma, ep[i].ep_info); dma += field_size; xhci_dbg(xhci, "@%p (virt) @%08llx (dma) %#08x - ep_info2\n", - &ctx->ep[i].ep_info2, - (unsigned long long)dma, ctx->ep[i].ep_info2); + &ep[i].ep_info2, + (unsigned long long)dma, ep[i].ep_info2); dma += field_size; xhci_dbg(xhci, "@%p (virt) @%08llx (dma) %#08llx - deq\n", - &ctx->ep[i].deq, - (unsigned long long)dma, ctx->ep[i].deq); + &ep[i].deq, + (unsigned long long)dma, ep[i].deq); dma += 2*field_size; xhci_dbg(xhci, "@%p (virt) @%08llx (dma) %#08x - tx_info\n", - &ctx->ep[i].tx_info, - (unsigned long long)dma, ctx->ep[i].tx_info); + &ep[i].tx_info, + (unsigned long long)dma, ep[i].tx_info); dma += field_size; for (j = 0; j < 3; ++j) { xhci_dbg(xhci, "@%p (virt) @%08llx (dma) %#08x - rsvd[%d]\n", - &ctx->ep[i].reserved[j], + &ep[i].reserved[j], (unsigned long long)dma, - ctx->ep[i].reserved[j], j); + ep[i].reserved[j], j); dma += field_size; } } + return dma; +} + +void xhci_dbg_ctx(struct xhci_hcd *xhci, struct xhci_device_control *ctx, dma_addr_t dma, unsigned int last_ep) +{ + int i; + /* Fields are 32 bits wide, DMA addresses are in bytes */ + int field_size = 32 / 8; + + xhci_dbg(xhci, "@%p (virt) @%08llx (dma) %#08x - drop flags\n", + &ctx->drop_flags, (unsigned long long)dma, + ctx->drop_flags); + dma += field_size; + xhci_dbg(xhci, "@%p (virt) @%08llx (dma) %#08x - add flags\n", + &ctx->add_flags, (unsigned long long)dma, + ctx->add_flags); + dma += field_size; + for (i = 0; i < 6; ++i) { + xhci_dbg(xhci, "@%p (virt) @%08llx (dma) %#08x - rsvd[%d]\n", + &ctx->rsvd[i], (unsigned long long)dma, + ctx->rsvd[i], i); + dma += field_size; + } + dma = xhci_dbg_slot_ctx(xhci, &ctx->slot, dma); + dma = xhci_dbg_ep_ctx(xhci, ctx->ep, dma, last_ep); +} + +void xhci_dbg_device_ctx(struct xhci_hcd *xhci, struct xhci_device_ctx *ctx, dma_addr_t dma, unsigned int last_ep) +{ + dma = xhci_dbg_slot_ctx(xhci, &ctx->slot, dma); + dma = xhci_dbg_ep_ctx(xhci, ctx->ep, dma, last_ep); } diff --git a/drivers/usb/host/xhci-hcd.c b/drivers/usb/host/xhci-hcd.c index 008326d5bc52..921dd173d793 100644 --- a/drivers/usb/host/xhci-hcd.c +++ b/drivers/usb/host/xhci-hcd.c @@ -1013,7 +1013,7 @@ int xhci_check_bandwidth(struct usb_hcd *hcd, struct usb_device *udev) } xhci_dbg(xhci, "Output context after successful config ep cmd:\n"); - xhci_dbg_ctx(xhci, virt_dev->out_ctx, virt_dev->out_ctx_dma, + xhci_dbg_device_ctx(xhci, virt_dev->out_ctx, virt_dev->out_ctx_dma, LAST_CTX_TO_EP_NUM(virt_dev->in_ctx->slot.dev_info)); xhci_zero_in_ctx(virt_dev); @@ -1265,7 +1265,7 @@ int xhci_address_device(struct usb_hcd *hcd, struct usb_device *udev) xhci_dbg(xhci, "Slot ID %d Input Context:\n", udev->slot_id); xhci_dbg_ctx(xhci, virt_dev->in_ctx, virt_dev->in_ctx_dma, 2); xhci_dbg(xhci, "Slot ID %d Output Context:\n", udev->slot_id); - xhci_dbg_ctx(xhci, virt_dev->out_ctx, virt_dev->out_ctx_dma, 2); + xhci_dbg_device_ctx(xhci, virt_dev->out_ctx, virt_dev->out_ctx_dma, 2); /* * USB core uses address 1 for the roothubs, so we add one to the * address given back to us by the HC. @@ -1274,9 +1274,6 @@ int xhci_address_device(struct usb_hcd *hcd, struct usb_device *udev) /* Zero the input context control for later use */ virt_dev->in_ctx->add_flags = 0; virt_dev->in_ctx->drop_flags = 0; - /* Mirror flags in the output context for future ep enable/disable */ - virt_dev->out_ctx->add_flags = SLOT_FLAG | EP0_FLAG; - virt_dev->out_ctx->drop_flags = 0; xhci_dbg(xhci, "Device address = %d\n", udev->devnum); /* XXX Meh, not sure if anyone else but choose_address uses this. */ diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c index 71121d99235d..8d6bdf2f8015 100644 --- a/drivers/usb/host/xhci-mem.c +++ b/drivers/usb/host/xhci-mem.c @@ -235,7 +235,10 @@ int xhci_alloc_virt_device(struct xhci_hcd *xhci, int slot_id, return 0; dev = xhci->devs[slot_id]; - /* Allocate the (output) device context that will be used in the HC */ + /* Allocate the (output) device context that will be used in the HC. + * The structure is 32 bytes smaller than the input context, but that's + * fine. + */ dev->out_ctx = dma_pool_alloc(xhci->device_pool, flags, &dma); if (!dev->out_ctx) goto fail; @@ -260,16 +263,12 @@ int xhci_alloc_virt_device(struct xhci_hcd *xhci, int slot_id, init_completion(&dev->cmd_completion); - /* - * Point to output device context in dcbaa; skip the output control - * context, which is eight 32 bit fields (or 32 bytes long) - */ - xhci->dcbaa->dev_context_ptrs[slot_id] = - (u32) dev->out_ctx_dma + (32); + /* Point to output device context in dcbaa. */ + xhci->dcbaa->dev_context_ptrs[slot_id] = dev->out_ctx_dma; xhci_dbg(xhci, "Set slot id %d dcbaa entry %p to 0x%llx\n", slot_id, &xhci->dcbaa->dev_context_ptrs[slot_id], - (unsigned long long)dev->out_ctx_dma); + (unsigned long long) xhci->dcbaa->dev_context_ptrs[slot_id]); return 1; fail: diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h index 5a09b9a26e0d..d4d3c7777fb8 100644 --- a/drivers/usb/host/xhci.h +++ b/drivers/usb/host/xhci.h @@ -584,15 +584,29 @@ struct xhci_ep_ctx { /** * struct xhci_device_control - * Input/Output context; see section 6.2.5. + * Input context; see section 6.2.5. * * @drop_context: set the bit of the endpoint context you want to disable * @add_context: set the bit of the endpoint context you want to enable */ struct xhci_device_control { + /* Input control context */ u32 drop_flags; u32 add_flags; u32 rsvd[6]; + /* Copy of device context */ + struct xhci_slot_ctx slot; + struct xhci_ep_ctx ep[31]; +}; + +/** + * struct xhci_device_ctx + * Device context; see section 6.2.1. + * + * @slot: slot context for the device. + * @ep: array of endpoint contexts for the device. + */ +struct xhci_device_ctx { struct xhci_slot_ctx slot; struct xhci_ep_ctx ep[31]; }; @@ -612,7 +626,7 @@ struct xhci_virt_device { * track of input and output contexts separately because * these commands might fail and we don't trust the hardware. */ - struct xhci_device_control *out_ctx; + struct xhci_device_ctx *out_ctx; dma_addr_t out_ctx_dma; /* Used for addressing devices and configuration changes */ struct xhci_device_control *in_ctx; @@ -1126,6 +1140,7 @@ void xhci_dbg_erst(struct xhci_hcd *xhci, struct xhci_erst *erst); void xhci_dbg_cmd_ptrs(struct xhci_hcd *xhci); void xhci_dbg_ring_ptrs(struct xhci_hcd *xhci, struct xhci_ring *ring); void xhci_dbg_ctx(struct xhci_hcd *xhci, struct xhci_device_control *ctx, dma_addr_t dma, unsigned int last_ep); +void xhci_dbg_device_ctx(struct xhci_hcd *xhci, struct xhci_device_ctx *ctx, dma_addr_t dma, unsigned int last_ep); /* xHCI memory managment */ void xhci_mem_cleanup(struct xhci_hcd *xhci); -- cgit v1.2.3 From d115b04818e57bdbc7ccde4d0660b15e33013dc8 Mon Sep 17 00:00:00 2001 From: John Youn Date: Mon, 27 Jul 2009 12:05:15 -0700 Subject: USB: xhci: Support for 64-byte contexts Adds support for controllers that use 64-byte contexts. The following context data structures are affected by this: Device, Input, Input Control, Endpoint, and Slot. To accommodate the use of either 32 or 64-byte contexts, a Device or Input context can only be accessed through functions which look-up and return pointers to their contained contexts. Signed-off-by: John Youn Acked-by: Sarah Sharp Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/xhci-dbg.c | 125 +++++++++++++++++++++++++++---------------- drivers/usb/host/xhci-hcd.c | 121 ++++++++++++++++++++++++----------------- drivers/usb/host/xhci-mem.c | 121 +++++++++++++++++++++++++++++------------ drivers/usb/host/xhci-ring.c | 22 +++++--- drivers/usb/host/xhci.h | 61 +++++++++++---------- 5 files changed, 287 insertions(+), 163 deletions(-) diff --git a/drivers/usb/host/xhci-dbg.c b/drivers/usb/host/xhci-dbg.c index d77f8de11256..705e34324156 100644 --- a/drivers/usb/host/xhci-dbg.c +++ b/drivers/usb/host/xhci-dbg.c @@ -393,103 +393,138 @@ void xhci_dbg_cmd_ptrs(struct xhci_hcd *xhci) upper_32_bits(val)); } -dma_addr_t xhci_dbg_slot_ctx(struct xhci_hcd *xhci, struct xhci_slot_ctx *slot, dma_addr_t dma) +/* Print the last 32 bytes for 64-byte contexts */ +static void dbg_rsvd64(struct xhci_hcd *xhci, u64 *ctx, dma_addr_t dma) +{ + int i; + for (i = 0; i < 4; ++i) { + xhci_dbg(xhci, "@%p (virt) @%08llx " + "(dma) %#08llx - rsvd64[%d]\n", + &ctx[4 + i], (unsigned long long)dma, + ctx[4 + i], i); + dma += 8; + } +} + +void xhci_dbg_slot_ctx(struct xhci_hcd *xhci, struct xhci_container_ctx *ctx) { /* Fields are 32 bits wide, DMA addresses are in bytes */ int field_size = 32 / 8; int i; + struct xhci_slot_ctx *slot_ctx = xhci_get_slot_ctx(xhci, ctx); + dma_addr_t dma = ctx->dma + ((unsigned long)slot_ctx - (unsigned long)ctx); + int csz = HCC_64BYTE_CONTEXT(xhci->hcc_params); + xhci_dbg(xhci, "Slot Context:\n"); xhci_dbg(xhci, "@%p (virt) @%08llx (dma) %#08x - dev_info\n", - &slot->dev_info, - (unsigned long long)dma, slot->dev_info); + &slot_ctx->dev_info, + (unsigned long long)dma, slot_ctx->dev_info); dma += field_size; xhci_dbg(xhci, "@%p (virt) @%08llx (dma) %#08x - dev_info2\n", - &slot->dev_info2, - (unsigned long long)dma, slot->dev_info2); + &slot_ctx->dev_info2, + (unsigned long long)dma, slot_ctx->dev_info2); dma += field_size; xhci_dbg(xhci, "@%p (virt) @%08llx (dma) %#08x - tt_info\n", - &slot->tt_info, - (unsigned long long)dma, slot->tt_info); + &slot_ctx->tt_info, + (unsigned long long)dma, slot_ctx->tt_info); dma += field_size; xhci_dbg(xhci, "@%p (virt) @%08llx (dma) %#08x - dev_state\n", - &slot->dev_state, - (unsigned long long)dma, slot->dev_state); + &slot_ctx->dev_state, + (unsigned long long)dma, slot_ctx->dev_state); dma += field_size; for (i = 0; i < 4; ++i) { xhci_dbg(xhci, "@%p (virt) @%08llx (dma) %#08x - rsvd[%d]\n", - &slot->reserved[i], (unsigned long long)dma, - slot->reserved[i], i); + &slot_ctx->reserved[i], (unsigned long long)dma, + slot_ctx->reserved[i], i); dma += field_size; } - return dma; + if (csz) + dbg_rsvd64(xhci, (u64 *)slot_ctx, dma); } -dma_addr_t xhci_dbg_ep_ctx(struct xhci_hcd *xhci, struct xhci_ep_ctx *ep, dma_addr_t dma, unsigned int last_ep) +void xhci_dbg_ep_ctx(struct xhci_hcd *xhci, + struct xhci_container_ctx *ctx, + unsigned int last_ep) { int i, j; int last_ep_ctx = 31; /* Fields are 32 bits wide, DMA addresses are in bytes */ int field_size = 32 / 8; + int csz = HCC_64BYTE_CONTEXT(xhci->hcc_params); if (last_ep < 31) last_ep_ctx = last_ep + 1; for (i = 0; i < last_ep_ctx; ++i) { + struct xhci_ep_ctx *ep_ctx = xhci_get_ep_ctx(xhci, ctx, i); + dma_addr_t dma = ctx->dma + + ((unsigned long)ep_ctx - (unsigned long)ctx); + xhci_dbg(xhci, "Endpoint %02d Context:\n", i); xhci_dbg(xhci, "@%p (virt) @%08llx (dma) %#08x - ep_info\n", - &ep[i].ep_info, - (unsigned long long)dma, ep[i].ep_info); + &ep_ctx->ep_info, + (unsigned long long)dma, ep_ctx->ep_info); dma += field_size; xhci_dbg(xhci, "@%p (virt) @%08llx (dma) %#08x - ep_info2\n", - &ep[i].ep_info2, - (unsigned long long)dma, ep[i].ep_info2); + &ep_ctx->ep_info2, + (unsigned long long)dma, ep_ctx->ep_info2); dma += field_size; xhci_dbg(xhci, "@%p (virt) @%08llx (dma) %#08llx - deq\n", - &ep[i].deq, - (unsigned long long)dma, ep[i].deq); + &ep_ctx->deq, + (unsigned long long)dma, ep_ctx->deq); dma += 2*field_size; xhci_dbg(xhci, "@%p (virt) @%08llx (dma) %#08x - tx_info\n", - &ep[i].tx_info, - (unsigned long long)dma, ep[i].tx_info); + &ep_ctx->tx_info, + (unsigned long long)dma, ep_ctx->tx_info); dma += field_size; for (j = 0; j < 3; ++j) { xhci_dbg(xhci, "@%p (virt) @%08llx (dma) %#08x - rsvd[%d]\n", - &ep[i].reserved[j], + &ep_ctx->reserved[j], (unsigned long long)dma, - ep[i].reserved[j], j); + ep_ctx->reserved[j], j); dma += field_size; } + + if (csz) + dbg_rsvd64(xhci, (u64 *)ep_ctx, dma); } - return dma; } -void xhci_dbg_ctx(struct xhci_hcd *xhci, struct xhci_device_control *ctx, dma_addr_t dma, unsigned int last_ep) +void xhci_dbg_ctx(struct xhci_hcd *xhci, + struct xhci_container_ctx *ctx, + unsigned int last_ep) { int i; /* Fields are 32 bits wide, DMA addresses are in bytes */ int field_size = 32 / 8; - - xhci_dbg(xhci, "@%p (virt) @%08llx (dma) %#08x - drop flags\n", - &ctx->drop_flags, (unsigned long long)dma, - ctx->drop_flags); - dma += field_size; - xhci_dbg(xhci, "@%p (virt) @%08llx (dma) %#08x - add flags\n", - &ctx->add_flags, (unsigned long long)dma, - ctx->add_flags); - dma += field_size; - for (i = 0; i < 6; ++i) { - xhci_dbg(xhci, "@%p (virt) @%08llx (dma) %#08x - rsvd[%d]\n", - &ctx->rsvd[i], (unsigned long long)dma, - ctx->rsvd[i], i); + struct xhci_slot_ctx *slot_ctx; + dma_addr_t dma = ctx->dma; + int csz = HCC_64BYTE_CONTEXT(xhci->hcc_params); + + if (ctx->type == XHCI_CTX_TYPE_INPUT) { + struct xhci_input_control_ctx *ctrl_ctx = + xhci_get_input_control_ctx(xhci, ctx); + xhci_dbg(xhci, "@%p (virt) @%08llx (dma) %#08x - drop flags\n", + &ctrl_ctx->drop_flags, (unsigned long long)dma, + ctrl_ctx->drop_flags); dma += field_size; + xhci_dbg(xhci, "@%p (virt) @%08llx (dma) %#08x - add flags\n", + &ctrl_ctx->add_flags, (unsigned long long)dma, + ctrl_ctx->add_flags); + dma += field_size; + for (i = 0; i < 6; ++i) { + xhci_dbg(xhci, "@%p (virt) @%08llx (dma) %#08x - rsvd2[%d]\n", + &ctrl_ctx->rsvd2[i], (unsigned long long)dma, + ctrl_ctx->rsvd2[i], i); + dma += field_size; + } + + if (csz) + dbg_rsvd64(xhci, (u64 *)ctrl_ctx, dma); } - dma = xhci_dbg_slot_ctx(xhci, &ctx->slot, dma); - dma = xhci_dbg_ep_ctx(xhci, ctx->ep, dma, last_ep); -} -void xhci_dbg_device_ctx(struct xhci_hcd *xhci, struct xhci_device_ctx *ctx, dma_addr_t dma, unsigned int last_ep) -{ - dma = xhci_dbg_slot_ctx(xhci, &ctx->slot, dma); - dma = xhci_dbg_ep_ctx(xhci, ctx->ep, dma, last_ep); + slot_ctx = xhci_get_slot_ctx(xhci, ctx); + xhci_dbg_slot_ctx(xhci, ctx); + xhci_dbg_ep_ctx(xhci, ctx, last_ep); } diff --git a/drivers/usb/host/xhci-hcd.c b/drivers/usb/host/xhci-hcd.c index 921dd173d793..057a07e876be 100644 --- a/drivers/usb/host/xhci-hcd.c +++ b/drivers/usb/host/xhci-hcd.c @@ -722,7 +722,9 @@ int xhci_drop_endpoint(struct usb_hcd *hcd, struct usb_device *udev, struct usb_host_endpoint *ep) { struct xhci_hcd *xhci; - struct xhci_device_control *in_ctx; + struct xhci_container_ctx *in_ctx, *out_ctx; + struct xhci_input_control_ctx *ctrl_ctx; + struct xhci_slot_ctx *slot_ctx; unsigned int last_ctx; unsigned int ep_index; struct xhci_ep_ctx *ep_ctx; @@ -750,31 +752,34 @@ int xhci_drop_endpoint(struct usb_hcd *hcd, struct usb_device *udev, } in_ctx = xhci->devs[udev->slot_id]->in_ctx; + out_ctx = xhci->devs[udev->slot_id]->out_ctx; + ctrl_ctx = xhci_get_input_control_ctx(xhci, in_ctx); ep_index = xhci_get_endpoint_index(&ep->desc); - ep_ctx = &xhci->devs[udev->slot_id]->out_ctx->ep[ep_index]; + ep_ctx = xhci_get_ep_ctx(xhci, out_ctx, ep_index); /* If the HC already knows the endpoint is disabled, * or the HCD has noted it is disabled, ignore this request */ if ((ep_ctx->ep_info & EP_STATE_MASK) == EP_STATE_DISABLED || - in_ctx->drop_flags & xhci_get_endpoint_flag(&ep->desc)) { + ctrl_ctx->drop_flags & xhci_get_endpoint_flag(&ep->desc)) { xhci_warn(xhci, "xHCI %s called with disabled ep %p\n", __func__, ep); return 0; } - in_ctx->drop_flags |= drop_flag; - new_drop_flags = in_ctx->drop_flags; + ctrl_ctx->drop_flags |= drop_flag; + new_drop_flags = ctrl_ctx->drop_flags; - in_ctx->add_flags = ~drop_flag; - new_add_flags = in_ctx->add_flags; + ctrl_ctx->add_flags = ~drop_flag; + new_add_flags = ctrl_ctx->add_flags; - last_ctx = xhci_last_valid_endpoint(in_ctx->add_flags); + last_ctx = xhci_last_valid_endpoint(ctrl_ctx->add_flags); + slot_ctx = xhci_get_slot_ctx(xhci, in_ctx); /* Update the last valid endpoint context, if we deleted the last one */ - if ((in_ctx->slot.dev_info & LAST_CTX_MASK) > LAST_CTX(last_ctx)) { - in_ctx->slot.dev_info &= ~LAST_CTX_MASK; - in_ctx->slot.dev_info |= LAST_CTX(last_ctx); + if ((slot_ctx->dev_info & LAST_CTX_MASK) > LAST_CTX(last_ctx)) { + slot_ctx->dev_info &= ~LAST_CTX_MASK; + slot_ctx->dev_info |= LAST_CTX(last_ctx); } - new_slot_info = in_ctx->slot.dev_info; + new_slot_info = slot_ctx->dev_info; xhci_endpoint_zero(xhci, xhci->devs[udev->slot_id], ep); @@ -804,9 +809,11 @@ int xhci_add_endpoint(struct usb_hcd *hcd, struct usb_device *udev, struct usb_host_endpoint *ep) { struct xhci_hcd *xhci; - struct xhci_device_control *in_ctx; + struct xhci_container_ctx *in_ctx, *out_ctx; unsigned int ep_index; struct xhci_ep_ctx *ep_ctx; + struct xhci_slot_ctx *slot_ctx; + struct xhci_input_control_ctx *ctrl_ctx; u32 added_ctxs; unsigned int last_ctx; u32 new_add_flags, new_drop_flags, new_slot_info; @@ -839,12 +846,14 @@ int xhci_add_endpoint(struct usb_hcd *hcd, struct usb_device *udev, } in_ctx = xhci->devs[udev->slot_id]->in_ctx; + out_ctx = xhci->devs[udev->slot_id]->out_ctx; + ctrl_ctx = xhci_get_input_control_ctx(xhci, in_ctx); ep_index = xhci_get_endpoint_index(&ep->desc); - ep_ctx = &xhci->devs[udev->slot_id]->out_ctx->ep[ep_index]; + ep_ctx = xhci_get_ep_ctx(xhci, out_ctx, ep_index); /* If the HCD has already noted the endpoint is enabled, * ignore this request. */ - if (in_ctx->add_flags & xhci_get_endpoint_flag(&ep->desc)) { + if (ctrl_ctx->add_flags & xhci_get_endpoint_flag(&ep->desc)) { xhci_warn(xhci, "xHCI %s called with enabled ep %p\n", __func__, ep); return 0; @@ -862,8 +871,8 @@ int xhci_add_endpoint(struct usb_hcd *hcd, struct usb_device *udev, return -ENOMEM; } - in_ctx->add_flags |= added_ctxs; - new_add_flags = in_ctx->add_flags; + ctrl_ctx->add_flags |= added_ctxs; + new_add_flags = ctrl_ctx->add_flags; /* If xhci_endpoint_disable() was called for this endpoint, but the * xHC hasn't been notified yet through the check_bandwidth() call, @@ -871,14 +880,15 @@ int xhci_add_endpoint(struct usb_hcd *hcd, struct usb_device *udev, * descriptors. We must drop and re-add this endpoint, so we leave the * drop flags alone. */ - new_drop_flags = in_ctx->drop_flags; + new_drop_flags = ctrl_ctx->drop_flags; + slot_ctx = xhci_get_slot_ctx(xhci, in_ctx); /* Update the last valid endpoint context, if we just added one past */ - if ((in_ctx->slot.dev_info & LAST_CTX_MASK) < LAST_CTX(last_ctx)) { - in_ctx->slot.dev_info &= ~LAST_CTX_MASK; - in_ctx->slot.dev_info |= LAST_CTX(last_ctx); + if ((slot_ctx->dev_info & LAST_CTX_MASK) < LAST_CTX(last_ctx)) { + slot_ctx->dev_info &= ~LAST_CTX_MASK; + slot_ctx->dev_info |= LAST_CTX(last_ctx); } - new_slot_info = in_ctx->slot.dev_info; + new_slot_info = slot_ctx->dev_info; /* Store the usb_device pointer for later use */ ep->hcpriv = udev; @@ -892,9 +902,11 @@ int xhci_add_endpoint(struct usb_hcd *hcd, struct usb_device *udev, return 0; } -static void xhci_zero_in_ctx(struct xhci_virt_device *virt_dev) +static void xhci_zero_in_ctx(struct xhci_hcd *xhci, struct xhci_virt_device *virt_dev) { + struct xhci_input_control_ctx *ctrl_ctx; struct xhci_ep_ctx *ep_ctx; + struct xhci_slot_ctx *slot_ctx; int i; /* When a device's add flag and drop flag are zero, any subsequent @@ -902,13 +914,15 @@ static void xhci_zero_in_ctx(struct xhci_virt_device *virt_dev) * untouched. Make sure we don't leave any old state in the input * endpoint contexts. */ - virt_dev->in_ctx->drop_flags = 0; - virt_dev->in_ctx->add_flags = 0; - virt_dev->in_ctx->slot.dev_info &= ~LAST_CTX_MASK; + ctrl_ctx = xhci_get_input_control_ctx(xhci, virt_dev->in_ctx); + ctrl_ctx->drop_flags = 0; + ctrl_ctx->add_flags = 0; + slot_ctx = xhci_get_slot_ctx(xhci, virt_dev->in_ctx); + slot_ctx->dev_info &= ~LAST_CTX_MASK; /* Endpoint 0 is always valid */ - virt_dev->in_ctx->slot.dev_info |= LAST_CTX(1); + slot_ctx->dev_info |= LAST_CTX(1); for (i = 1; i < 31; ++i) { - ep_ctx = &virt_dev->in_ctx->ep[i]; + ep_ctx = xhci_get_ep_ctx(xhci, virt_dev->in_ctx, i); ep_ctx->ep_info = 0; ep_ctx->ep_info2 = 0; ep_ctx->deq = 0; @@ -934,6 +948,8 @@ int xhci_check_bandwidth(struct usb_hcd *hcd, struct usb_device *udev) unsigned long flags; struct xhci_hcd *xhci; struct xhci_virt_device *virt_dev; + struct xhci_input_control_ctx *ctrl_ctx; + struct xhci_slot_ctx *slot_ctx; ret = xhci_check_args(hcd, udev, NULL, 0, __func__); if (ret <= 0) @@ -949,16 +965,18 @@ int xhci_check_bandwidth(struct usb_hcd *hcd, struct usb_device *udev) virt_dev = xhci->devs[udev->slot_id]; /* See section 4.6.6 - A0 = 1; A1 = D0 = D1 = 0 */ - virt_dev->in_ctx->add_flags |= SLOT_FLAG; - virt_dev->in_ctx->add_flags &= ~EP0_FLAG; - virt_dev->in_ctx->drop_flags &= ~SLOT_FLAG; - virt_dev->in_ctx->drop_flags &= ~EP0_FLAG; + ctrl_ctx = xhci_get_input_control_ctx(xhci, virt_dev->in_ctx); + ctrl_ctx->add_flags |= SLOT_FLAG; + ctrl_ctx->add_flags &= ~EP0_FLAG; + ctrl_ctx->drop_flags &= ~SLOT_FLAG; + ctrl_ctx->drop_flags &= ~EP0_FLAG; xhci_dbg(xhci, "New Input Control Context:\n"); - xhci_dbg_ctx(xhci, virt_dev->in_ctx, virt_dev->in_ctx_dma, - LAST_CTX_TO_EP_NUM(virt_dev->in_ctx->slot.dev_info)); + slot_ctx = xhci_get_slot_ctx(xhci, virt_dev->in_ctx); + xhci_dbg_ctx(xhci, virt_dev->in_ctx, + LAST_CTX_TO_EP_NUM(slot_ctx->dev_info)); spin_lock_irqsave(&xhci->lock, flags); - ret = xhci_queue_configure_endpoint(xhci, virt_dev->in_ctx_dma, + ret = xhci_queue_configure_endpoint(xhci, virt_dev->in_ctx->dma, udev->slot_id); if (ret < 0) { spin_unlock_irqrestore(&xhci->lock, flags); @@ -1013,10 +1031,10 @@ int xhci_check_bandwidth(struct usb_hcd *hcd, struct usb_device *udev) } xhci_dbg(xhci, "Output context after successful config ep cmd:\n"); - xhci_dbg_device_ctx(xhci, virt_dev->out_ctx, virt_dev->out_ctx_dma, - LAST_CTX_TO_EP_NUM(virt_dev->in_ctx->slot.dev_info)); + xhci_dbg_ctx(xhci, virt_dev->out_ctx, + LAST_CTX_TO_EP_NUM(slot_ctx->dev_info)); - xhci_zero_in_ctx(virt_dev); + xhci_zero_in_ctx(xhci, virt_dev); /* Free any old rings */ for (i = 1; i < 31; ++i) { if (virt_dev->new_ep_rings[i]) { @@ -1054,7 +1072,7 @@ void xhci_reset_bandwidth(struct usb_hcd *hcd, struct usb_device *udev) virt_dev->new_ep_rings[i] = NULL; } } - xhci_zero_in_ctx(virt_dev); + xhci_zero_in_ctx(xhci, virt_dev); } /* Deal with stalled endpoints. The core should have sent the control message @@ -1187,6 +1205,8 @@ int xhci_address_device(struct usb_hcd *hcd, struct usb_device *udev) struct xhci_virt_device *virt_dev; int ret = 0; struct xhci_hcd *xhci = hcd_to_xhci(hcd); + struct xhci_slot_ctx *slot_ctx; + struct xhci_input_control_ctx *ctrl_ctx; u64 temp_64; if (!udev->slot_id) { @@ -1201,11 +1221,11 @@ int xhci_address_device(struct usb_hcd *hcd, struct usb_device *udev) xhci_setup_addressable_virt_dev(xhci, udev); /* Otherwise, assume the core has the device configured how it wants */ xhci_dbg(xhci, "Slot ID %d Input Context:\n", udev->slot_id); - xhci_dbg_ctx(xhci, virt_dev->in_ctx, virt_dev->in_ctx_dma, 2); + xhci_dbg_ctx(xhci, virt_dev->in_ctx, 2); spin_lock_irqsave(&xhci->lock, flags); - ret = xhci_queue_address_device(xhci, virt_dev->in_ctx_dma, - udev->slot_id); + ret = xhci_queue_address_device(xhci, virt_dev->in_ctx->dma, + udev->slot_id); if (ret) { spin_unlock_irqrestore(&xhci->lock, flags); xhci_dbg(xhci, "FIXME: allocate a command ring segment\n"); @@ -1246,7 +1266,7 @@ int xhci_address_device(struct usb_hcd *hcd, struct usb_device *udev) xhci_err(xhci, "ERROR: unexpected command completion " "code 0x%x.\n", virt_dev->cmd_status); xhci_dbg(xhci, "Slot ID %d Output Context:\n", udev->slot_id); - xhci_dbg_ctx(xhci, virt_dev->out_ctx, virt_dev->out_ctx_dma, 2); + xhci_dbg_ctx(xhci, virt_dev->out_ctx, 2); ret = -EINVAL; break; } @@ -1261,19 +1281,21 @@ int xhci_address_device(struct usb_hcd *hcd, struct usb_device *udev) (unsigned long long) xhci->dcbaa->dev_context_ptrs[udev->slot_id]); xhci_dbg(xhci, "Output Context DMA address = %#08llx\n", - (unsigned long long)virt_dev->out_ctx_dma); + (unsigned long long)virt_dev->out_ctx->dma); xhci_dbg(xhci, "Slot ID %d Input Context:\n", udev->slot_id); - xhci_dbg_ctx(xhci, virt_dev->in_ctx, virt_dev->in_ctx_dma, 2); + xhci_dbg_ctx(xhci, virt_dev->in_ctx, 2); xhci_dbg(xhci, "Slot ID %d Output Context:\n", udev->slot_id); - xhci_dbg_device_ctx(xhci, virt_dev->out_ctx, virt_dev->out_ctx_dma, 2); + xhci_dbg_ctx(xhci, virt_dev->out_ctx, 2); /* * USB core uses address 1 for the roothubs, so we add one to the * address given back to us by the HC. */ - udev->devnum = (virt_dev->out_ctx->slot.dev_state & DEV_ADDR_MASK) + 1; + slot_ctx = xhci_get_slot_ctx(xhci, virt_dev->out_ctx); + udev->devnum = (slot_ctx->dev_state & DEV_ADDR_MASK) + 1; /* Zero the input context control for later use */ - virt_dev->in_ctx->add_flags = 0; - virt_dev->in_ctx->drop_flags = 0; + ctrl_ctx = xhci_get_input_control_ctx(xhci, virt_dev->in_ctx); + ctrl_ctx->add_flags = 0; + ctrl_ctx->drop_flags = 0; xhci_dbg(xhci, "Device address = %d\n", udev->devnum); /* XXX Meh, not sure if anyone else but choose_address uses this. */ @@ -1315,7 +1337,6 @@ static int __init xhci_hcd_init(void) /* xhci_device_control has eight fields, and also * embeds one xhci_slot_ctx and 31 xhci_ep_ctx */ - BUILD_BUG_ON(sizeof(struct xhci_device_control) != (8+8+8*31)*32/8); BUILD_BUG_ON(sizeof(struct xhci_stream_ctx) != 4*32/8); BUILD_BUG_ON(sizeof(union xhci_trb) != 4*32/8); BUILD_BUG_ON(sizeof(struct xhci_erst_entry) != 4*32/8); diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c index 8d6bdf2f8015..e6b9a1c6002d 100644 --- a/drivers/usb/host/xhci-mem.c +++ b/drivers/usb/host/xhci-mem.c @@ -189,6 +189,63 @@ fail: return 0; } +#define CTX_SIZE(_hcc) (HCC_64BYTE_CONTEXT(_hcc) ? 64 : 32) + +struct xhci_container_ctx *xhci_alloc_container_ctx(struct xhci_hcd *xhci, + int type, gfp_t flags) +{ + struct xhci_container_ctx *ctx = kzalloc(sizeof(*ctx), flags); + if (!ctx) + return NULL; + + BUG_ON((type != XHCI_CTX_TYPE_DEVICE) && (type != XHCI_CTX_TYPE_INPUT)); + ctx->type = type; + ctx->size = HCC_64BYTE_CONTEXT(xhci->hcc_params) ? 2048 : 1024; + if (type == XHCI_CTX_TYPE_INPUT) + ctx->size += CTX_SIZE(xhci->hcc_params); + + ctx->bytes = dma_pool_alloc(xhci->device_pool, flags, &ctx->dma); + memset(ctx->bytes, 0, ctx->size); + return ctx; +} + +void xhci_free_container_ctx(struct xhci_hcd *xhci, + struct xhci_container_ctx *ctx) +{ + dma_pool_free(xhci->device_pool, ctx->bytes, ctx->dma); + kfree(ctx); +} + +struct xhci_input_control_ctx *xhci_get_input_control_ctx(struct xhci_hcd *xhci, + struct xhci_container_ctx *ctx) +{ + BUG_ON(ctx->type != XHCI_CTX_TYPE_INPUT); + return (struct xhci_input_control_ctx *)ctx->bytes; +} + +struct xhci_slot_ctx *xhci_get_slot_ctx(struct xhci_hcd *xhci, + struct xhci_container_ctx *ctx) +{ + if (ctx->type == XHCI_CTX_TYPE_DEVICE) + return (struct xhci_slot_ctx *)ctx->bytes; + + return (struct xhci_slot_ctx *) + (ctx->bytes + CTX_SIZE(xhci->hcc_params)); +} + +struct xhci_ep_ctx *xhci_get_ep_ctx(struct xhci_hcd *xhci, + struct xhci_container_ctx *ctx, + unsigned int ep_index) +{ + /* increment ep index by offset of start of ep ctx array */ + ep_index++; + if (ctx->type == XHCI_CTX_TYPE_INPUT) + ep_index++; + + return (struct xhci_ep_ctx *) + (ctx->bytes + (ep_index * CTX_SIZE(xhci->hcc_params))); +} + /* All the xhci_tds in the ring's TD list should be freed at this point */ void xhci_free_virt_device(struct xhci_hcd *xhci, int slot_id) { @@ -209,11 +266,10 @@ void xhci_free_virt_device(struct xhci_hcd *xhci, int slot_id) xhci_ring_free(xhci, dev->ep_rings[i]); if (dev->in_ctx) - dma_pool_free(xhci->device_pool, - dev->in_ctx, dev->in_ctx_dma); + xhci_free_container_ctx(xhci, dev->in_ctx); if (dev->out_ctx) - dma_pool_free(xhci->device_pool, - dev->out_ctx, dev->out_ctx_dma); + xhci_free_container_ctx(xhci, dev->out_ctx); + kfree(xhci->devs[slot_id]); xhci->devs[slot_id] = 0; } @@ -221,7 +277,6 @@ void xhci_free_virt_device(struct xhci_hcd *xhci, int slot_id) int xhci_alloc_virt_device(struct xhci_hcd *xhci, int slot_id, struct usb_device *udev, gfp_t flags) { - dma_addr_t dma; struct xhci_virt_device *dev; /* Slot ID 0 is reserved */ @@ -235,26 +290,21 @@ int xhci_alloc_virt_device(struct xhci_hcd *xhci, int slot_id, return 0; dev = xhci->devs[slot_id]; - /* Allocate the (output) device context that will be used in the HC. - * The structure is 32 bytes smaller than the input context, but that's - * fine. - */ - dev->out_ctx = dma_pool_alloc(xhci->device_pool, flags, &dma); + /* Allocate the (output) device context that will be used in the HC. */ + dev->out_ctx = xhci_alloc_container_ctx(xhci, XHCI_CTX_TYPE_DEVICE, flags); if (!dev->out_ctx) goto fail; - dev->out_ctx_dma = dma; + xhci_dbg(xhci, "Slot %d output ctx = 0x%llx (dma)\n", slot_id, - (unsigned long long)dma); - memset(dev->out_ctx, 0, sizeof(*dev->out_ctx)); + (unsigned long long)dev->out_ctx->dma); /* Allocate the (input) device context for address device command */ - dev->in_ctx = dma_pool_alloc(xhci->device_pool, flags, &dma); + dev->in_ctx = xhci_alloc_container_ctx(xhci, XHCI_CTX_TYPE_INPUT, flags); if (!dev->in_ctx) goto fail; - dev->in_ctx_dma = dma; + xhci_dbg(xhci, "Slot %d input ctx = 0x%llx (dma)\n", slot_id, - (unsigned long long)dma); - memset(dev->in_ctx, 0, sizeof(*dev->in_ctx)); + (unsigned long long)dev->in_ctx->dma); /* Allocate endpoint 0 ring */ dev->ep_rings[0] = xhci_ring_alloc(xhci, 1, true, flags); @@ -264,7 +314,7 @@ int xhci_alloc_virt_device(struct xhci_hcd *xhci, int slot_id, init_completion(&dev->cmd_completion); /* Point to output device context in dcbaa. */ - xhci->dcbaa->dev_context_ptrs[slot_id] = dev->out_ctx_dma; + xhci->dcbaa->dev_context_ptrs[slot_id] = dev->out_ctx->dma; xhci_dbg(xhci, "Set slot id %d dcbaa entry %p to 0x%llx\n", slot_id, &xhci->dcbaa->dev_context_ptrs[slot_id], @@ -282,6 +332,8 @@ int xhci_setup_addressable_virt_dev(struct xhci_hcd *xhci, struct usb_device *ud struct xhci_virt_device *dev; struct xhci_ep_ctx *ep0_ctx; struct usb_device *top_dev; + struct xhci_slot_ctx *slot_ctx; + struct xhci_input_control_ctx *ctrl_ctx; dev = xhci->devs[udev->slot_id]; /* Slot ID 0 is reserved */ @@ -290,27 +342,29 @@ int xhci_setup_addressable_virt_dev(struct xhci_hcd *xhci, struct usb_device *ud udev->slot_id); return -EINVAL; } - ep0_ctx = &dev->in_ctx->ep[0]; + ep0_ctx = xhci_get_ep_ctx(xhci, dev->in_ctx, 0); + ctrl_ctx = xhci_get_input_control_ctx(xhci, dev->in_ctx); + slot_ctx = xhci_get_slot_ctx(xhci, dev->in_ctx); /* 2) New slot context and endpoint 0 context are valid*/ - dev->in_ctx->add_flags = SLOT_FLAG | EP0_FLAG; + ctrl_ctx->add_flags = SLOT_FLAG | EP0_FLAG; /* 3) Only the control endpoint is valid - one endpoint context */ - dev->in_ctx->slot.dev_info |= LAST_CTX(1); + slot_ctx->dev_info |= LAST_CTX(1); switch (udev->speed) { case USB_SPEED_SUPER: - dev->in_ctx->slot.dev_info |= (u32) udev->route; - dev->in_ctx->slot.dev_info |= (u32) SLOT_SPEED_SS; + slot_ctx->dev_info |= (u32) udev->route; + slot_ctx->dev_info |= (u32) SLOT_SPEED_SS; break; case USB_SPEED_HIGH: - dev->in_ctx->slot.dev_info |= (u32) SLOT_SPEED_HS; + slot_ctx->dev_info |= (u32) SLOT_SPEED_HS; break; case USB_SPEED_FULL: - dev->in_ctx->slot.dev_info |= (u32) SLOT_SPEED_FS; + slot_ctx->dev_info |= (u32) SLOT_SPEED_FS; break; case USB_SPEED_LOW: - dev->in_ctx->slot.dev_info |= (u32) SLOT_SPEED_LS; + slot_ctx->dev_info |= (u32) SLOT_SPEED_LS; break; case USB_SPEED_VARIABLE: xhci_dbg(xhci, "FIXME xHCI doesn't support wireless speeds\n"); @@ -324,7 +378,7 @@ int xhci_setup_addressable_virt_dev(struct xhci_hcd *xhci, struct usb_device *ud for (top_dev = udev; top_dev->parent && top_dev->parent->parent; top_dev = top_dev->parent) /* Found device below root hub */; - dev->in_ctx->slot.dev_info2 |= (u32) ROOT_HUB_PORT(top_dev->portnum); + slot_ctx->dev_info2 |= (u32) ROOT_HUB_PORT(top_dev->portnum); xhci_dbg(xhci, "Set root hub portnum to %d\n", top_dev->portnum); /* Is this a LS/FS device under a HS hub? */ @@ -334,8 +388,8 @@ int xhci_setup_addressable_virt_dev(struct xhci_hcd *xhci, struct usb_device *ud */ if ((udev->speed == USB_SPEED_LOW || udev->speed == USB_SPEED_FULL) && udev->tt) { - dev->in_ctx->slot.tt_info = udev->tt->hub->slot_id; - dev->in_ctx->slot.tt_info |= udev->ttport << 8; + slot_ctx->tt_info = udev->tt->hub->slot_id; + slot_ctx->tt_info |= udev->ttport << 8; } xhci_dbg(xhci, "udev->tt = %p\n", udev->tt); xhci_dbg(xhci, "udev->ttport = 0x%x\n", udev->ttport); @@ -466,7 +520,7 @@ int xhci_endpoint_init(struct xhci_hcd *xhci, unsigned int max_burst; ep_index = xhci_get_endpoint_index(&ep->desc); - ep_ctx = &virt_dev->in_ctx->ep[ep_index]; + ep_ctx = xhci_get_ep_ctx(xhci, virt_dev->in_ctx, ep_index); /* Set up the endpoint ring */ virt_dev->new_ep_rings[ep_index] = xhci_ring_alloc(xhci, 1, true, mem_flags); @@ -533,7 +587,7 @@ void xhci_endpoint_zero(struct xhci_hcd *xhci, struct xhci_ep_ctx *ep_ctx; ep_index = xhci_get_endpoint_index(&ep->desc); - ep_ctx = &virt_dev->in_ctx->ep[ep_index]; + ep_ctx = xhci_get_ep_ctx(xhci, virt_dev->in_ctx, ep_index); ep_ctx->ep_info = 0; ep_ctx->ep_info2 = 0; @@ -753,11 +807,10 @@ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags) */ xhci->segment_pool = dma_pool_create("xHCI ring segments", dev, SEGMENT_SIZE, 64, xhci->page_size); + /* See Table 46 and Note on Figure 55 */ - /* FIXME support 64-byte contexts */ xhci->device_pool = dma_pool_create("xHCI input/output contexts", dev, - sizeof(struct xhci_device_control), - 64, xhci->page_size); + 2112, 64, xhci->page_size); if (!xhci->segment_pool || !xhci->device_pool) goto fail; diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c index 0903e98989ec..ea31753c3137 100644 --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c @@ -362,6 +362,7 @@ static void find_new_dequeue_state(struct xhci_hcd *xhci, struct xhci_virt_device *dev = xhci->devs[slot_id]; struct xhci_ring *ep_ring = dev->ep_rings[ep_index]; struct xhci_generic_trb *trb; + struct xhci_ep_ctx *ep_ctx; state->new_cycle_state = 0; state->new_deq_seg = find_trb_seg(cur_td->start_seg, @@ -370,7 +371,8 @@ static void find_new_dequeue_state(struct xhci_hcd *xhci, if (!state->new_deq_seg) BUG(); /* Dig out the cycle state saved by the xHC during the stop ep cmd */ - state->new_cycle_state = 0x1 & dev->out_ctx->ep[ep_index].deq; + ep_ctx = xhci_get_ep_ctx(xhci, dev->out_ctx, ep_index); + state->new_cycle_state = 0x1 & ep_ctx->deq; state->new_deq_ptr = cur_td->last_trb; state->new_deq_seg = find_trb_seg(state->new_deq_seg, @@ -570,11 +572,15 @@ static void handle_set_deq_completion(struct xhci_hcd *xhci, unsigned int ep_index; struct xhci_ring *ep_ring; struct xhci_virt_device *dev; + struct xhci_ep_ctx *ep_ctx; + struct xhci_slot_ctx *slot_ctx; slot_id = TRB_TO_SLOT_ID(trb->generic.field[3]); ep_index = TRB_TO_EP_INDEX(trb->generic.field[3]); dev = xhci->devs[slot_id]; ep_ring = dev->ep_rings[ep_index]; + ep_ctx = xhci_get_ep_ctx(xhci, dev->out_ctx, ep_index); + slot_ctx = xhci_get_slot_ctx(xhci, dev->out_ctx); if (GET_COMP_CODE(event->status) != COMP_SUCCESS) { unsigned int ep_state; @@ -588,9 +594,9 @@ static void handle_set_deq_completion(struct xhci_hcd *xhci, case COMP_CTX_STATE: xhci_warn(xhci, "WARN Set TR Deq Ptr cmd failed due " "to incorrect slot or ep state.\n"); - ep_state = dev->out_ctx->ep[ep_index].ep_info; + ep_state = ep_ctx->ep_info; ep_state &= EP_STATE_MASK; - slot_state = dev->out_ctx->slot.dev_state; + slot_state = slot_ctx->dev_state; slot_state = GET_SLOT_STATE(slot_state); xhci_dbg(xhci, "Slot state = %u, EP state = %u\n", slot_state, ep_state); @@ -613,7 +619,7 @@ static void handle_set_deq_completion(struct xhci_hcd *xhci, */ } else { xhci_dbg(xhci, "Successful Set TR Deq Ptr cmd, deq = @%08llx\n", - dev->out_ctx->ep[ep_index].deq); + ep_ctx->deq); } ep_ring->state &= ~SET_DEQ_PENDING; @@ -795,6 +801,7 @@ static int handle_tx_event(struct xhci_hcd *xhci, union xhci_trb *event_trb; struct urb *urb = 0; int status = -EINPROGRESS; + struct xhci_ep_ctx *ep_ctx; xhci_dbg(xhci, "In %s\n", __func__); xdev = xhci->devs[TRB_TO_SLOT_ID(event->flags)]; @@ -807,7 +814,8 @@ static int handle_tx_event(struct xhci_hcd *xhci, ep_index = TRB_TO_EP_ID(event->flags) - 1; xhci_dbg(xhci, "%s - ep index = %d\n", __func__, ep_index); ep_ring = xdev->ep_rings[ep_index]; - if (!ep_ring || (xdev->out_ctx->ep[ep_index].ep_info & EP_STATE_MASK) == EP_STATE_DISABLED) { + ep_ctx = xhci_get_ep_ctx(xhci, xdev->out_ctx, ep_index); + if (!ep_ring || (ep_ctx->ep_info & EP_STATE_MASK) == EP_STATE_DISABLED) { xhci_err(xhci, "ERROR Transfer event pointed to disabled endpoint\n"); return -ENODEV; } @@ -1193,9 +1201,9 @@ static int prepare_transfer(struct xhci_hcd *xhci, gfp_t mem_flags) { int ret; - + struct xhci_ep_ctx *ep_ctx = xhci_get_ep_ctx(xhci, xdev->out_ctx, ep_index); ret = prepare_ring(xhci, xdev->ep_rings[ep_index], - xdev->out_ctx->ep[ep_index].ep_info & EP_STATE_MASK, + ep_ctx->ep_info & EP_STATE_MASK, num_trbs, mem_flags); if (ret) return ret; diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h index d4d3c7777fb8..9c108c632704 100644 --- a/drivers/usb/host/xhci.h +++ b/drivers/usb/host/xhci.h @@ -446,6 +446,27 @@ struct xhci_doorbell_array { #define EPI_TO_DB(p) (((p) + 1) & 0xff) +/** + * struct xhci_container_ctx + * @type: Type of context. Used to calculated offsets to contained contexts. + * @size: Size of the context data + * @bytes: The raw context data given to HW + * @dma: dma address of the bytes + * + * Represents either a Device or Input context. Holds a pointer to the raw + * memory used for the context (bytes) and dma address of it (dma). + */ +struct xhci_container_ctx { + unsigned type; +#define XHCI_CTX_TYPE_DEVICE 0x1 +#define XHCI_CTX_TYPE_INPUT 0x2 + + int size; + + u8 *bytes; + dma_addr_t dma; +}; + /** * struct xhci_slot_ctx * @dev_info: Route string, device speed, hub info, and last valid endpoint @@ -583,32 +604,16 @@ struct xhci_ep_ctx { /** - * struct xhci_device_control - * Input context; see section 6.2.5. + * struct xhci_input_control_context + * Input control context; see section 6.2.5. * * @drop_context: set the bit of the endpoint context you want to disable * @add_context: set the bit of the endpoint context you want to enable */ -struct xhci_device_control { - /* Input control context */ +struct xhci_input_control_ctx { u32 drop_flags; u32 add_flags; - u32 rsvd[6]; - /* Copy of device context */ - struct xhci_slot_ctx slot; - struct xhci_ep_ctx ep[31]; -}; - -/** - * struct xhci_device_ctx - * Device context; see section 6.2.1. - * - * @slot: slot context for the device. - * @ep: array of endpoint contexts for the device. - */ -struct xhci_device_ctx { - struct xhci_slot_ctx slot; - struct xhci_ep_ctx ep[31]; + u32 rsvd2[6]; }; /* drop context bitmasks */ @@ -616,7 +621,6 @@ struct xhci_device_ctx { /* add context bitmasks */ #define ADD_EP(x) (0x1 << x) - struct xhci_virt_device { /* * Commands to the hardware are passed an "input context" that @@ -626,11 +630,10 @@ struct xhci_virt_device { * track of input and output contexts separately because * these commands might fail and we don't trust the hardware. */ - struct xhci_device_ctx *out_ctx; - dma_addr_t out_ctx_dma; + struct xhci_container_ctx *out_ctx; /* Used for addressing devices and configuration changes */ - struct xhci_device_control *in_ctx; - dma_addr_t in_ctx_dma; + struct xhci_container_ctx *in_ctx; + /* FIXME when stream support is added */ struct xhci_ring *ep_rings[31]; /* Temporary storage in case the configure endpoint command fails and we @@ -1139,8 +1142,7 @@ void xhci_debug_ring(struct xhci_hcd *xhci, struct xhci_ring *ring); void xhci_dbg_erst(struct xhci_hcd *xhci, struct xhci_erst *erst); void xhci_dbg_cmd_ptrs(struct xhci_hcd *xhci); void xhci_dbg_ring_ptrs(struct xhci_hcd *xhci, struct xhci_ring *ring); -void xhci_dbg_ctx(struct xhci_hcd *xhci, struct xhci_device_control *ctx, dma_addr_t dma, unsigned int last_ep); -void xhci_dbg_device_ctx(struct xhci_hcd *xhci, struct xhci_device_ctx *ctx, dma_addr_t dma, unsigned int last_ep); +void xhci_dbg_ctx(struct xhci_hcd *xhci, struct xhci_container_ctx *ctx, unsigned int last_ep); /* xHCI memory managment */ void xhci_mem_cleanup(struct xhci_hcd *xhci); @@ -1207,4 +1209,9 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, u16 wIndex, char *buf, u16 wLength); int xhci_hub_status_data(struct usb_hcd *hcd, char *buf); +/* xHCI contexts */ +struct xhci_input_control_ctx *xhci_get_input_control_ctx(struct xhci_hcd *xhci, struct xhci_container_ctx *ctx); +struct xhci_slot_ctx *xhci_get_slot_ctx(struct xhci_hcd *xhci, struct xhci_container_ctx *ctx); +struct xhci_ep_ctx *xhci_get_ep_ctx(struct xhci_hcd *xhci, struct xhci_container_ctx *ctx, unsigned int ep_index); + #endif /* __LINUX_XHCI_HCD_H */ -- cgit v1.2.3 From c92bcfa7b4038d8ffe1f02e21269f18eb0b64144 Mon Sep 17 00:00:00 2001 From: Sarah Sharp Date: Mon, 27 Jul 2009 12:05:21 -0700 Subject: USB: xhci: Stall handling bug fixes. Correct the xHCI code to handle stalls on USB endpoints. We need to move the endpoint ring's dequeue pointer past the stalled transfer, or the HW will try to restart the transfer the next time the doorbell is rung. Don't attempt to clear a halt on an endpoint if we haven't seen a stalled transfer for it. The USB core will attempt to clear a halt on all endpoints when it selects a new configuration. Signed-off-by: Sarah Sharp Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/xhci-hcd.c | 24 ++++++++ drivers/usb/host/xhci-ring.c | 133 +++++++++++++++++++++++++++---------------- drivers/usb/host/xhci.h | 12 ++++ 3 files changed, 120 insertions(+), 49 deletions(-) diff --git a/drivers/usb/host/xhci-hcd.c b/drivers/usb/host/xhci-hcd.c index 057a07e876be..816c39caca1c 100644 --- a/drivers/usb/host/xhci-hcd.c +++ b/drivers/usb/host/xhci-hcd.c @@ -1089,6 +1089,8 @@ void xhci_endpoint_reset(struct usb_hcd *hcd, unsigned int ep_index; unsigned long flags; int ret; + struct xhci_dequeue_state deq_state; + struct xhci_ring *ep_ring; xhci = hcd_to_xhci(hcd); udev = (struct usb_device *) ep->hcpriv; @@ -1098,11 +1100,33 @@ void xhci_endpoint_reset(struct usb_hcd *hcd, if (!ep->hcpriv) return; ep_index = xhci_get_endpoint_index(&ep->desc); + ep_ring = xhci->devs[udev->slot_id]->ep_rings[ep_index]; + if (!ep_ring->stopped_td) { + xhci_dbg(xhci, "Endpoint 0x%x not halted, refusing to reset.\n", + ep->desc.bEndpointAddress); + return; + } xhci_dbg(xhci, "Queueing reset endpoint command\n"); spin_lock_irqsave(&xhci->lock, flags); ret = xhci_queue_reset_ep(xhci, udev->slot_id, ep_index); + /* + * Can't change the ring dequeue pointer until it's transitioned to the + * stopped state, which is only upon a successful reset endpoint + * command. Better hope that last command worked! + */ if (!ret) { + xhci_dbg(xhci, "Cleaning up stalled endpoint ring\n"); + /* We need to move the HW's dequeue pointer past this TD, + * or it will attempt to resend it on the next doorbell ring. + */ + xhci_find_new_dequeue_state(xhci, udev->slot_id, + ep_index, ep_ring->stopped_td, &deq_state); + xhci_dbg(xhci, "Queueing new dequeue state\n"); + xhci_queue_new_dequeue_state(xhci, ep_ring, + udev->slot_id, + ep_index, &deq_state); + kfree(ep_ring->stopped_td); xhci_ring_cmd_db(xhci); } spin_unlock_irqrestore(&xhci->lock, flags); diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c index ea31753c3137..aa88a067148b 100644 --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c @@ -335,12 +335,6 @@ static struct xhci_segment *find_trb_seg( return cur_seg; } -struct dequeue_state { - struct xhci_segment *new_deq_seg; - union xhci_trb *new_deq_ptr; - int new_cycle_state; -}; - /* * Move the xHC's endpoint ring dequeue pointer past cur_td. * Record the new state of the xHC's endpoint ring dequeue segment, @@ -355,26 +349,30 @@ struct dequeue_state { * - Finally we move the dequeue state one TRB further, toggling the cycle bit * if we've moved it past a link TRB with the toggle cycle bit set. */ -static void find_new_dequeue_state(struct xhci_hcd *xhci, +void xhci_find_new_dequeue_state(struct xhci_hcd *xhci, unsigned int slot_id, unsigned int ep_index, - struct xhci_td *cur_td, struct dequeue_state *state) + struct xhci_td *cur_td, struct xhci_dequeue_state *state) { struct xhci_virt_device *dev = xhci->devs[slot_id]; struct xhci_ring *ep_ring = dev->ep_rings[ep_index]; struct xhci_generic_trb *trb; struct xhci_ep_ctx *ep_ctx; + dma_addr_t addr; state->new_cycle_state = 0; + xhci_dbg(xhci, "Finding segment containing stopped TRB.\n"); state->new_deq_seg = find_trb_seg(cur_td->start_seg, ep_ring->stopped_trb, &state->new_cycle_state); if (!state->new_deq_seg) BUG(); /* Dig out the cycle state saved by the xHC during the stop ep cmd */ + xhci_dbg(xhci, "Finding endpoint context\n"); ep_ctx = xhci_get_ep_ctx(xhci, dev->out_ctx, ep_index); state->new_cycle_state = 0x1 & ep_ctx->deq; state->new_deq_ptr = cur_td->last_trb; + xhci_dbg(xhci, "Finding segment containing last TRB in TD.\n"); state->new_deq_seg = find_trb_seg(state->new_deq_seg, state->new_deq_ptr, &state->new_cycle_state); @@ -388,6 +386,12 @@ static void find_new_dequeue_state(struct xhci_hcd *xhci, next_trb(xhci, ep_ring, &state->new_deq_seg, &state->new_deq_ptr); /* Don't update the ring cycle state for the producer (us). */ + xhci_dbg(xhci, "New dequeue segment = %p (virtual)\n", + state->new_deq_seg); + addr = xhci_trb_virt_to_dma(state->new_deq_seg, state->new_deq_ptr); + xhci_dbg(xhci, "New dequeue pointer = 0x%llx (DMA)\n", + (unsigned long long) addr); + xhci_dbg(xhci, "Setting dequeue pointer in internal ring state.\n"); ep_ring->dequeue = state->new_deq_ptr; ep_ring->deq_seg = state->new_deq_seg; } @@ -437,6 +441,30 @@ static int queue_set_tr_deq(struct xhci_hcd *xhci, int slot_id, unsigned int ep_index, struct xhci_segment *deq_seg, union xhci_trb *deq_ptr, u32 cycle_state); +void xhci_queue_new_dequeue_state(struct xhci_hcd *xhci, + struct xhci_ring *ep_ring, unsigned int slot_id, + unsigned int ep_index, struct xhci_dequeue_state *deq_state) +{ + xhci_dbg(xhci, "Set TR Deq Ptr cmd, new deq seg = %p (0x%llx dma), " + "new deq ptr = %p (0x%llx dma), new cycle = %u\n", + deq_state->new_deq_seg, + (unsigned long long)deq_state->new_deq_seg->dma, + deq_state->new_deq_ptr, + (unsigned long long)xhci_trb_virt_to_dma(deq_state->new_deq_seg, deq_state->new_deq_ptr), + deq_state->new_cycle_state); + queue_set_tr_deq(xhci, slot_id, ep_index, + deq_state->new_deq_seg, + deq_state->new_deq_ptr, + (u32) deq_state->new_cycle_state); + /* Stop the TD queueing code from ringing the doorbell until + * this command completes. The HC won't set the dequeue pointer + * if the ring is running, and ringing the doorbell starts the + * ring running. + */ + ep_ring->state |= SET_DEQ_PENDING; + xhci_ring_cmd_db(xhci); +} + /* * When we get a command completion for a Stop Endpoint Command, we need to * unlink any cancelled TDs from the ring. There are two ways to do that: @@ -457,7 +485,7 @@ static void handle_stopped_endpoint(struct xhci_hcd *xhci, struct xhci_td *cur_td = 0; struct xhci_td *last_unlinked_td; - struct dequeue_state deq_state; + struct xhci_dequeue_state deq_state; #ifdef CONFIG_USB_HCD_STAT ktime_t stop_time = ktime_get(); #endif @@ -485,7 +513,7 @@ static void handle_stopped_endpoint(struct xhci_hcd *xhci, * move the xHC endpoint ring dequeue pointer past this TD. */ if (cur_td == ep_ring->stopped_td) - find_new_dequeue_state(xhci, slot_id, ep_index, cur_td, + xhci_find_new_dequeue_state(xhci, slot_id, ep_index, cur_td, &deq_state); else td_to_noop(xhci, ep_ring, cur_td); @@ -501,24 +529,8 @@ static void handle_stopped_endpoint(struct xhci_hcd *xhci, /* If necessary, queue a Set Transfer Ring Dequeue Pointer command */ if (deq_state.new_deq_ptr && deq_state.new_deq_seg) { - xhci_dbg(xhci, "Set TR Deq Ptr cmd, new deq seg = %p (0x%llx dma), " - "new deq ptr = %p (0x%llx dma), new cycle = %u\n", - deq_state.new_deq_seg, - (unsigned long long)deq_state.new_deq_seg->dma, - deq_state.new_deq_ptr, - (unsigned long long)xhci_trb_virt_to_dma(deq_state.new_deq_seg, deq_state.new_deq_ptr), - deq_state.new_cycle_state); - queue_set_tr_deq(xhci, slot_id, ep_index, - deq_state.new_deq_seg, - deq_state.new_deq_ptr, - (u32) deq_state.new_cycle_state); - /* Stop the TD queueing code from ringing the doorbell until - * this command completes. The HC won't set the dequeue pointer - * if the ring is running, and ringing the doorbell starts the - * ring running. - */ - ep_ring->state |= SET_DEQ_PENDING; - xhci_ring_cmd_db(xhci); + xhci_queue_new_dequeue_state(xhci, ep_ring, + slot_id, ep_index, &deq_state); } else { /* Otherwise just ring the doorbell to restart the ring */ ring_ep_doorbell(xhci, slot_id, ep_index); @@ -929,12 +941,15 @@ static int handle_tx_event(struct xhci_hcd *xhci, if (event_trb != ep_ring->dequeue) { /* The event was for the status stage */ if (event_trb == td->last_trb) { - /* Did we already see a short data stage? */ - if (td->urb->actual_length != 0) - status = -EREMOTEIO; - else + if (td->urb->actual_length != 0) { + /* Don't overwrite a previously set error code */ + if (status == -EINPROGRESS || status == 0) + /* Did we already see a short data stage? */ + status = -EREMOTEIO; + } else { td->urb->actual_length = td->urb->transfer_buffer_length; + } } else { /* Maybe the event was for the data stage? */ if (GET_COMP_CODE(event->transfer_len) != COMP_STOP_INVAL) { @@ -992,16 +1007,20 @@ static int handle_tx_event(struct xhci_hcd *xhci, TRB_LEN(event->transfer_len)); td->urb->actual_length = 0; } - if (td->urb->transfer_flags & URB_SHORT_NOT_OK) - status = -EREMOTEIO; - else - status = 0; + /* Don't overwrite a previously set error code */ + if (status == -EINPROGRESS) { + if (td->urb->transfer_flags & URB_SHORT_NOT_OK) + status = -EREMOTEIO; + else + status = 0; + } } else { td->urb->actual_length = td->urb->transfer_buffer_length; /* Ignore a short packet completion if the * untransferred length was zero. */ - status = 0; + if (status == -EREMOTEIO) + status = 0; } } else { /* Slow path - walk the list, starting from the dequeue @@ -1028,19 +1047,30 @@ static int handle_tx_event(struct xhci_hcd *xhci, TRB_LEN(event->transfer_len); } } - /* The Endpoint Stop Command completion will take care of - * any stopped TDs. A stopped TD may be restarted, so don't update the - * ring dequeue pointer or take this TD off any lists yet. - */ if (GET_COMP_CODE(event->transfer_len) == COMP_STOP_INVAL || GET_COMP_CODE(event->transfer_len) == COMP_STOP) { + /* The Endpoint Stop Command completion will take care of any + * stopped TDs. A stopped TD may be restarted, so don't update + * the ring dequeue pointer or take this TD off any lists yet. + */ ep_ring->stopped_td = td; ep_ring->stopped_trb = event_trb; } else { - /* Update ring dequeue pointer */ - while (ep_ring->dequeue != td->last_trb) + if (GET_COMP_CODE(event->transfer_len) == COMP_STALL) { + /* The transfer is completed from the driver's + * perspective, but we need to issue a set dequeue + * command for this stalled endpoint to move the dequeue + * pointer past the TD. We can't do that here because + * the halt condition must be cleared first. + */ + ep_ring->stopped_td = td; + ep_ring->stopped_trb = event_trb; + } else { + /* Update ring dequeue pointer */ + while (ep_ring->dequeue != td->last_trb) + inc_deq(xhci, ep_ring, false); inc_deq(xhci, ep_ring, false); - inc_deq(xhci, ep_ring, false); + } /* Clean up the endpoint's TD list */ urb = td->urb; @@ -1050,7 +1080,10 @@ static int handle_tx_event(struct xhci_hcd *xhci, list_del(&td->cancelled_td_list); ep_ring->cancels_pending--; } - kfree(td); + /* Leave the TD around for the reset endpoint function to use */ + if (GET_COMP_CODE(event->transfer_len) != COMP_STALL) { + kfree(td); + } urb->hcpriv = NULL; } cleanup: @@ -1166,13 +1199,13 @@ static int prepare_ring(struct xhci_hcd *xhci, struct xhci_ring *ep_ring, */ xhci_warn(xhci, "WARN urb submitted to disabled ep\n"); return -ENOENT; - case EP_STATE_HALTED: case EP_STATE_ERROR: - xhci_warn(xhci, "WARN waiting for halt or error on ep " - "to be cleared\n"); + xhci_warn(xhci, "WARN waiting for error on ep to be cleared\n"); /* FIXME event handling code for error needs to clear it */ /* XXX not sure if this should be -ENOENT or not */ return -EINVAL; + case EP_STATE_HALTED: + xhci_dbg(xhci, "WARN halted endpoint, queueing URB anyway.\n"); case EP_STATE_STOPPED: case EP_STATE_RUNNING: break; @@ -1724,10 +1757,12 @@ static int queue_set_tr_deq(struct xhci_hcd *xhci, int slot_id, u32 type = TRB_TYPE(TRB_SET_DEQ); addr = xhci_trb_virt_to_dma(deq_seg, deq_ptr); - if (addr == 0) + if (addr == 0) { xhci_warn(xhci, "WARN Cannot submit Set TR Deq Ptr\n"); xhci_warn(xhci, "WARN deq seg = %p, deq pt = %p\n", deq_seg, deq_ptr); + return 0; + } return queue_command(xhci, lower_32_bits(addr) | cycle_state, upper_32_bits(addr), 0, trb_slot_id | trb_ep_index | type); diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h index 9c108c632704..d31d32206ba3 100644 --- a/drivers/usb/host/xhci.h +++ b/drivers/usb/host/xhci.h @@ -952,6 +952,12 @@ struct xhci_ring { u32 cycle_state; }; +struct xhci_dequeue_state { + struct xhci_segment *new_deq_seg; + union xhci_trb *new_deq_ptr; + int new_cycle_state; +}; + struct xhci_erst_entry { /* 64-bit event ring segment address */ u64 seg_addr; @@ -1203,6 +1209,12 @@ int xhci_queue_configure_endpoint(struct xhci_hcd *xhci, dma_addr_t in_ctx_ptr, u32 slot_id); int xhci_queue_reset_ep(struct xhci_hcd *xhci, int slot_id, unsigned int ep_index); +void xhci_find_new_dequeue_state(struct xhci_hcd *xhci, + unsigned int slot_id, unsigned int ep_index, + struct xhci_td *cur_td, struct xhci_dequeue_state *state); +void xhci_queue_new_dequeue_state(struct xhci_hcd *xhci, + struct xhci_ring *ep_ring, unsigned int slot_id, + unsigned int ep_index, struct xhci_dequeue_state *deq_state); /* xHCI roothub code */ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, u16 wIndex, -- cgit v1.2.3 From 044dcc824a167e3d39ba69a49e2b723dd10678f6 Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Sun, 26 Jul 2009 18:27:29 +0200 Subject: pata_pcmcia: add CNF-CDROM-ID Fixes this report: http://article.gmane.org/gmane.linux.kernel.pcmcia.devel/2228/ Reported-by: John McGrath Signed-off-by: Wolfram Sang Signed-off-by: Jeff Garzik --- drivers/ata/pata_pcmcia.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/ata/pata_pcmcia.c b/drivers/ata/pata_pcmcia.c index f4d009ed50ac..dc99e26f8e5b 100644 --- a/drivers/ata/pata_pcmcia.c +++ b/drivers/ata/pata_pcmcia.c @@ -411,6 +411,7 @@ static struct pcmcia_device_id pcmcia_devices[] = { PCMCIA_DEVICE_PROD_ID123("PCMCIA", "IDE CARD", "F1", 0x281f1c5d, 0x1907960c, 0xf7fde8b9), PCMCIA_DEVICE_PROD_ID12("ARGOSY", "CD-ROM", 0x78f308dc, 0x66536591), PCMCIA_DEVICE_PROD_ID12("ARGOSY", "PnPIDE", 0x78f308dc, 0x0c694728), + PCMCIA_DEVICE_PROD_ID12("CNF ", "CD-ROM", 0x46d7db81, 0x66536591), PCMCIA_DEVICE_PROD_ID12("CNF CD-M", "CD-ROM", 0x7d93b852, 0x66536591), PCMCIA_DEVICE_PROD_ID12("Creative Technology Ltd.", "PCMCIA CD-ROM Interface Card", 0xff8c8a45, 0xfe8020c4), PCMCIA_DEVICE_PROD_ID12("Digital Equipment Corporation.", "Digital Mobile Media CD-ROM", 0x17692a66, 0xef1dcbde), -- cgit v1.2.3 From 705d201414382b0966d7c903d738dfdb9380e4af Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Sun, 26 Jul 2009 16:21:01 +0200 Subject: libata: add missing NULL pointer check to ata_eh_reset() drivers/ata/libata-eh.c +2403 ata_eh_reset(80) warning: variable derefenced before check 'slave' Please note that this is _not_ a real bug at the moment since ata_eh_context structure is embedded into ata_list structure and the code alwas checks for 'slave' before accessing 'sehc'. Anyway lets add missing check and always have a valid 'sehc' pointer (which makes code easier to understand and prevents introducing some possible bugs in the future). Reported-by: Dan Carpenter Cc: corbet@lwn.net Cc: eteo@redhat.com Signed-off-by: Bartlomiej Zolnierkiewicz Signed-off-by: Jeff Garzik --- drivers/ata/libata-eh.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c index 1a07c061f644..79711b64054b 100644 --- a/drivers/ata/libata-eh.c +++ b/drivers/ata/libata-eh.c @@ -2327,7 +2327,7 @@ int ata_eh_reset(struct ata_link *link, int classify, struct ata_port *ap = link->ap; struct ata_link *slave = ap->slave_link; struct ata_eh_context *ehc = &link->eh_context; - struct ata_eh_context *sehc = &slave->eh_context; + struct ata_eh_context *sehc = slave ? &slave->eh_context : NULL; unsigned int *classes = ehc->classes; unsigned int lflags = link->flags; int verbose = !(ehc->i.flags & ATA_EHI_QUIET); -- cgit v1.2.3 From c9abde12d6debe5b97f36fb43cf188c1b9cd477f Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Sun, 26 Jul 2009 16:05:13 +0200 Subject: libata: remove superfluous NULL pointer checks host->ports[] always contain pointers to valid port structures since a "dummy port" structure is used in case if there is no physical port. This patch takes care of two entries from Dan's list: drivers/ata/sata_sil.c +535 sil_interrupt(13) warning: variable derefenced before check 'ap' drivers/ata/sata_mv.c +2517 mv_unexpected_intr(6) warning: variable derefenced before check 'ap' and of another needless NULL pointer check in pata_octeon_cf.c. Reported-by: Dan Carpenter Cc: corbet@lwn.net Cc: eteo@redhat.com Signed-off-by: Bartlomiej Zolnierkiewicz Signed-off-by: Jeff Garzik --- drivers/ata/pata_octeon_cf.c | 3 ++- drivers/ata/sata_mv.c | 2 +- drivers/ata/sata_sil.c | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/ata/pata_octeon_cf.c b/drivers/ata/pata_octeon_cf.c index 8d9343accf3c..abdd19fe990a 100644 --- a/drivers/ata/pata_octeon_cf.c +++ b/drivers/ata/pata_octeon_cf.c @@ -653,7 +653,8 @@ static irqreturn_t octeon_cf_interrupt(int irq, void *dev_instance) ap = host->ports[i]; ocd = ap->dev->platform_data; - if (!ap || (ap->flags & ATA_FLAG_DISABLED)) + + if (ap->flags & ATA_FLAG_DISABLED) continue; ocd = ap->dev->platform_data; diff --git a/drivers/ata/sata_mv.c b/drivers/ata/sata_mv.c index 23714aefb825..c19417e02208 100644 --- a/drivers/ata/sata_mv.c +++ b/drivers/ata/sata_mv.c @@ -2514,7 +2514,7 @@ static void mv_unexpected_intr(struct ata_port *ap, int edma_was_enabled) char *when = "idle"; ata_ehi_clear_desc(ehi); - if (!ap || (ap->flags & ATA_FLAG_DISABLED)) { + if (ap->flags & ATA_FLAG_DISABLED) { when = "disabled"; } else if (edma_was_enabled) { when = "EDMA enabled"; diff --git a/drivers/ata/sata_sil.c b/drivers/ata/sata_sil.c index 030ec079b184..35bd5cc7f285 100644 --- a/drivers/ata/sata_sil.c +++ b/drivers/ata/sata_sil.c @@ -532,7 +532,7 @@ static irqreturn_t sil_interrupt(int irq, void *dev_instance) struct ata_port *ap = host->ports[i]; u32 bmdma2 = readl(mmio_base + sil_port[ap->port_no].bmdma2); - if (unlikely(!ap || ap->flags & ATA_FLAG_DISABLED)) + if (unlikely(ap->flags & ATA_FLAG_DISABLED)) continue; /* turn off SATA_IRQ if not supported */ -- cgit v1.2.3 From c1f57d9b9846e7366c328f916d1a82d03ba4312c Mon Sep 17 00:00:00 2001 From: David Milburn Date: Wed, 22 Jul 2009 15:15:56 -0500 Subject: ahci: add device IDs for Ibex Peak ahci controllers Add device IDS for Ibex Peak SATA AHCI Controllers Signed-off-by: Jaroslav Kysela Signed-off-by: David Milburn Signed-off-by: Jeff Garzik --- drivers/ata/ahci.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c index 336eb1ed73cc..958c1fa41900 100644 --- a/drivers/ata/ahci.c +++ b/drivers/ata/ahci.c @@ -515,10 +515,14 @@ static const struct pci_device_id ahci_pci_tbl[] = { { PCI_VDEVICE(INTEL, 0x3a05), board_ahci }, /* ICH10 */ { PCI_VDEVICE(INTEL, 0x3a22), board_ahci }, /* ICH10 */ { PCI_VDEVICE(INTEL, 0x3a25), board_ahci }, /* ICH10 */ + { PCI_VDEVICE(INTEL, 0x3b22), board_ahci }, /* PCH AHCI */ + { PCI_VDEVICE(INTEL, 0x3b23), board_ahci }, /* PCH AHCI */ { PCI_VDEVICE(INTEL, 0x3b24), board_ahci }, /* PCH RAID */ { PCI_VDEVICE(INTEL, 0x3b25), board_ahci }, /* PCH RAID */ + { PCI_VDEVICE(INTEL, 0x3b29), board_ahci }, /* PCH AHCI */ { PCI_VDEVICE(INTEL, 0x3b2b), board_ahci }, /* PCH RAID */ { PCI_VDEVICE(INTEL, 0x3b2c), board_ahci }, /* PCH RAID */ + { PCI_VDEVICE(INTEL, 0x3b2f), board_ahci }, /* PCH AHCI */ /* JMicron 360/1/3/5/6, match class to avoid IDE function */ { PCI_VENDOR_ID_JMICRON, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, -- cgit v1.2.3 From 6034734d333c1bd01119a5b480b34a507a3adf56 Mon Sep 17 00:00:00 2001 From: Steve Conklin Date: Thu, 16 Jul 2009 16:27:56 -0500 Subject: ata_piix: Add new laptop short cable IDs OriginalAuthor: Michael Frey Signed-off-by: Steve Conklin Signed-off-by: Jeff Garzik --- drivers/ata/ata_piix.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/ata/ata_piix.c b/drivers/ata/ata_piix.c index d0a14cf2bd74..deada1fe6a01 100644 --- a/drivers/ata/ata_piix.c +++ b/drivers/ata/ata_piix.c @@ -596,9 +596,11 @@ static const struct ich_laptop ich_laptop[] = { { 0x27DF, 0x0005, 0x0280 }, /* ICH7 on Acer 5602WLMi */ { 0x27DF, 0x1025, 0x0102 }, /* ICH7 on Acer 5602aWLMi */ { 0x27DF, 0x1025, 0x0110 }, /* ICH7 on Acer 3682WLMi */ + { 0x27DF, 0x1028, 0x02b0 }, /* ICH7 on unknown Dell */ { 0x27DF, 0x1043, 0x1267 }, /* ICH7 on Asus W5F */ { 0x27DF, 0x103C, 0x30A1 }, /* ICH7 on HP Compaq nc2400 */ { 0x27DF, 0x1071, 0xD221 }, /* ICH7 on Hercules EC-900 */ + { 0x27DF, 0x152D, 0x0778 }, /* ICH7 on unknown Intel */ { 0x24CA, 0x1025, 0x0061 }, /* ICH4 on ACER Aspire 2023WLMi */ { 0x24CA, 0x1025, 0x003d }, /* ICH4 on ACER TM290 */ { 0x266F, 0x1025, 0x0066 }, /* ICH6 on ACER Aspire 1694WLMi */ -- cgit v1.2.3 From 760cdb7760be928e85a021552253eb1b39acdf37 Mon Sep 17 00:00:00 2001 From: Steve Conklin Date: Thu, 16 Jul 2009 16:31:10 -0500 Subject: ata_piix: Add new short cable ID OriginalAuthor: Tony Espy Signed-off-by: Steve Conklin Signed-off-by: Jeff Garzik --- drivers/ata/ata_piix.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/ata/ata_piix.c b/drivers/ata/ata_piix.c index deada1fe6a01..56b8a3ff1286 100644 --- a/drivers/ata/ata_piix.c +++ b/drivers/ata/ata_piix.c @@ -599,6 +599,7 @@ static const struct ich_laptop ich_laptop[] = { { 0x27DF, 0x1028, 0x02b0 }, /* ICH7 on unknown Dell */ { 0x27DF, 0x1043, 0x1267 }, /* ICH7 on Asus W5F */ { 0x27DF, 0x103C, 0x30A1 }, /* ICH7 on HP Compaq nc2400 */ + { 0x27DF, 0x103C, 0x361a }, /* ICH7 on unkown HP */ { 0x27DF, 0x1071, 0xD221 }, /* ICH7 on Hercules EC-900 */ { 0x27DF, 0x152D, 0x0778 }, /* ICH7 on unknown Intel */ { 0x24CA, 0x1025, 0x0061 }, /* ICH4 on ACER Aspire 2023WLMi */ -- cgit v1.2.3 From 7d084d96fdf1d791cb171da57efc1ca89d68dd6c Mon Sep 17 00:00:00 2001 From: Sergey Matyukevich Date: Thu, 16 Jul 2009 22:38:55 +0400 Subject: libata: Updates and fixes for pata_at91 driver Please consider the following updates and fixes for pata_at91 driver. * Removed extra headers Here we need only static memory controller properties, which are contained in generic header at91sam9_smc.h. No need to include any specific headers for at91sam9260 SoC. * No harsh BUG_ON for get_clk in set_smc_timing function get_clk is now performed in driver probing function, probing fails if master clock is not available * Fixed uint/ulong mess in calc_mck_cycles function Signed-off-by: Sergey Matyukevich Signed-off-by: Jeff Garzik --- drivers/ata/pata_at91.c | 67 ++++++++++++++++++++++++++----------------------- 1 file changed, 36 insertions(+), 31 deletions(-) diff --git a/drivers/ata/pata_at91.c b/drivers/ata/pata_at91.c index 8561a9f195c1..5702affcb325 100644 --- a/drivers/ata/pata_at91.c +++ b/drivers/ata/pata_at91.c @@ -26,9 +26,7 @@ #include #include -#include #include -#include #include #include @@ -44,65 +42,62 @@ struct at91_ide_info { unsigned long mode; unsigned int cs; + struct clk *mck; + void __iomem *ide_addr; void __iomem *alt_addr; }; -const struct ata_timing initial_timing = +static const struct ata_timing initial_timing = {XFER_PIO_0, 70, 290, 240, 600, 165, 150, 600, 0}; -static unsigned int calc_mck_cycles(unsigned int ns, unsigned int mck_hz) +static unsigned long calc_mck_cycles(unsigned long ns, unsigned long mck_hz) { unsigned long mul; - /* - * cycles = x [nsec] * f [Hz] / 10^9 [ns in sec] = - * x * (f / 1_000_000_000) = - * x * ((f * 65536) / 1_000_000_000) / 65536 = - * x * (((f / 10_000) * 65536) / 100_000) / 65536 = - */ + /* + * cycles = x [nsec] * f [Hz] / 10^9 [ns in sec] = + * x * (f / 1_000_000_000) = + * x * ((f * 65536) / 1_000_000_000) / 65536 = + * x * (((f / 10_000) * 65536) / 100_000) / 65536 = + */ - mul = (mck_hz / 10000) << 16; - mul /= 100000; + mul = (mck_hz / 10000) << 16; + mul /= 100000; - return (ns * mul + 65536) >> 16; /* rounding */ + return (ns * mul + 65536) >> 16; /* rounding */ } static void set_smc_mode(struct at91_ide_info *info) { - at91_sys_write(AT91_SMC_MODE(info->cs), info->mode); - return; + at91_sys_write(AT91_SMC_MODE(info->cs), info->mode); + return; } static void set_smc_timing(struct device *dev, struct at91_ide_info *info, const struct ata_timing *ata) { - int read_cycle, write_cycle, active, recover; - int nrd_setup, nrd_pulse, nrd_recover; - int nwe_setup, nwe_pulse; + unsigned long read_cycle, write_cycle, active, recover; + unsigned long nrd_setup, nrd_pulse, nrd_recover; + unsigned long nwe_setup, nwe_pulse; - int ncs_write_setup, ncs_write_pulse; - int ncs_read_setup, ncs_read_pulse; + unsigned long ncs_write_setup, ncs_write_pulse; + unsigned long ncs_read_setup, ncs_read_pulse; - unsigned int mck_hz; - struct clk *mck; + unsigned long mck_hz; read_cycle = ata->cyc8b; nrd_setup = ata->setup; nrd_pulse = ata->act8b; nrd_recover = ata->rec8b; - mck = clk_get(NULL, "mck"); - BUG_ON(IS_ERR(mck)); - mck_hz = clk_get_rate(mck); + mck_hz = clk_get_rate(info->mck); read_cycle = calc_mck_cycles(read_cycle, mck_hz); nrd_setup = calc_mck_cycles(nrd_setup, mck_hz); nrd_pulse = calc_mck_cycles(nrd_pulse, mck_hz); nrd_recover = calc_mck_cycles(nrd_recover, mck_hz); - clk_put(mck); - active = nrd_setup + nrd_pulse; recover = read_cycle - active; @@ -121,13 +116,13 @@ static void set_smc_timing(struct device *dev, ncs_write_setup = ncs_read_setup; ncs_write_pulse = ncs_read_pulse; - dev_dbg(dev, "ATA timings: nrd_setup = %d nrd_pulse = %d nrd_cycle = %d\n", + dev_dbg(dev, "ATA timings: nrd_setup = %lu nrd_pulse = %lu nrd_cycle = %lu\n", nrd_setup, nrd_pulse, read_cycle); - dev_dbg(dev, "ATA timings: nwe_setup = %d nwe_pulse = %d nwe_cycle = %d\n", + dev_dbg(dev, "ATA timings: nwe_setup = %lu nwe_pulse = %lu nwe_cycle = %lu\n", nwe_setup, nwe_pulse, write_cycle); - dev_dbg(dev, "ATA timings: ncs_read_setup = %d ncs_read_pulse = %d\n", + dev_dbg(dev, "ATA timings: ncs_read_setup = %lu ncs_read_pulse = %lu\n", ncs_read_setup, ncs_read_pulse); - dev_dbg(dev, "ATA timings: ncs_write_setup = %d ncs_write_pulse = %d\n", + dev_dbg(dev, "ATA timings: ncs_write_setup = %lu ncs_write_pulse = %lu\n", ncs_write_setup, ncs_write_pulse); at91_sys_write(AT91_SMC_SETUP(info->cs), @@ -217,6 +212,7 @@ static int __devinit pata_at91_probe(struct platform_device *pdev) struct resource *mem_res; struct ata_host *host; struct ata_port *ap; + int irq_flags = 0; int irq = 0; int ret; @@ -261,6 +257,13 @@ static int __devinit pata_at91_probe(struct platform_device *pdev) return -ENOMEM; } + info->mck = clk_get(NULL, "mck"); + + if (IS_ERR(info->mck)) { + dev_err(dev, "failed to get access to mck clock\n"); + return -ENODEV; + } + info->cs = board->chipselect; info->mode = AT91_SMC_READMODE | AT91_SMC_WRITEMODE | AT91_SMC_EXNWMODE_READY | AT91_SMC_BAT_SELECT | @@ -304,6 +307,7 @@ err_alt_ioremap: devm_iounmap(dev, info->ide_addr); err_ide_ioremap: + clk_put(info->mck); kfree(info); return ret; @@ -326,6 +330,7 @@ static int __devexit pata_at91_remove(struct platform_device *pdev) devm_iounmap(dev, info->ide_addr); devm_iounmap(dev, info->alt_addr); + clk_put(info->mck); kfree(info); return 0; -- cgit v1.2.3 From 5920dadfb4aec6c1372c5570e71bcd3b4837e63c Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Wed, 15 Jul 2009 17:11:41 +0900 Subject: libata: accept late unlocking of HPA On certain configurations, HPA isn't or can't be unlocked during probing but it somehow ends up unlocked afterwards. In the following thread, the problem can be reliably reproduced after resuming from STR. The BIOS turns on HPA during boot but forgets to do it during resume. http://thread.gmane.org/gmane.linux.kernel/858310 This patch updates libata revalidation such that it considers native n_sectors. If the device size has increased to match native n_sectors, it's assumed that HPA has been unlocked involuntarily and the device is recognized as the same one. This should be fairly safe while nicely working around the problem. Signed-off-by: Tejun Heo Reported-by: Christof Warlich Signed-off-by: Jeff Garzik --- drivers/ata/libata-core.c | 30 +++++++++++++++++++++++------- include/linux/libata.h | 1 + 2 files changed, 24 insertions(+), 7 deletions(-) diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index 2c6aedaef718..8ac98ff16d7d 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -1515,6 +1515,7 @@ static int ata_hpa_resize(struct ata_device *dev) return rc; } + dev->n_native_sectors = native_sectors; /* nothing to do? */ if (native_sectors <= sectors || !ata_ignore_hpa) { @@ -4099,6 +4100,7 @@ int ata_dev_revalidate(struct ata_device *dev, unsigned int new_class, unsigned int readid_flags) { u64 n_sectors = dev->n_sectors; + u64 n_native_sectors = dev->n_native_sectors; int rc; if (!ata_dev_enabled(dev)) @@ -4128,16 +4130,30 @@ int ata_dev_revalidate(struct ata_device *dev, unsigned int new_class, /* verify n_sectors hasn't changed */ if (dev->class == ATA_DEV_ATA && n_sectors && dev->n_sectors != n_sectors) { - ata_dev_printk(dev, KERN_INFO, "n_sectors mismatch " + ata_dev_printk(dev, KERN_WARNING, "n_sectors mismatch " "%llu != %llu\n", (unsigned long long)n_sectors, (unsigned long long)dev->n_sectors); - - /* restore original n_sectors */ - dev->n_sectors = n_sectors; - - rc = -ENODEV; - goto fail; + /* + * Something could have caused HPA to be unlocked + * involuntarily. If n_native_sectors hasn't changed + * and the new size matches it, keep the device. + */ + if (dev->n_native_sectors == n_native_sectors && + dev->n_sectors > n_sectors && + dev->n_sectors == n_native_sectors) { + ata_dev_printk(dev, KERN_WARNING, + "new n_sectors matches native, probably " + "late HPA unlock, continuing\n"); + /* keep using the old n_sectors */ + dev->n_sectors = n_sectors; + } else { + /* restore original n_[native]_sectors and fail */ + dev->n_native_sectors = n_native_sectors; + dev->n_sectors = n_sectors; + rc = -ENODEV; + goto fail; + } } return 0; diff --git a/include/linux/libata.h b/include/linux/libata.h index 79b6d7fd4ac2..e5b6e33c6571 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -589,6 +589,7 @@ struct ata_device { #endif /* n_sector is CLEAR_BEGIN, read comment above CLEAR_BEGIN */ u64 n_sectors; /* size of device, if ATA */ + u64 n_native_sectors; /* native size, if ATA */ unsigned int class; /* ATA_DEV_xxx */ unsigned long unpark_deadline; -- cgit v1.2.3 From 68dbcb726e372b3c8ef60b79b5aff4174dd2bdf0 Mon Sep 17 00:00:00 2001 From: Jeff Garzik Date: Tue, 28 Jul 2009 22:36:59 -0400 Subject: Remove zero-length file drivers/char/vr41xx_giu.c Signed-off-by: Jeff Garzik --- drivers/char/vr41xx_giu.c | 0 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 drivers/char/vr41xx_giu.c diff --git a/drivers/char/vr41xx_giu.c b/drivers/char/vr41xx_giu.c deleted file mode 100644 index e69de29bb2d1..000000000000 -- cgit v1.2.3 From e024e11070a0a0dc7163ce1ec2da354a638bdbed Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Wed, 24 Jun 2009 09:48:08 +1000 Subject: drm/radeon/kms: add initial colortiling support. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This adds new set/get tiling interfaces where the pitch and macro/micro tiling enables can be set. Along with a flag to decide if this object should have a surface when mapped. The only thing we need to allocate with a mapped surface should be the frontbuffer. Note rotate scanout shouldn't require one, and back/depth shouldn't either, though mesa needs some fixes. It fixes the TTM interfaces along Thomas's suggestions, and I've tested the surface stealing code with two X servers and not seen any lockdep issues. I've stopped tiling the fbcon frontbuffer, as I don't see there being any advantage other than testing, I've left the testing commands in there, just flip the fb_tiled to true in radeon_fb.c Open: Can we integrate endian swapping in with this? Future features: texture tiling - need to relocate texture registers TXOFFSET* with tiling info. This also merges Michel's cleanup surfaces regs at init time patch even though it makes sense on its own, this patch really relies on it. Some PowerMac firmwares set up a tiling surface at the beginning of VRAM which messes us up otherwise. that patch is: Signed-off-by: Michel Dänzer Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/atombios_crtc.c | 11 ++- drivers/gpu/drm/radeon/r100.c | 79 ++++++++++++++++- drivers/gpu/drm/radeon/r300.c | 51 ++++++++++- drivers/gpu/drm/radeon/r300_reg.h | 4 +- drivers/gpu/drm/radeon/radeon.h | 32 ++++++- drivers/gpu/drm/radeon/radeon_asic.h | 19 ++++ drivers/gpu/drm/radeon/radeon_device.c | 2 + drivers/gpu/drm/radeon/radeon_fb.c | 12 ++- drivers/gpu/drm/radeon/radeon_gem.c | 41 +++++++++ drivers/gpu/drm/radeon/radeon_kms.c | 2 + drivers/gpu/drm/radeon/radeon_legacy_crtc.c | 15 ++-- drivers/gpu/drm/radeon/radeon_object.c | 130 ++++++++++++++++++++++++++++ drivers/gpu/drm/radeon/radeon_ttm.c | 2 + drivers/gpu/drm/ttm/ttm_bo.c | 5 +- drivers/gpu/drm/ttm/ttm_bo_vm.c | 3 + include/drm/radeon_drm.h | 23 ++++- include/drm/ttm/ttm_bo_driver.h | 15 ++++ 17 files changed, 427 insertions(+), 19 deletions(-) diff --git a/drivers/gpu/drm/radeon/atombios_crtc.c b/drivers/gpu/drm/radeon/atombios_crtc.c index e64a199b5ee1..eac26cdb5dae 100644 --- a/drivers/gpu/drm/radeon/atombios_crtc.c +++ b/drivers/gpu/drm/radeon/atombios_crtc.c @@ -327,7 +327,7 @@ int atombios_crtc_set_base(struct drm_crtc *crtc, int x, int y, struct drm_gem_object *obj; struct drm_radeon_gem_object *obj_priv; uint64_t fb_location; - uint32_t fb_format, fb_pitch_pixels; + uint32_t fb_format, fb_pitch_pixels, tiling_flags; if (!crtc->fb) return -EINVAL; @@ -364,7 +364,14 @@ int atombios_crtc_set_base(struct drm_crtc *crtc, int x, int y, return -EINVAL; } - /* TODO tiling */ + radeon_object_get_tiling_flags(obj->driver_private, + &tiling_flags, NULL); + if (tiling_flags & RADEON_TILING_MACRO) + fb_format |= AVIVO_D1GRPH_MACRO_ADDRESS_MODE; + + if (tiling_flags & RADEON_TILING_MICRO) + fb_format |= AVIVO_D1GRPH_TILED; + if (radeon_crtc->crtc_id == 0) WREG32(AVIVO_D1VGA_CONTROL, 0); else diff --git a/drivers/gpu/drm/radeon/r100.c b/drivers/gpu/drm/radeon/r100.c index 0d05909f03f6..69bd7cb59972 100644 --- a/drivers/gpu/drm/radeon/r100.c +++ b/drivers/gpu/drm/radeon/r100.c @@ -909,6 +909,7 @@ static int r100_packet0_check(struct radeon_cs_parser *p, unsigned idx; bool onereg; int r; + u32 tile_flags = 0; ib = p->ib->ptr; ib_chunk = &p->chunks[p->chunk_ib_idx]; @@ -942,7 +943,20 @@ static int r100_packet0_check(struct radeon_cs_parser *p, } tmp = ib_chunk->kdata[idx] & 0x003fffff; tmp += (((u32)reloc->lobj.gpu_offset) >> 10); - ib[idx] = (ib_chunk->kdata[idx] & 0xffc00000) | tmp; + + if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO) + tile_flags |= RADEON_DST_TILE_MACRO; + if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO) { + if (reg == RADEON_SRC_PITCH_OFFSET) { + DRM_ERROR("Cannot src blit from microtiled surface\n"); + r100_cs_dump_packet(p, pkt); + return -EINVAL; + } + tile_flags |= RADEON_DST_TILE_MICRO; + } + + tmp |= tile_flags; + ib[idx] = (ib_chunk->kdata[idx] & 0x3fc00000) | tmp; break; case RADEON_RB3D_DEPTHOFFSET: case RADEON_RB3D_COLOROFFSET: @@ -987,6 +1001,25 @@ static int r100_packet0_check(struct radeon_cs_parser *p, } ib[idx] = ib_chunk->kdata[idx] + ((u32)reloc->lobj.gpu_offset); break; + case R300_RB3D_COLORPITCH0: + case RADEON_RB3D_COLORPITCH: + 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; + } + + if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO) + tile_flags |= RADEON_COLOR_TILE_ENABLE; + if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO) + tile_flags |= RADEON_COLOR_MICROTILE_ENABLE; + + tmp = ib_chunk->kdata[idx] & ~(0x7 << 16); + tmp |= tile_flags; + ib[idx] = tmp; + break; default: /* FIXME: we don't want to allow anyothers packet */ break; @@ -1707,3 +1740,47 @@ int r100_debugfs_mc_info_init(struct radeon_device *rdev) return 0; #endif } + +int r100_set_surface_reg(struct radeon_device *rdev, int reg, + uint32_t tiling_flags, uint32_t pitch, + uint32_t offset, uint32_t obj_size) +{ + int surf_index = reg * 16; + int flags = 0; + + /* r100/r200 divide by 16 */ + if (rdev->family < CHIP_R300) + flags = pitch / 16; + else + flags = pitch / 8; + + if (rdev->family <= CHIP_RS200) { + if ((tiling_flags & (RADEON_TILING_MACRO|RADEON_TILING_MICRO)) + == (RADEON_TILING_MACRO|RADEON_TILING_MICRO)) + flags |= RADEON_SURF_TILE_COLOR_BOTH; + if (tiling_flags & RADEON_TILING_MACRO) + flags |= RADEON_SURF_TILE_COLOR_MACRO; + } else if (rdev->family <= CHIP_RV280) { + if (tiling_flags & (RADEON_TILING_MACRO)) + flags |= R200_SURF_TILE_COLOR_MACRO; + if (tiling_flags & RADEON_TILING_MICRO) + flags |= R200_SURF_TILE_COLOR_MICRO; + } else { + if (tiling_flags & RADEON_TILING_MACRO) + flags |= R300_SURF_TILE_MACRO; + if (tiling_flags & RADEON_TILING_MICRO) + flags |= R300_SURF_TILE_MICRO; + } + + DRM_DEBUG("writing surface %d %d %x %x\n", reg, flags, offset, offset+obj_size-1); + WREG32(RADEON_SURFACE0_INFO + surf_index, flags); + WREG32(RADEON_SURFACE0_LOWER_BOUND + surf_index, offset); + WREG32(RADEON_SURFACE0_UPPER_BOUND + surf_index, offset + obj_size - 1); + return 0; +} + +void r100_clear_surface_reg(struct radeon_device *rdev, int reg) +{ + int surf_index = reg * 16; + WREG32(RADEON_SURFACE0_INFO + surf_index, 0); +} diff --git a/drivers/gpu/drm/radeon/r300.c b/drivers/gpu/drm/radeon/r300.c index 0e0e094da503..28e5777658be 100644 --- a/drivers/gpu/drm/radeon/r300.c +++ b/drivers/gpu/drm/radeon/r300.c @@ -30,6 +30,7 @@ #include "drm.h" #include "radeon_reg.h" #include "radeon.h" +#include "radeon_drm.h" /* r300,r350,rv350,rv370,rv380 depends on : */ void r100_hdp_reset(struct radeon_device *rdev); @@ -1023,7 +1024,7 @@ static int r300_packet0_check(struct radeon_cs_parser *p, struct radeon_cs_reloc *reloc; struct r300_cs_track *track; volatile uint32_t *ib; - uint32_t tmp; + uint32_t tmp, tile_flags = 0; unsigned i; int r; @@ -1052,7 +1053,19 @@ static int r300_packet0_check(struct radeon_cs_parser *p, } tmp = ib_chunk->kdata[idx] & 0x003fffff; tmp += (((u32)reloc->lobj.gpu_offset) >> 10); - ib[idx] = (ib_chunk->kdata[idx] & 0xffc00000) | tmp; + + if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO) + tile_flags |= RADEON_DST_TILE_MACRO; + if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO) { + if (reg == RADEON_SRC_PITCH_OFFSET) { + DRM_ERROR("Cannot src blit from microtiled surface\n"); + r100_cs_dump_packet(p, pkt); + return -EINVAL; + } + tile_flags |= RADEON_DST_TILE_MICRO; + } + tmp |= tile_flags; + ib[idx] = (ib_chunk->kdata[idx] & 0x3fc00000) | tmp; break; case R300_RB3D_COLOROFFSET0: case R300_RB3D_COLOROFFSET1: @@ -1141,6 +1154,23 @@ static int r300_packet0_check(struct radeon_cs_parser *p, /* RB3D_COLORPITCH1 */ /* RB3D_COLORPITCH2 */ /* RB3D_COLORPITCH3 */ + 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; + } + + if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO) + tile_flags |= R300_COLOR_TILE_ENABLE; + if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO) + tile_flags |= R300_COLOR_MICROTILE_ENABLE; + + tmp = ib_chunk->kdata[idx] & ~(0x7 << 16); + tmp |= tile_flags; + ib[idx] = tmp; + i = (reg - 0x4E38) >> 2; track->cb[i].pitch = ib_chunk->kdata[idx] & 0x3FFE; switch (((ib_chunk->kdata[idx] >> 21) & 0xF)) { @@ -1196,6 +1226,23 @@ static int r300_packet0_check(struct radeon_cs_parser *p, break; case 0x4F24: /* ZB_DEPTHPITCH */ + 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; + } + + if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO) + tile_flags |= R300_DEPTHMACROTILE_ENABLE; + if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO) + tile_flags |= R300_DEPTHMICROTILE_TILED;; + + tmp = ib_chunk->kdata[idx] & ~(0x7 << 16); + tmp |= tile_flags; + ib[idx] = tmp; + track->zb.pitch = ib_chunk->kdata[idx] & 0x3FFC; break; case 0x4104: diff --git a/drivers/gpu/drm/radeon/r300_reg.h b/drivers/gpu/drm/radeon/r300_reg.h index 70f48609515e..4b7afef35a65 100644 --- a/drivers/gpu/drm/radeon/r300_reg.h +++ b/drivers/gpu/drm/radeon/r300_reg.h @@ -27,7 +27,9 @@ #ifndef _R300_REG_H_ #define _R300_REG_H_ - +#define R300_SURF_TILE_MACRO (1<<16) +#define R300_SURF_TILE_MICRO (2<<16) +#define R300_SURF_TILE_BOTH (3<<16) #define R300_MC_INIT_MISC_LAT_TIMER 0x180 diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h index 7f007185e7f7..af12a2fe3221 100644 --- a/drivers/gpu/drm/radeon/radeon.h +++ b/drivers/gpu/drm/radeon/radeon.h @@ -201,6 +201,14 @@ int radeon_fence_wait_last(struct radeon_device *rdev); struct radeon_fence *radeon_fence_ref(struct radeon_fence *fence); void radeon_fence_unref(struct radeon_fence **fence); +/* + * Tiling registers + */ +struct radeon_surface_reg { + struct radeon_object *robj; +}; + +#define RADEON_GEM_MAX_SURFACES 8 /* * Radeon buffer. @@ -213,6 +221,7 @@ struct radeon_object_list { uint64_t gpu_offset; unsigned rdomain; unsigned wdomain; + uint32_t tiling_flags; }; int radeon_object_init(struct radeon_device *rdev); @@ -242,8 +251,15 @@ void radeon_object_list_clean(struct list_head *head); int radeon_object_fbdev_mmap(struct radeon_object *robj, struct vm_area_struct *vma); unsigned long radeon_object_size(struct radeon_object *robj); - - +void radeon_object_clear_surface_reg(struct radeon_object *robj); +int radeon_object_check_tiling(struct radeon_object *robj, bool has_moved, + bool force_drop); +void radeon_object_set_tiling_flags(struct radeon_object *robj, + uint32_t tiling_flags, uint32_t pitch); +void radeon_object_get_tiling_flags(struct radeon_object *robj, uint32_t *tiling_flags, uint32_t *pitch); +void radeon_bo_move_notify(struct ttm_buffer_object *bo, + struct ttm_mem_reg *mem); +void radeon_bo_fault_reserve_notify(struct ttm_buffer_object *bo); /* * GEM objects. */ @@ -535,6 +551,11 @@ struct radeon_asic { void (*set_memory_clock)(struct radeon_device *rdev, uint32_t mem_clock); void (*set_pcie_lanes)(struct radeon_device *rdev, int lanes); void (*set_clock_gating)(struct radeon_device *rdev, int enable); + + int (*set_surface_reg)(struct radeon_device *rdev, int reg, + uint32_t tiling_flags, uint32_t pitch, + uint32_t offset, uint32_t obj_size); + int (*clear_surface_reg)(struct radeon_device *rdev, int reg); }; union radeon_asic_config { @@ -568,6 +589,10 @@ int radeon_gem_busy_ioctl(struct drm_device *dev, void *data, int radeon_gem_wait_idle_ioctl(struct drm_device *dev, void *data, struct drm_file *filp); int radeon_cs_ioctl(struct drm_device *dev, void *data, struct drm_file *filp); +int radeon_gem_set_tiling_ioctl(struct drm_device *dev, void *data, + struct drm_file *filp); +int radeon_gem_get_tiling_ioctl(struct drm_device *dev, void *data, + struct drm_file *filp); /* @@ -627,6 +652,7 @@ struct radeon_device { bool shutdown; bool suspend; bool need_dma32; + struct radeon_surface_reg surface_regs[RADEON_GEM_MAX_SURFACES]; }; int radeon_device_init(struct radeon_device *rdev, @@ -801,5 +827,7 @@ static inline void radeon_ring_write(struct radeon_device *rdev, uint32_t v) #define radeon_set_memory_clock(rdev, e) (rdev)->asic->set_engine_clock((rdev), (e)) #define radeon_set_pcie_lanes(rdev, l) (rdev)->asic->set_pcie_lanes((rdev), (l)) #define radeon_set_clock_gating(rdev, e) (rdev)->asic->set_clock_gating((rdev), (e)) +#define radeon_set_surface_reg(rdev, r, f, p, o, s) ((rdev)->asic->set_surface_reg((rdev), (r), (f), (p), (o), (s))) +#define radeon_clear_surface_reg(rdev, r) ((rdev)->asic->clear_surface_reg((rdev), (r))) #endif diff --git a/drivers/gpu/drm/radeon/radeon_asic.h b/drivers/gpu/drm/radeon/radeon_asic.h index e2e567395df8..dd903d329406 100644 --- a/drivers/gpu/drm/radeon/radeon_asic.h +++ b/drivers/gpu/drm/radeon/radeon_asic.h @@ -71,6 +71,10 @@ int r100_copy_blit(struct radeon_device *rdev, uint64_t dst_offset, unsigned num_pages, struct radeon_fence *fence); +int r100_set_surface_reg(struct radeon_device *rdev, int reg, + uint32_t tiling_flags, uint32_t pitch, + uint32_t offset, uint32_t obj_size); +int r100_clear_surface_reg(struct radeon_device *rdev, int reg); static struct radeon_asic r100_asic = { .init = &r100_init, @@ -100,6 +104,8 @@ static struct radeon_asic r100_asic = { .set_memory_clock = NULL, .set_pcie_lanes = NULL, .set_clock_gating = &radeon_legacy_set_clock_gating, + .set_surface_reg = r100_set_surface_reg, + .clear_surface_reg = r100_clear_surface_reg, }; @@ -128,6 +134,7 @@ int r300_copy_dma(struct radeon_device *rdev, uint64_t dst_offset, unsigned num_pages, struct radeon_fence *fence); + static struct radeon_asic r300_asic = { .init = &r300_init, .errata = &r300_errata, @@ -156,6 +163,8 @@ static struct radeon_asic r300_asic = { .set_memory_clock = NULL, .set_pcie_lanes = &rv370_set_pcie_lanes, .set_clock_gating = &radeon_legacy_set_clock_gating, + .set_surface_reg = r100_set_surface_reg, + .clear_surface_reg = r100_clear_surface_reg, }; /* @@ -193,6 +202,8 @@ static struct radeon_asic r420_asic = { .set_memory_clock = &radeon_atom_set_memory_clock, .set_pcie_lanes = &rv370_set_pcie_lanes, .set_clock_gating = &radeon_atom_set_clock_gating, + .set_surface_reg = r100_set_surface_reg, + .clear_surface_reg = r100_clear_surface_reg, }; @@ -237,6 +248,8 @@ static struct radeon_asic rs400_asic = { .set_memory_clock = NULL, .set_pcie_lanes = NULL, .set_clock_gating = &radeon_legacy_set_clock_gating, + .set_surface_reg = r100_set_surface_reg, + .clear_surface_reg = r100_clear_surface_reg, }; @@ -322,6 +335,8 @@ static struct radeon_asic rs690_asic = { .set_memory_clock = &radeon_atom_set_memory_clock, .set_pcie_lanes = NULL, .set_clock_gating = &radeon_atom_set_clock_gating, + .set_surface_reg = r100_set_surface_reg, + .clear_surface_reg = r100_clear_surface_reg, }; @@ -367,6 +382,8 @@ static struct radeon_asic rv515_asic = { .set_memory_clock = &radeon_atom_set_memory_clock, .set_pcie_lanes = &rv370_set_pcie_lanes, .set_clock_gating = &radeon_atom_set_clock_gating, + .set_surface_reg = r100_set_surface_reg, + .clear_surface_reg = r100_clear_surface_reg, }; @@ -405,6 +422,8 @@ static struct radeon_asic r520_asic = { .set_memory_clock = &radeon_atom_set_memory_clock, .set_pcie_lanes = &rv370_set_pcie_lanes, .set_clock_gating = &radeon_atom_set_clock_gating, + .set_surface_reg = r100_set_surface_reg, + .clear_surface_reg = r100_clear_surface_reg, }; /* diff --git a/drivers/gpu/drm/radeon/radeon_device.c b/drivers/gpu/drm/radeon/radeon_device.c index cdef6eb01baf..f23083bbba3f 100644 --- a/drivers/gpu/drm/radeon/radeon_device.c +++ b/drivers/gpu/drm/radeon/radeon_device.c @@ -48,6 +48,8 @@ static void radeon_surface_init(struct radeon_device *rdev) i * (RADEON_SURFACE1_INFO - RADEON_SURFACE0_INFO), 0); } + /* enable surfaces */ + WREG32(RADEON_SURFACE_CNTL, 0); } } diff --git a/drivers/gpu/drm/radeon/radeon_fb.c b/drivers/gpu/drm/radeon/radeon_fb.c index 260870a29d83..36d2f5588f20 100644 --- a/drivers/gpu/drm/radeon/radeon_fb.c +++ b/drivers/gpu/drm/radeon/radeon_fb.c @@ -471,10 +471,10 @@ static struct notifier_block paniced = { .notifier_call = radeonfb_panic, }; -static int radeon_align_pitch(struct radeon_device *rdev, int width, int bpp) +static int radeon_align_pitch(struct radeon_device *rdev, int width, int bpp, bool tiled) { int aligned = width; - int align_large = (ASIC_IS_AVIVO(rdev)); + int align_large = (ASIC_IS_AVIVO(rdev)) || tiled; int pitch_mask = 0; switch (bpp / 8) { @@ -512,12 +512,13 @@ int radeonfb_create(struct radeon_device *rdev, u64 fb_gpuaddr; void *fbptr = NULL; unsigned long tmp; + bool fb_tiled = false; /* useful for testing */ mode_cmd.width = surface_width; mode_cmd.height = surface_height; mode_cmd.bpp = 32; /* need to align pitch with crtc limits */ - mode_cmd.pitch = radeon_align_pitch(rdev, mode_cmd.width, mode_cmd.bpp) * ((mode_cmd.bpp + 1) / 8); + mode_cmd.pitch = radeon_align_pitch(rdev, mode_cmd.width, mode_cmd.bpp, fb_tiled) * ((mode_cmd.bpp + 1) / 8); mode_cmd.depth = 24; size = mode_cmd.pitch * mode_cmd.height; @@ -535,6 +536,8 @@ int radeonfb_create(struct radeon_device *rdev, } robj = gobj->driver_private; + if (fb_tiled) + radeon_object_set_tiling_flags(robj, RADEON_TILING_MACRO|RADEON_TILING_SURFACE, mode_cmd.pitch); mutex_lock(&rdev->ddev->struct_mutex); fb = radeon_framebuffer_create(rdev->ddev, &mode_cmd, gobj); if (fb == NULL) { @@ -563,6 +566,9 @@ int radeonfb_create(struct radeon_device *rdev, } rfbdev = info->par; + if (fb_tiled) + radeon_object_check_tiling(robj, 0, 0); + ret = radeon_object_kmap(robj, &fbptr); if (ret) { goto out_unref; diff --git a/drivers/gpu/drm/radeon/radeon_gem.c b/drivers/gpu/drm/radeon/radeon_gem.c index eb516034235d..12542087b298 100644 --- a/drivers/gpu/drm/radeon/radeon_gem.c +++ b/drivers/gpu/drm/radeon/radeon_gem.c @@ -285,3 +285,44 @@ int radeon_gem_wait_idle_ioctl(struct drm_device *dev, void *data, mutex_unlock(&dev->struct_mutex); return r; } + +int radeon_gem_set_tiling_ioctl(struct drm_device *dev, void *data, + struct drm_file *filp) +{ + struct drm_radeon_gem_set_tiling *args = data; + struct drm_gem_object *gobj; + struct radeon_object *robj; + int r = 0; + + DRM_DEBUG("%d \n", args->handle); + gobj = drm_gem_object_lookup(dev, filp, args->handle); + if (gobj == NULL) + return -EINVAL; + robj = gobj->driver_private; + radeon_object_set_tiling_flags(robj, args->tiling_flags, args->pitch); + mutex_lock(&dev->struct_mutex); + drm_gem_object_unreference(gobj); + mutex_unlock(&dev->struct_mutex); + return r; +} + +int radeon_gem_get_tiling_ioctl(struct drm_device *dev, void *data, + struct drm_file *filp) +{ + struct drm_radeon_gem_get_tiling *args = data; + struct drm_gem_object *gobj; + struct radeon_object *robj; + int r = 0; + + DRM_DEBUG("\n"); + gobj = drm_gem_object_lookup(dev, filp, args->handle); + if (gobj == NULL) + return -EINVAL; + robj = gobj->driver_private; + radeon_object_get_tiling_flags(robj, &args->tiling_flags, + &args->pitch); + mutex_lock(&dev->struct_mutex); + drm_gem_object_unreference(gobj); + mutex_unlock(&dev->struct_mutex); + return r; +} diff --git a/drivers/gpu/drm/radeon/radeon_kms.c b/drivers/gpu/drm/radeon/radeon_kms.c index 4612a7c146d1..937a2f1cdb46 100644 --- a/drivers/gpu/drm/radeon/radeon_kms.c +++ b/drivers/gpu/drm/radeon/radeon_kms.c @@ -291,5 +291,7 @@ struct drm_ioctl_desc radeon_ioctls_kms[] = { DRM_IOCTL_DEF(DRM_RADEON_GEM_WAIT_IDLE, radeon_gem_wait_idle_ioctl, DRM_AUTH), DRM_IOCTL_DEF(DRM_RADEON_CS, radeon_cs_ioctl, DRM_AUTH), 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), }; 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 14c1a5107fc9..0613790e2a5b 100644 --- a/drivers/gpu/drm/radeon/radeon_legacy_crtc.c +++ b/drivers/gpu/drm/radeon/radeon_legacy_crtc.c @@ -235,6 +235,7 @@ int radeon_crtc_set_base(struct drm_crtc *crtc, int x, int y, uint64_t base; uint32_t crtc_offset, crtc_offset_cntl, crtc_tile_x0_y0 = 0; uint32_t crtc_pitch, pitch_pixels; + uint32_t tiling_flags; DRM_DEBUG("\n"); @@ -258,8 +259,12 @@ int radeon_crtc_set_base(struct drm_crtc *crtc, int x, int y, (crtc->fb->bits_per_pixel * 8)); crtc_pitch |= crtc_pitch << 16; - /* TODO tiling */ - if (0) { + radeon_object_get_tiling_flags(obj->driver_private, + &tiling_flags, NULL); + if (tiling_flags & RADEON_TILING_MICRO) + DRM_ERROR("trying to scanout microtiled buffer\n"); + + if (tiling_flags & RADEON_TILING_MACRO) { if (ASIC_IS_R300(rdev)) crtc_offset_cntl |= (R300_CRTC_X_Y_MODE_EN | R300_CRTC_MICRO_TILE_BUFFER_DIS | @@ -275,15 +280,13 @@ int radeon_crtc_set_base(struct drm_crtc *crtc, int x, int y, crtc_offset_cntl &= ~RADEON_CRTC_TILE_EN; } - - /* TODO more tiling */ - if (0) { + if (tiling_flags & RADEON_TILING_MACRO) { if (ASIC_IS_R300(rdev)) { crtc_tile_x0_y0 = x | (y << 16); base &= ~0x7ff; } else { int byteshift = crtc->fb->bits_per_pixel >> 4; - int tile_addr = (((y >> 3) * crtc->fb->width + x) >> (8 - byteshift)) << 11; + int tile_addr = (((y >> 3) * pitch_pixels + x) >> (8 - byteshift)) << 11; base += tile_addr + ((x << byteshift) % 256) + ((y % 8) << 8); crtc_offset_cntl |= (y % 16); } diff --git a/drivers/gpu/drm/radeon/radeon_object.c b/drivers/gpu/drm/radeon/radeon_object.c index bac0d06c52ac..d5b1fd562d88 100644 --- a/drivers/gpu/drm/radeon/radeon_object.c +++ b/drivers/gpu/drm/radeon/radeon_object.c @@ -44,6 +44,9 @@ struct radeon_object { uint64_t gpu_addr; void *kptr; bool is_iomem; + uint32_t tiling_flags; + uint32_t pitch; + int surface_reg; }; int radeon_ttm_init(struct radeon_device *rdev); @@ -70,6 +73,7 @@ static void radeon_ttm_object_object_destroy(struct ttm_buffer_object *tobj) robj = container_of(tobj, struct radeon_object, tobj); list_del_init(&robj->list); + radeon_object_clear_surface_reg(robj); kfree(robj); } @@ -141,6 +145,7 @@ int radeon_object_create(struct radeon_device *rdev, } robj->rdev = rdev; robj->gobj = gobj; + robj->surface_reg = -1; INIT_LIST_HEAD(&robj->list); flags = radeon_object_flags_from_domain(domain); @@ -435,6 +440,7 @@ int radeon_object_list_validate(struct list_head *head, void *fence) radeon_object_gpu_addr(robj); } lobj->gpu_offset = robj->gpu_addr; + lobj->tiling_flags = robj->tiling_flags; if (fence) { old_fence = (struct radeon_fence *)robj->tobj.sync_obj; robj->tobj.sync_obj = radeon_fence_ref(fence); @@ -479,3 +485,127 @@ unsigned long radeon_object_size(struct radeon_object *robj) { return robj->tobj.num_pages << PAGE_SHIFT; } + +int radeon_object_get_surface_reg(struct radeon_object *robj) +{ + struct radeon_device *rdev = robj->rdev; + struct radeon_surface_reg *reg; + struct radeon_object *old_object; + int steal; + int i; + + if (!robj->tiling_flags) + return 0; + + if (robj->surface_reg >= 0) { + reg = &rdev->surface_regs[robj->surface_reg]; + i = robj->surface_reg; + goto out; + } + + steal = -1; + for (i = 0; i < RADEON_GEM_MAX_SURFACES; i++) { + + reg = &rdev->surface_regs[i]; + if (!reg->robj) + break; + + old_object = reg->robj; + if (old_object->pin_count == 0) + steal = i; + } + + /* if we are all out */ + if (i == RADEON_GEM_MAX_SURFACES) { + if (steal == -1) + return -ENOMEM; + /* find someone with a surface reg and nuke their BO */ + reg = &rdev->surface_regs[steal]; + old_object = reg->robj; + /* blow away the mapping */ + DRM_DEBUG("stealing surface reg %d from %p\n", steal, old_object); + ttm_bo_unmap_virtual(&old_object->tobj); + old_object->surface_reg = -1; + i = steal; + } + + robj->surface_reg = i; + reg->robj = robj; + +out: + radeon_set_surface_reg(rdev, i, robj->tiling_flags, robj->pitch, + robj->tobj.mem.mm_node->start << PAGE_SHIFT, + robj->tobj.num_pages << PAGE_SHIFT); + return 0; +} + +void radeon_object_clear_surface_reg(struct radeon_object *robj) +{ + struct radeon_device *rdev = robj->rdev; + struct radeon_surface_reg *reg; + + if (robj->surface_reg == -1) + return; + + reg = &rdev->surface_regs[robj->surface_reg]; + radeon_clear_surface_reg(rdev, robj->surface_reg); + + reg->robj = NULL; + robj->surface_reg = -1; +} + +void radeon_object_set_tiling_flags(struct radeon_object *robj, + uint32_t tiling_flags, uint32_t pitch) +{ + robj->tiling_flags = tiling_flags; + robj->pitch = pitch; +} + +void radeon_object_get_tiling_flags(struct radeon_object *robj, + uint32_t *tiling_flags, + uint32_t *pitch) +{ + if (tiling_flags) + *tiling_flags = robj->tiling_flags; + if (pitch) + *pitch = robj->pitch; +} + +int radeon_object_check_tiling(struct radeon_object *robj, bool has_moved, + bool force_drop) +{ + if (!(robj->tiling_flags & RADEON_TILING_SURFACE)) + return 0; + + if (force_drop) { + radeon_object_clear_surface_reg(robj); + return 0; + } + + if (robj->tobj.mem.mem_type != TTM_PL_VRAM) { + if (!has_moved) + return 0; + + if (robj->surface_reg >= 0) + radeon_object_clear_surface_reg(robj); + return 0; + } + + if ((robj->surface_reg >= 0) && !has_moved) + return 0; + + return radeon_object_get_surface_reg(robj); +} + +void radeon_bo_move_notify(struct ttm_buffer_object *bo, + struct ttm_mem_reg *mem) +{ + struct radeon_object *robj = container_of(bo, struct radeon_object, tobj); + radeon_object_check_tiling(robj, 0, 1); +} + +void radeon_bo_fault_reserve_notify(struct ttm_buffer_object *bo) +{ + struct radeon_object *robj = container_of(bo, struct radeon_object, tobj); + radeon_object_check_tiling(robj, 0, 0); +} diff --git a/drivers/gpu/drm/radeon/radeon_ttm.c b/drivers/gpu/drm/radeon/radeon_ttm.c index 4ca9aa9203d0..37e1cbcce3a9 100644 --- a/drivers/gpu/drm/radeon/radeon_ttm.c +++ b/drivers/gpu/drm/radeon/radeon_ttm.c @@ -429,6 +429,8 @@ static struct ttm_bo_driver radeon_bo_driver = { .sync_obj_flush = &radeon_sync_obj_flush, .sync_obj_unref = &radeon_sync_obj_unref, .sync_obj_ref = &radeon_sync_obj_ref, + .move_notify = &radeon_bo_move_notify, + .fault_reserve_notify = &radeon_bo_fault_reserve_notify, }; int radeon_ttm_init(struct radeon_device *rdev) diff --git a/drivers/gpu/drm/ttm/ttm_bo.c b/drivers/gpu/drm/ttm/ttm_bo.c index e55e7972c897..6538d4236989 100644 --- a/drivers/gpu/drm/ttm/ttm_bo.c +++ b/drivers/gpu/drm/ttm/ttm_bo.c @@ -43,7 +43,6 @@ #define TTM_BO_HASH_ORDER 13 static int ttm_bo_setup_vm(struct ttm_buffer_object *bo); -static void ttm_bo_unmap_virtual(struct ttm_buffer_object *bo); static int ttm_bo_swapout(struct ttm_mem_shrink *shrink); static inline uint32_t ttm_bo_type_flags(unsigned type) @@ -307,6 +306,9 @@ static int ttm_bo_handle_move_mem(struct ttm_buffer_object *bo, } + if (bdev->driver->move_notify) + bdev->driver->move_notify(bo, mem); + if (!(old_man->flags & TTM_MEMTYPE_FLAG_FIXED) && !(new_man->flags & TTM_MEMTYPE_FLAG_FIXED)) ret = ttm_bo_move_ttm(bo, evict, no_wait, mem); @@ -1451,6 +1453,7 @@ void ttm_bo_unmap_virtual(struct ttm_buffer_object *bo) unmap_mapping_range(bdev->dev_mapping, offset, holelen, 1); } +EXPORT_SYMBOL(ttm_bo_unmap_virtual); static void ttm_bo_vm_insert_rb(struct ttm_buffer_object *bo) { diff --git a/drivers/gpu/drm/ttm/ttm_bo_vm.c b/drivers/gpu/drm/ttm/ttm_bo_vm.c index 40b75032ea47..41c907f6c560 100644 --- a/drivers/gpu/drm/ttm/ttm_bo_vm.c +++ b/drivers/gpu/drm/ttm/ttm_bo_vm.c @@ -101,6 +101,9 @@ static int ttm_bo_vm_fault(struct vm_area_struct *vma, struct vm_fault *vmf) return VM_FAULT_NOPAGE; } + if (bdev->driver->fault_reserve_notify) + bdev->driver->fault_reserve_notify(bo); + /* * Wait for buffer data in transit, due to a pipelined * move. diff --git a/include/drm/radeon_drm.h b/include/drm/radeon_drm.h index 41862e9a4c20..af4b4826997e 100644 --- a/include/drm/radeon_drm.h +++ b/include/drm/radeon_drm.h @@ -506,6 +506,8 @@ typedef struct { #define DRM_RADEON_GEM_WAIT_IDLE 0x24 #define DRM_RADEON_CS 0x26 #define DRM_RADEON_INFO 0x27 +#define DRM_RADEON_GEM_SET_TILING 0x28 +#define DRM_RADEON_GEM_GET_TILING 0x29 #define DRM_IOCTL_RADEON_CP_INIT DRM_IOW( DRM_COMMAND_BASE + DRM_RADEON_CP_INIT, drm_radeon_init_t) #define DRM_IOCTL_RADEON_CP_START DRM_IO( DRM_COMMAND_BASE + DRM_RADEON_CP_START) @@ -544,7 +546,8 @@ typedef struct { #define DRM_IOCTL_RADEON_GEM_WAIT_IDLE DRM_IOW(DRM_COMMAND_BASE + DRM_RADEON_GEM_WAIT_IDLE, struct drm_radeon_gem_wait_idle) #define DRM_IOCTL_RADEON_CS DRM_IOWR(DRM_COMMAND_BASE + DRM_RADEON_CS, struct drm_radeon_cs) #define DRM_IOCTL_RADEON_INFO DRM_IOWR(DRM_COMMAND_BASE + DRM_RADEON_INFO, struct drm_radeon_info) - +#define DRM_IOCTL_RADEON_SET_TILING DRM_IOWR(DRM_COMMAND_BASE + DRM_RADEON_GEM_SET_TILING, struct drm_radeon_gem_set_tiling) +#define DRM_IOCTL_RADEON_GET_TILING DRM_IOWR(DRM_COMMAND_BASE + DRM_RADEON_GEM_GET_TILING, struct drm_radeon_gem_get_tiling) typedef struct drm_radeon_init { enum { @@ -796,6 +799,24 @@ struct drm_radeon_gem_create { uint32_t flags; }; +#define RADEON_TILING_MACRO 0x1 +#define RADEON_TILING_MICRO 0x2 +#define RADEON_TILING_SWAP 0x4 +#define RADEON_TILING_SURFACE 0x8 /* this object requires a surface + * when mapped - i.e. front buffer */ + +struct drm_radeon_gem_set_tiling { + uint32_t handle; + uint32_t tiling_flags; + uint32_t pitch; +}; + +struct drm_radeon_gem_get_tiling { + uint32_t handle; + uint32_t tiling_flags; + uint32_t pitch; +}; + struct drm_radeon_gem_mmap { uint32_t handle; uint32_t pad; diff --git a/include/drm/ttm/ttm_bo_driver.h b/include/drm/ttm/ttm_bo_driver.h index ea83dd23a4d7..a68829db381a 100644 --- a/include/drm/ttm/ttm_bo_driver.h +++ b/include/drm/ttm/ttm_bo_driver.h @@ -354,6 +354,14 @@ struct ttm_bo_driver { int (*sync_obj_flush) (void *sync_obj, void *sync_arg); void (*sync_obj_unref) (void **sync_obj); void *(*sync_obj_ref) (void *sync_obj); + + /* hook to notify driver about a driver move so it + * can do tiling things */ + void (*move_notify)(struct ttm_buffer_object *bo, + struct ttm_mem_reg *new_mem); + /* notify the driver we are taking a fault on this BO + * and have reserved it */ + void (*fault_reserve_notify)(struct ttm_buffer_object *bo); }; #define TTM_NUM_MEM_TYPES 8 @@ -653,6 +661,13 @@ extern int ttm_bo_device_init(struct ttm_bo_device *bdev, struct ttm_bo_driver *driver, uint64_t file_page_offset, bool need_dma32); +/** + * ttm_bo_unmap_virtual + * + * @bo: tear down the virtual mappings for this BO + */ +extern void ttm_bo_unmap_virtual(struct ttm_buffer_object *bo); + /** * ttm_bo_reserve: * -- cgit v1.2.3 From c93bb85b5cba3e3a06f2cad8e9bc5c23d3d10aac Mon Sep 17 00:00:00 2001 From: Jerome Glisse Date: Mon, 13 Jul 2009 21:04:08 +0200 Subject: drm/radeon/kms: fix bandwidth computation on avivo hardware Fix bandwidth computation and crtc priority in memory controller so that crtc memory request are fullfill in time to avoid display artifact. Signed-off-by: Jerome Glisse Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/atombios_crtc.c | 276 ++++----- drivers/gpu/drm/radeon/r100.c | 483 +++++++++++++++ drivers/gpu/drm/radeon/r300.c | 1 + drivers/gpu/drm/radeon/r520.c | 14 + drivers/gpu/drm/radeon/radeon.h | 40 +- drivers/gpu/drm/radeon/radeon_asic.h | 13 + drivers/gpu/drm/radeon/radeon_device.c | 10 +- drivers/gpu/drm/radeon/radeon_display.c | 68 ++- drivers/gpu/drm/radeon/radeon_encoders.c | 369 +---------- drivers/gpu/drm/radeon/radeon_legacy_crtc.c | 661 ++++++-------------- drivers/gpu/drm/radeon/radeon_legacy_encoders.c | 188 +----- drivers/gpu/drm/radeon/radeon_mode.h | 48 +- drivers/gpu/drm/radeon/radeon_share.h | 39 ++ drivers/gpu/drm/radeon/rs400.c | 1 + drivers/gpu/drm/radeon/rs600.c | 5 + drivers/gpu/drm/radeon/rs690.c | 472 +++++++++++++++ drivers/gpu/drm/radeon/rs690r.h | 99 +++ drivers/gpu/drm/radeon/rv515.c | 774 ++++++++++++++++++++---- drivers/gpu/drm/radeon/rv515r.h | 170 ++++++ 19 files changed, 2377 insertions(+), 1354 deletions(-) create mode 100644 drivers/gpu/drm/radeon/radeon_share.h create mode 100644 drivers/gpu/drm/radeon/rs690r.h create mode 100644 drivers/gpu/drm/radeon/rv515r.h diff --git a/drivers/gpu/drm/radeon/atombios_crtc.c b/drivers/gpu/drm/radeon/atombios_crtc.c index eac26cdb5dae..74d034f77c6b 100644 --- a/drivers/gpu/drm/radeon/atombios_crtc.c +++ b/drivers/gpu/drm/radeon/atombios_crtc.c @@ -31,6 +31,132 @@ #include "atom.h" #include "atom-bits.h" +static void atombios_overscan_setup(struct drm_crtc *crtc, + struct drm_display_mode *mode, + struct drm_display_mode *adjusted_mode) +{ + struct drm_device *dev = crtc->dev; + struct radeon_device *rdev = dev->dev_private; + struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); + SET_CRTC_OVERSCAN_PS_ALLOCATION args; + int index = GetIndexIntoMasterTable(COMMAND, SetCRTC_OverScan); + int a1, a2; + + memset(&args, 0, sizeof(args)); + + args.usOverscanRight = 0; + args.usOverscanLeft = 0; + args.usOverscanBottom = 0; + args.usOverscanTop = 0; + args.ucCRTC = radeon_crtc->crtc_id; + + switch (radeon_crtc->rmx_type) { + case RMX_CENTER: + args.usOverscanTop = (adjusted_mode->crtc_vdisplay - mode->crtc_vdisplay) / 2; + args.usOverscanBottom = (adjusted_mode->crtc_vdisplay - mode->crtc_vdisplay) / 2; + args.usOverscanLeft = (adjusted_mode->crtc_hdisplay - mode->crtc_hdisplay) / 2; + args.usOverscanRight = (adjusted_mode->crtc_hdisplay - mode->crtc_hdisplay) / 2; + atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); + break; + case RMX_ASPECT: + a1 = mode->crtc_vdisplay * adjusted_mode->crtc_hdisplay; + a2 = adjusted_mode->crtc_vdisplay * mode->crtc_hdisplay; + + if (a1 > a2) { + args.usOverscanLeft = (adjusted_mode->crtc_hdisplay - (a2 / mode->crtc_vdisplay)) / 2; + args.usOverscanRight = (adjusted_mode->crtc_hdisplay - (a2 / mode->crtc_vdisplay)) / 2; + } else if (a2 > a1) { + args.usOverscanLeft = (adjusted_mode->crtc_vdisplay - (a1 / mode->crtc_hdisplay)) / 2; + args.usOverscanRight = (adjusted_mode->crtc_vdisplay - (a1 / mode->crtc_hdisplay)) / 2; + } + atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); + break; + case RMX_FULL: + default: + args.usOverscanRight = 0; + args.usOverscanLeft = 0; + args.usOverscanBottom = 0; + args.usOverscanTop = 0; + atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); + break; + } +} + +static void atombios_scaler_setup(struct drm_crtc *crtc) +{ + struct drm_device *dev = crtc->dev; + struct radeon_device *rdev = dev->dev_private; + struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); + ENABLE_SCALER_PS_ALLOCATION args; + int index = GetIndexIntoMasterTable(COMMAND, EnableScaler); + /* fixme - fill in enc_priv for atom dac */ + enum radeon_tv_std tv_std = TV_STD_NTSC; + + if (!ASIC_IS_AVIVO(rdev) && radeon_crtc->crtc_id) + return; + + memset(&args, 0, sizeof(args)); + + args.ucScaler = radeon_crtc->crtc_id; + + if (radeon_crtc->devices & (ATOM_DEVICE_TV_SUPPORT)) { + switch (tv_std) { + case TV_STD_NTSC: + default: + args.ucTVStandard = ATOM_TV_NTSC; + break; + case TV_STD_PAL: + args.ucTVStandard = ATOM_TV_PAL; + break; + case TV_STD_PAL_M: + args.ucTVStandard = ATOM_TV_PALM; + break; + case TV_STD_PAL_60: + args.ucTVStandard = ATOM_TV_PAL60; + break; + case TV_STD_NTSC_J: + args.ucTVStandard = ATOM_TV_NTSCJ; + break; + case TV_STD_SCART_PAL: + args.ucTVStandard = ATOM_TV_PAL; /* ??? */ + break; + case TV_STD_SECAM: + args.ucTVStandard = ATOM_TV_SECAM; + break; + case TV_STD_PAL_CN: + args.ucTVStandard = ATOM_TV_PALCN; + break; + } + args.ucEnable = SCALER_ENABLE_MULTITAP_MODE; + } else if (radeon_crtc->devices & (ATOM_DEVICE_CV_SUPPORT)) { + args.ucTVStandard = ATOM_TV_CV; + args.ucEnable = SCALER_ENABLE_MULTITAP_MODE; + } else { + switch (radeon_crtc->rmx_type) { + case RMX_FULL: + args.ucEnable = ATOM_SCALER_EXPANSION; + break; + case RMX_CENTER: + args.ucEnable = ATOM_SCALER_CENTER; + break; + case RMX_ASPECT: + args.ucEnable = ATOM_SCALER_EXPANSION; + break; + default: + if (ASIC_IS_AVIVO(rdev)) + args.ucEnable = ATOM_SCALER_DISABLE; + else + args.ucEnable = ATOM_SCALER_CENTER; + break; + } + } + atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); + if (radeon_crtc->devices & (ATOM_DEVICE_CV_SUPPORT | ATOM_DEVICE_TV_SUPPORT) + && rdev->family >= CHIP_RV515 && rdev->family <= CHIP_RV570) { + atom_rv515_force_tv_scaler(rdev); + } +} + static void atombios_lock_crtc(struct drm_crtc *crtc, int lock) { struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); @@ -522,6 +648,9 @@ int atombios_crtc_mode_set(struct drm_crtc *crtc, radeon_crtc_set_base(crtc, x, y, old_fb); radeon_legacy_atom_set_surface(crtc); } + atombios_overscan_setup(crtc, mode, adjusted_mode); + atombios_scaler_setup(crtc); + radeon_bandwidth_update(rdev); return 0; } @@ -529,6 +658,8 @@ static bool atombios_crtc_mode_fixup(struct drm_crtc *crtc, struct drm_display_mode *mode, struct drm_display_mode *adjusted_mode) { + if (!radeon_crtc_scaling_mode_fixup(crtc, mode, adjusted_mode)) + return false; return true; } @@ -561,148 +692,3 @@ void radeon_atombios_init_crtc(struct drm_device *dev, AVIVO_D2CRTC_H_TOTAL - AVIVO_D1CRTC_H_TOTAL; drm_crtc_helper_add(&radeon_crtc->base, &atombios_helper_funcs); } - -void radeon_init_disp_bw_avivo(struct drm_device *dev, - struct drm_display_mode *mode1, - uint32_t pixel_bytes1, - struct drm_display_mode *mode2, - uint32_t pixel_bytes2) -{ - struct radeon_device *rdev = dev->dev_private; - fixed20_12 min_mem_eff; - fixed20_12 peak_disp_bw, mem_bw, pix_clk, pix_clk2, temp_ff; - fixed20_12 sclk_ff, mclk_ff; - uint32_t dc_lb_memory_split, temp; - - min_mem_eff.full = rfixed_const_8(0); - if (rdev->disp_priority == 2) { - uint32_t mc_init_misc_lat_timer = 0; - if (rdev->family == CHIP_RV515) - mc_init_misc_lat_timer = - RREG32_MC(RV515_MC_INIT_MISC_LAT_TIMER); - else if (rdev->family == CHIP_RS690) - mc_init_misc_lat_timer = - RREG32_MC(RS690_MC_INIT_MISC_LAT_TIMER); - - mc_init_misc_lat_timer &= - ~(R300_MC_DISP1R_INIT_LAT_MASK << - R300_MC_DISP1R_INIT_LAT_SHIFT); - mc_init_misc_lat_timer &= - ~(R300_MC_DISP0R_INIT_LAT_MASK << - R300_MC_DISP0R_INIT_LAT_SHIFT); - - if (mode2) - mc_init_misc_lat_timer |= - (1 << R300_MC_DISP1R_INIT_LAT_SHIFT); - if (mode1) - mc_init_misc_lat_timer |= - (1 << R300_MC_DISP0R_INIT_LAT_SHIFT); - - if (rdev->family == CHIP_RV515) - WREG32_MC(RV515_MC_INIT_MISC_LAT_TIMER, - mc_init_misc_lat_timer); - else if (rdev->family == CHIP_RS690) - WREG32_MC(RS690_MC_INIT_MISC_LAT_TIMER, - mc_init_misc_lat_timer); - } - - /* - * determine is there is enough bw for current mode - */ - temp_ff.full = rfixed_const(100); - mclk_ff.full = rfixed_const(rdev->clock.default_mclk); - mclk_ff.full = rfixed_div(mclk_ff, temp_ff); - sclk_ff.full = rfixed_const(rdev->clock.default_sclk); - sclk_ff.full = rfixed_div(sclk_ff, temp_ff); - - temp = (rdev->mc.vram_width / 8) * (rdev->mc.vram_is_ddr ? 2 : 1); - temp_ff.full = rfixed_const(temp); - mem_bw.full = rfixed_mul(mclk_ff, temp_ff); - mem_bw.full = rfixed_mul(mem_bw, min_mem_eff); - - pix_clk.full = 0; - pix_clk2.full = 0; - peak_disp_bw.full = 0; - if (mode1) { - temp_ff.full = rfixed_const(1000); - pix_clk.full = rfixed_const(mode1->clock); /* convert to fixed point */ - pix_clk.full = rfixed_div(pix_clk, temp_ff); - temp_ff.full = rfixed_const(pixel_bytes1); - peak_disp_bw.full += rfixed_mul(pix_clk, temp_ff); - } - if (mode2) { - temp_ff.full = rfixed_const(1000); - pix_clk2.full = rfixed_const(mode2->clock); /* convert to fixed point */ - pix_clk2.full = rfixed_div(pix_clk2, temp_ff); - temp_ff.full = rfixed_const(pixel_bytes2); - peak_disp_bw.full += rfixed_mul(pix_clk2, temp_ff); - } - - if (peak_disp_bw.full >= mem_bw.full) { - DRM_ERROR - ("You may not have enough display bandwidth for current mode\n" - "If you have flickering problem, try to lower resolution, refresh rate, or color depth\n"); - printk("peak disp bw %d, mem_bw %d\n", - rfixed_trunc(peak_disp_bw), rfixed_trunc(mem_bw)); - } - - /* - * Line Buffer Setup - * There is a single line buffer shared by both display controllers. - * DC_LB_MEMORY_SPLIT controls how that line buffer is shared between the display - * controllers. The paritioning can either be done manually or via one of four - * preset allocations specified in bits 1:0: - * 0 - line buffer is divided in half and shared between each display controller - * 1 - D1 gets 3/4 of the line buffer, D2 gets 1/4 - * 2 - D1 gets the whole buffer - * 3 - D1 gets 1/4 of the line buffer, D2 gets 3/4 - * Setting bit 2 of DC_LB_MEMORY_SPLIT controls switches to manual allocation mode. - * In manual allocation mode, D1 always starts at 0, D1 end/2 is specified in bits - * 14:4; D2 allocation follows D1. - */ - - /* is auto or manual better ? */ - dc_lb_memory_split = - RREG32(AVIVO_DC_LB_MEMORY_SPLIT) & ~AVIVO_DC_LB_MEMORY_SPLIT_MASK; - dc_lb_memory_split &= ~AVIVO_DC_LB_MEMORY_SPLIT_SHIFT_MODE; -#if 1 - /* auto */ - if (mode1 && mode2) { - if (mode1->hdisplay > mode2->hdisplay) { - if (mode1->hdisplay > 2560) - dc_lb_memory_split |= - AVIVO_DC_LB_MEMORY_SPLIT_D1_3Q_D2_1Q; - else - dc_lb_memory_split |= - AVIVO_DC_LB_MEMORY_SPLIT_D1HALF_D2HALF; - } else if (mode2->hdisplay > mode1->hdisplay) { - if (mode2->hdisplay > 2560) - dc_lb_memory_split |= - AVIVO_DC_LB_MEMORY_SPLIT_D1_1Q_D2_3Q; - else - dc_lb_memory_split |= - AVIVO_DC_LB_MEMORY_SPLIT_D1HALF_D2HALF; - } else - dc_lb_memory_split |= - AVIVO_DC_LB_MEMORY_SPLIT_D1HALF_D2HALF; - } else if (mode1) { - dc_lb_memory_split |= AVIVO_DC_LB_MEMORY_SPLIT_D1_ONLY; - } else if (mode2) { - dc_lb_memory_split |= AVIVO_DC_LB_MEMORY_SPLIT_D1_1Q_D2_3Q; - } -#else - /* manual */ - dc_lb_memory_split |= AVIVO_DC_LB_MEMORY_SPLIT_SHIFT_MODE; - dc_lb_memory_split &= - ~(AVIVO_DC_LB_DISP1_END_ADR_MASK << - AVIVO_DC_LB_DISP1_END_ADR_SHIFT); - if (mode1) { - dc_lb_memory_split |= - ((((mode1->hdisplay / 2) + 64) & AVIVO_DC_LB_DISP1_END_ADR_MASK) - << AVIVO_DC_LB_DISP1_END_ADR_SHIFT); - } else if (mode2) { - dc_lb_memory_split |= (0 << AVIVO_DC_LB_DISP1_END_ADR_SHIFT); - } -#endif - WREG32(AVIVO_DC_LB_MEMORY_SPLIT, dc_lb_memory_split); -} diff --git a/drivers/gpu/drm/radeon/r100.c b/drivers/gpu/drm/radeon/r100.c index 69bd7cb59972..0e00fef0b84f 100644 --- a/drivers/gpu/drm/radeon/r100.c +++ b/drivers/gpu/drm/radeon/r100.c @@ -1784,3 +1784,486 @@ void r100_clear_surface_reg(struct radeon_device *rdev, int reg) int surf_index = reg * 16; WREG32(RADEON_SURFACE0_INFO + surf_index, 0); } + +void r100_bandwidth_update(struct radeon_device *rdev) +{ + fixed20_12 trcd_ff, trp_ff, tras_ff, trbs_ff, tcas_ff; + fixed20_12 sclk_ff, mclk_ff, sclk_eff_ff, sclk_delay_ff; + fixed20_12 peak_disp_bw, mem_bw, pix_clk, pix_clk2, temp_ff, crit_point_ff; + uint32_t temp, data, mem_trcd, mem_trp, mem_tras; + fixed20_12 memtcas_ff[8] = { + fixed_init(1), + fixed_init(2), + fixed_init(3), + fixed_init(0), + fixed_init_half(1), + fixed_init_half(2), + fixed_init(0), + }; + fixed20_12 memtcas_rs480_ff[8] = { + fixed_init(0), + fixed_init(1), + fixed_init(2), + fixed_init(3), + fixed_init(0), + fixed_init_half(1), + fixed_init_half(2), + fixed_init_half(3), + }; + fixed20_12 memtcas2_ff[8] = { + fixed_init(0), + fixed_init(1), + fixed_init(2), + fixed_init(3), + fixed_init(4), + fixed_init(5), + fixed_init(6), + fixed_init(7), + }; + fixed20_12 memtrbs[8] = { + fixed_init(1), + fixed_init_half(1), + fixed_init(2), + fixed_init_half(2), + fixed_init(3), + fixed_init_half(3), + fixed_init(4), + fixed_init_half(4) + }; + fixed20_12 memtrbs_r4xx[8] = { + fixed_init(4), + fixed_init(5), + fixed_init(6), + fixed_init(7), + fixed_init(8), + fixed_init(9), + fixed_init(10), + fixed_init(11) + }; + fixed20_12 min_mem_eff; + fixed20_12 mc_latency_sclk, mc_latency_mclk, k1; + fixed20_12 cur_latency_mclk, cur_latency_sclk; + fixed20_12 disp_latency, disp_latency_overhead, disp_drain_rate, + disp_drain_rate2, read_return_rate; + fixed20_12 time_disp1_drop_priority; + int c; + int cur_size = 16; /* in octawords */ + int critical_point = 0, critical_point2; +/* uint32_t read_return_rate, time_disp1_drop_priority; */ + int stop_req, max_stop_req; + struct drm_display_mode *mode1 = NULL; + struct drm_display_mode *mode2 = NULL; + uint32_t pixel_bytes1 = 0; + uint32_t pixel_bytes2 = 0; + + if (rdev->mode_info.crtcs[0]->base.enabled) { + mode1 = &rdev->mode_info.crtcs[0]->base.mode; + pixel_bytes1 = rdev->mode_info.crtcs[0]->base.fb->bits_per_pixel / 8; + } + if (rdev->mode_info.crtcs[1]->base.enabled) { + mode2 = &rdev->mode_info.crtcs[1]->base.mode; + pixel_bytes2 = rdev->mode_info.crtcs[1]->base.fb->bits_per_pixel / 8; + } + + min_mem_eff.full = rfixed_const_8(0); + /* get modes */ + if ((rdev->disp_priority == 2) && ASIC_IS_R300(rdev)) { + uint32_t mc_init_misc_lat_timer = RREG32(R300_MC_INIT_MISC_LAT_TIMER); + mc_init_misc_lat_timer &= ~(R300_MC_DISP1R_INIT_LAT_MASK << R300_MC_DISP1R_INIT_LAT_SHIFT); + mc_init_misc_lat_timer &= ~(R300_MC_DISP0R_INIT_LAT_MASK << R300_MC_DISP0R_INIT_LAT_SHIFT); + /* check crtc enables */ + if (mode2) + mc_init_misc_lat_timer |= (1 << R300_MC_DISP1R_INIT_LAT_SHIFT); + if (mode1) + mc_init_misc_lat_timer |= (1 << R300_MC_DISP0R_INIT_LAT_SHIFT); + WREG32(R300_MC_INIT_MISC_LAT_TIMER, mc_init_misc_lat_timer); + } + + /* + * determine is there is enough bw for current mode + */ + mclk_ff.full = rfixed_const(rdev->clock.default_mclk); + temp_ff.full = rfixed_const(100); + mclk_ff.full = rfixed_div(mclk_ff, temp_ff); + sclk_ff.full = rfixed_const(rdev->clock.default_sclk); + sclk_ff.full = rfixed_div(sclk_ff, temp_ff); + + temp = (rdev->mc.vram_width / 8) * (rdev->mc.vram_is_ddr ? 2 : 1); + temp_ff.full = rfixed_const(temp); + mem_bw.full = rfixed_mul(mclk_ff, temp_ff); + + pix_clk.full = 0; + pix_clk2.full = 0; + peak_disp_bw.full = 0; + if (mode1) { + temp_ff.full = rfixed_const(1000); + pix_clk.full = rfixed_const(mode1->clock); /* convert to fixed point */ + pix_clk.full = rfixed_div(pix_clk, temp_ff); + temp_ff.full = rfixed_const(pixel_bytes1); + peak_disp_bw.full += rfixed_mul(pix_clk, temp_ff); + } + if (mode2) { + temp_ff.full = rfixed_const(1000); + pix_clk2.full = rfixed_const(mode2->clock); /* convert to fixed point */ + pix_clk2.full = rfixed_div(pix_clk2, temp_ff); + temp_ff.full = rfixed_const(pixel_bytes2); + peak_disp_bw.full += rfixed_mul(pix_clk2, temp_ff); + } + + mem_bw.full = rfixed_mul(mem_bw, min_mem_eff); + if (peak_disp_bw.full >= mem_bw.full) { + DRM_ERROR("You may not have enough display bandwidth for current mode\n" + "If you have flickering problem, try to lower resolution, refresh rate, or color depth\n"); + } + + /* Get values from the EXT_MEM_CNTL register...converting its contents. */ + temp = RREG32(RADEON_MEM_TIMING_CNTL); + if ((rdev->family == CHIP_RV100) || (rdev->flags & RADEON_IS_IGP)) { /* RV100, M6, IGPs */ + mem_trcd = ((temp >> 2) & 0x3) + 1; + mem_trp = ((temp & 0x3)) + 1; + mem_tras = ((temp & 0x70) >> 4) + 1; + } else if (rdev->family == CHIP_R300 || + rdev->family == CHIP_R350) { /* r300, r350 */ + mem_trcd = (temp & 0x7) + 1; + mem_trp = ((temp >> 8) & 0x7) + 1; + mem_tras = ((temp >> 11) & 0xf) + 4; + } else if (rdev->family == CHIP_RV350 || + rdev->family <= CHIP_RV380) { + /* rv3x0 */ + mem_trcd = (temp & 0x7) + 3; + mem_trp = ((temp >> 8) & 0x7) + 3; + mem_tras = ((temp >> 11) & 0xf) + 6; + } else if (rdev->family == CHIP_R420 || + rdev->family == CHIP_R423 || + rdev->family == CHIP_RV410) { + /* r4xx */ + mem_trcd = (temp & 0xf) + 3; + if (mem_trcd > 15) + mem_trcd = 15; + mem_trp = ((temp >> 8) & 0xf) + 3; + if (mem_trp > 15) + mem_trp = 15; + mem_tras = ((temp >> 12) & 0x1f) + 6; + if (mem_tras > 31) + mem_tras = 31; + } else { /* RV200, R200 */ + mem_trcd = (temp & 0x7) + 1; + mem_trp = ((temp >> 8) & 0x7) + 1; + mem_tras = ((temp >> 12) & 0xf) + 4; + } + /* convert to FF */ + trcd_ff.full = rfixed_const(mem_trcd); + trp_ff.full = rfixed_const(mem_trp); + tras_ff.full = rfixed_const(mem_tras); + + /* Get values from the MEM_SDRAM_MODE_REG register...converting its */ + temp = RREG32(RADEON_MEM_SDRAM_MODE_REG); + data = (temp & (7 << 20)) >> 20; + if ((rdev->family == CHIP_RV100) || rdev->flags & RADEON_IS_IGP) { + if (rdev->family == CHIP_RS480) /* don't think rs400 */ + tcas_ff = memtcas_rs480_ff[data]; + else + tcas_ff = memtcas_ff[data]; + } else + tcas_ff = memtcas2_ff[data]; + + if (rdev->family == CHIP_RS400 || + rdev->family == CHIP_RS480) { + /* extra cas latency stored in bits 23-25 0-4 clocks */ + data = (temp >> 23) & 0x7; + if (data < 5) + tcas_ff.full += rfixed_const(data); + } + + if (ASIC_IS_R300(rdev) && !(rdev->flags & RADEON_IS_IGP)) { + /* on the R300, Tcas is included in Trbs. + */ + temp = RREG32(RADEON_MEM_CNTL); + data = (R300_MEM_NUM_CHANNELS_MASK & temp); + if (data == 1) { + if (R300_MEM_USE_CD_CH_ONLY & temp) { + temp = RREG32(R300_MC_IND_INDEX); + temp &= ~R300_MC_IND_ADDR_MASK; + temp |= R300_MC_READ_CNTL_CD_mcind; + WREG32(R300_MC_IND_INDEX, temp); + temp = RREG32(R300_MC_IND_DATA); + data = (R300_MEM_RBS_POSITION_C_MASK & temp); + } else { + temp = RREG32(R300_MC_READ_CNTL_AB); + data = (R300_MEM_RBS_POSITION_A_MASK & temp); + } + } else { + temp = RREG32(R300_MC_READ_CNTL_AB); + data = (R300_MEM_RBS_POSITION_A_MASK & temp); + } + if (rdev->family == CHIP_RV410 || + rdev->family == CHIP_R420 || + rdev->family == CHIP_R423) + trbs_ff = memtrbs_r4xx[data]; + else + trbs_ff = memtrbs[data]; + tcas_ff.full += trbs_ff.full; + } + + sclk_eff_ff.full = sclk_ff.full; + + if (rdev->flags & RADEON_IS_AGP) { + fixed20_12 agpmode_ff; + agpmode_ff.full = rfixed_const(radeon_agpmode); + temp_ff.full = rfixed_const_666(16); + sclk_eff_ff.full -= rfixed_mul(agpmode_ff, temp_ff); + } + /* TODO PCIE lanes may affect this - agpmode == 16?? */ + + if (ASIC_IS_R300(rdev)) { + sclk_delay_ff.full = rfixed_const(250); + } else { + if ((rdev->family == CHIP_RV100) || + rdev->flags & RADEON_IS_IGP) { + if (rdev->mc.vram_is_ddr) + sclk_delay_ff.full = rfixed_const(41); + else + sclk_delay_ff.full = rfixed_const(33); + } else { + if (rdev->mc.vram_width == 128) + sclk_delay_ff.full = rfixed_const(57); + else + sclk_delay_ff.full = rfixed_const(41); + } + } + + mc_latency_sclk.full = rfixed_div(sclk_delay_ff, sclk_eff_ff); + + if (rdev->mc.vram_is_ddr) { + if (rdev->mc.vram_width == 32) { + k1.full = rfixed_const(40); + c = 3; + } else { + k1.full = rfixed_const(20); + c = 1; + } + } else { + k1.full = rfixed_const(40); + c = 3; + } + + temp_ff.full = rfixed_const(2); + mc_latency_mclk.full = rfixed_mul(trcd_ff, temp_ff); + temp_ff.full = rfixed_const(c); + mc_latency_mclk.full += rfixed_mul(tcas_ff, temp_ff); + temp_ff.full = rfixed_const(4); + mc_latency_mclk.full += rfixed_mul(tras_ff, temp_ff); + mc_latency_mclk.full += rfixed_mul(trp_ff, temp_ff); + mc_latency_mclk.full += k1.full; + + mc_latency_mclk.full = rfixed_div(mc_latency_mclk, mclk_ff); + mc_latency_mclk.full += rfixed_div(temp_ff, sclk_eff_ff); + + /* + HW cursor time assuming worst case of full size colour cursor. + */ + temp_ff.full = rfixed_const((2 * (cur_size - (rdev->mc.vram_is_ddr + 1)))); + temp_ff.full += trcd_ff.full; + if (temp_ff.full < tras_ff.full) + temp_ff.full = tras_ff.full; + cur_latency_mclk.full = rfixed_div(temp_ff, mclk_ff); + + temp_ff.full = rfixed_const(cur_size); + cur_latency_sclk.full = rfixed_div(temp_ff, sclk_eff_ff); + /* + Find the total latency for the display data. + */ + disp_latency_overhead.full = rfixed_const(80); + disp_latency_overhead.full = rfixed_div(disp_latency_overhead, sclk_ff); + mc_latency_mclk.full += disp_latency_overhead.full + cur_latency_mclk.full; + mc_latency_sclk.full += disp_latency_overhead.full + cur_latency_sclk.full; + + if (mc_latency_mclk.full > mc_latency_sclk.full) + disp_latency.full = mc_latency_mclk.full; + else + disp_latency.full = mc_latency_sclk.full; + + /* setup Max GRPH_STOP_REQ default value */ + if (ASIC_IS_RV100(rdev)) + max_stop_req = 0x5c; + else + max_stop_req = 0x7c; + + if (mode1) { + /* CRTC1 + Set GRPH_BUFFER_CNTL register using h/w defined optimal values. + GRPH_STOP_REQ <= MIN[ 0x7C, (CRTC_H_DISP + 1) * (bit depth) / 0x10 ] + */ + stop_req = mode1->hdisplay * pixel_bytes1 / 16; + + if (stop_req > max_stop_req) + stop_req = max_stop_req; + + /* + Find the drain rate of the display buffer. + */ + temp_ff.full = rfixed_const((16/pixel_bytes1)); + disp_drain_rate.full = rfixed_div(pix_clk, temp_ff); + + /* + Find the critical point of the display buffer. + */ + crit_point_ff.full = rfixed_mul(disp_drain_rate, disp_latency); + crit_point_ff.full += rfixed_const_half(0); + + critical_point = rfixed_trunc(crit_point_ff); + + if (rdev->disp_priority == 2) { + critical_point = 0; + } + + /* + The critical point should never be above max_stop_req-4. Setting + GRPH_CRITICAL_CNTL = 0 will thus force high priority all the time. + */ + if (max_stop_req - critical_point < 4) + critical_point = 0; + + if (critical_point == 0 && mode2 && rdev->family == CHIP_R300) { + /* some R300 cards have problem with this set to 0, when CRTC2 is enabled.*/ + critical_point = 0x10; + } + + temp = RREG32(RADEON_GRPH_BUFFER_CNTL); + temp &= ~(RADEON_GRPH_STOP_REQ_MASK); + temp |= (stop_req << RADEON_GRPH_STOP_REQ_SHIFT); + temp &= ~(RADEON_GRPH_START_REQ_MASK); + if ((rdev->family == CHIP_R350) && + (stop_req > 0x15)) { + stop_req -= 0x10; + } + temp |= (stop_req << RADEON_GRPH_START_REQ_SHIFT); + temp |= RADEON_GRPH_BUFFER_SIZE; + temp &= ~(RADEON_GRPH_CRITICAL_CNTL | + RADEON_GRPH_CRITICAL_AT_SOF | + RADEON_GRPH_STOP_CNTL); + /* + Write the result into the register. + */ + WREG32(RADEON_GRPH_BUFFER_CNTL, ((temp & ~RADEON_GRPH_CRITICAL_POINT_MASK) | + (critical_point << RADEON_GRPH_CRITICAL_POINT_SHIFT))); + +#if 0 + if ((rdev->family == CHIP_RS400) || + (rdev->family == CHIP_RS480)) { + /* attempt to program RS400 disp regs correctly ??? */ + temp = RREG32(RS400_DISP1_REG_CNTL); + temp &= ~(RS400_DISP1_START_REQ_LEVEL_MASK | + RS400_DISP1_STOP_REQ_LEVEL_MASK); + WREG32(RS400_DISP1_REQ_CNTL1, (temp | + (critical_point << RS400_DISP1_START_REQ_LEVEL_SHIFT) | + (critical_point << RS400_DISP1_STOP_REQ_LEVEL_SHIFT))); + temp = RREG32(RS400_DMIF_MEM_CNTL1); + temp &= ~(RS400_DISP1_CRITICAL_POINT_START_MASK | + RS400_DISP1_CRITICAL_POINT_STOP_MASK); + WREG32(RS400_DMIF_MEM_CNTL1, (temp | + (critical_point << RS400_DISP1_CRITICAL_POINT_START_SHIFT) | + (critical_point << RS400_DISP1_CRITICAL_POINT_STOP_SHIFT))); + } +#endif + + DRM_DEBUG("GRPH_BUFFER_CNTL from to %x\n", + /* (unsigned int)info->SavedReg->grph_buffer_cntl, */ + (unsigned int)RREG32(RADEON_GRPH_BUFFER_CNTL)); + } + + if (mode2) { + u32 grph2_cntl; + stop_req = mode2->hdisplay * pixel_bytes2 / 16; + + if (stop_req > max_stop_req) + stop_req = max_stop_req; + + /* + Find the drain rate of the display buffer. + */ + temp_ff.full = rfixed_const((16/pixel_bytes2)); + disp_drain_rate2.full = rfixed_div(pix_clk2, temp_ff); + + grph2_cntl = RREG32(RADEON_GRPH2_BUFFER_CNTL); + grph2_cntl &= ~(RADEON_GRPH_STOP_REQ_MASK); + grph2_cntl |= (stop_req << RADEON_GRPH_STOP_REQ_SHIFT); + grph2_cntl &= ~(RADEON_GRPH_START_REQ_MASK); + if ((rdev->family == CHIP_R350) && + (stop_req > 0x15)) { + stop_req -= 0x10; + } + grph2_cntl |= (stop_req << RADEON_GRPH_START_REQ_SHIFT); + grph2_cntl |= RADEON_GRPH_BUFFER_SIZE; + grph2_cntl &= ~(RADEON_GRPH_CRITICAL_CNTL | + RADEON_GRPH_CRITICAL_AT_SOF | + RADEON_GRPH_STOP_CNTL); + + if ((rdev->family == CHIP_RS100) || + (rdev->family == CHIP_RS200)) + critical_point2 = 0; + else { + temp = (rdev->mc.vram_width * rdev->mc.vram_is_ddr + 1)/128; + temp_ff.full = rfixed_const(temp); + temp_ff.full = rfixed_mul(mclk_ff, temp_ff); + if (sclk_ff.full < temp_ff.full) + temp_ff.full = sclk_ff.full; + + read_return_rate.full = temp_ff.full; + + if (mode1) { + temp_ff.full = read_return_rate.full - disp_drain_rate.full; + time_disp1_drop_priority.full = rfixed_div(crit_point_ff, temp_ff); + } else { + time_disp1_drop_priority.full = 0; + } + crit_point_ff.full = disp_latency.full + time_disp1_drop_priority.full + disp_latency.full; + crit_point_ff.full = rfixed_mul(crit_point_ff, disp_drain_rate2); + crit_point_ff.full += rfixed_const_half(0); + + critical_point2 = rfixed_trunc(crit_point_ff); + + if (rdev->disp_priority == 2) { + critical_point2 = 0; + } + + if (max_stop_req - critical_point2 < 4) + critical_point2 = 0; + + } + + if (critical_point2 == 0 && rdev->family == CHIP_R300) { + /* some R300 cards have problem with this set to 0 */ + critical_point2 = 0x10; + } + + WREG32(RADEON_GRPH2_BUFFER_CNTL, ((grph2_cntl & ~RADEON_GRPH_CRITICAL_POINT_MASK) | + (critical_point2 << RADEON_GRPH_CRITICAL_POINT_SHIFT))); + + if ((rdev->family == CHIP_RS400) || + (rdev->family == CHIP_RS480)) { +#if 0 + /* attempt to program RS400 disp2 regs correctly ??? */ + temp = RREG32(RS400_DISP2_REQ_CNTL1); + temp &= ~(RS400_DISP2_START_REQ_LEVEL_MASK | + RS400_DISP2_STOP_REQ_LEVEL_MASK); + WREG32(RS400_DISP2_REQ_CNTL1, (temp | + (critical_point2 << RS400_DISP1_START_REQ_LEVEL_SHIFT) | + (critical_point2 << RS400_DISP1_STOP_REQ_LEVEL_SHIFT))); + temp = RREG32(RS400_DISP2_REQ_CNTL2); + temp &= ~(RS400_DISP2_CRITICAL_POINT_START_MASK | + RS400_DISP2_CRITICAL_POINT_STOP_MASK); + WREG32(RS400_DISP2_REQ_CNTL2, (temp | + (critical_point2 << RS400_DISP2_CRITICAL_POINT_START_SHIFT) | + (critical_point2 << RS400_DISP2_CRITICAL_POINT_STOP_SHIFT))); +#endif + WREG32(RS400_DISP2_REQ_CNTL1, 0x105DC1CC); + WREG32(RS400_DISP2_REQ_CNTL2, 0x2749D000); + WREG32(RS400_DMIF_MEM_CNTL1, 0x29CA71DC); + WREG32(RS400_DISP1_REQ_CNTL1, 0x28FBC3AC); + } + + DRM_DEBUG("GRPH2_BUFFER_CNTL from to %x\n", + (unsigned int)RREG32(RADEON_GRPH2_BUFFER_CNTL)); + } +} diff --git a/drivers/gpu/drm/radeon/r300.c b/drivers/gpu/drm/radeon/r300.c index 28e5777658be..9c8d41534a5d 100644 --- a/drivers/gpu/drm/radeon/r300.c +++ b/drivers/gpu/drm/radeon/r300.c @@ -31,6 +31,7 @@ #include "radeon_reg.h" #include "radeon.h" #include "radeon_drm.h" +#include "radeon_share.h" /* r300,r350,rv350,rv370,rv380 depends on : */ void r100_hdp_reset(struct radeon_device *rdev); diff --git a/drivers/gpu/drm/radeon/r520.c b/drivers/gpu/drm/radeon/r520.c index b6bd3758db6b..0a981e2ee2f8 100644 --- a/drivers/gpu/drm/radeon/r520.c +++ b/drivers/gpu/drm/radeon/r520.c @@ -28,6 +28,7 @@ #include "drmP.h" #include "radeon_reg.h" #include "radeon.h" +#include "radeon_share.h" /* r520,rv530,rv560,rv570,r580 depends on : */ void r100_hdp_reset(struct radeon_device *rdev); @@ -226,7 +227,20 @@ static void r520_vram_get_type(struct radeon_device *rdev) void r520_vram_info(struct radeon_device *rdev) { + fixed20_12 a; + r520_vram_get_type(rdev); r100_vram_init_sizes(rdev); + /* FIXME: we should enforce default clock in case GPU is not in + * default setup + */ + a.full = rfixed_const(100); + rdev->pm.sclk.full = rfixed_const(rdev->clock.default_sclk); + rdev->pm.sclk.full = rfixed_div(rdev->pm.sclk, a); +} + +void r520_bandwidth_update(struct radeon_device *rdev) +{ + rv515_bandwidth_avivo_update(rdev); } diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h index af12a2fe3221..63a3fe32e584 100644 --- a/drivers/gpu/drm/radeon/radeon.h +++ b/drivers/gpu/drm/radeon/radeon.h @@ -113,6 +113,7 @@ enum radeon_family { CHIP_RV770, CHIP_RV730, CHIP_RV710, + CHIP_RS880, CHIP_LAST, }; @@ -490,6 +491,39 @@ struct radeon_wb { uint64_t gpu_addr; }; +/** + * struct radeon_pm - power management datas + * @max_bandwidth: maximum bandwidth the gpu has (MByte/s) + * @igp_sideport_mclk: sideport memory clock Mhz (rs690,rs740,rs780,rs880) + * @igp_system_mclk: system clock Mhz (rs690,rs740,rs780,rs880) + * @igp_ht_link_clk: ht link clock Mhz (rs690,rs740,rs780,rs880) + * @igp_ht_link_width: ht link width in bits (rs690,rs740,rs780,rs880) + * @k8_bandwidth: k8 bandwidth the gpu has (MByte/s) (IGP) + * @sideport_bandwidth: sideport bandwidth the gpu has (MByte/s) (IGP) + * @ht_bandwidth: ht bandwidth the gpu has (MByte/s) (IGP) + * @core_bandwidth: core GPU bandwidth the gpu has (MByte/s) (IGP) + * @sclk: GPU clock Mhz (core bandwith depends of this clock) + * @needed_bandwidth: current bandwidth needs + * + * It keeps track of various data needed to take powermanagement decision. + * Bandwith need is used to determine minimun clock of the GPU and memory. + * Equation between gpu/memory clock and available bandwidth is hw dependent + * (type of memory, bus size, efficiency, ...) + */ +struct radeon_pm { + fixed20_12 max_bandwidth; + fixed20_12 igp_sideport_mclk; + fixed20_12 igp_system_mclk; + fixed20_12 igp_ht_link_clk; + fixed20_12 igp_ht_link_width; + fixed20_12 k8_bandwidth; + fixed20_12 sideport_bandwidth; + fixed20_12 ht_bandwidth; + fixed20_12 core_bandwidth; + fixed20_12 sclk; + fixed20_12 needed_bandwidth; +}; + /* * Benchmarking @@ -551,19 +585,17 @@ struct radeon_asic { void (*set_memory_clock)(struct radeon_device *rdev, uint32_t mem_clock); void (*set_pcie_lanes)(struct radeon_device *rdev, int lanes); void (*set_clock_gating)(struct radeon_device *rdev, int enable); - int (*set_surface_reg)(struct radeon_device *rdev, int reg, uint32_t tiling_flags, uint32_t pitch, uint32_t offset, uint32_t obj_size); int (*clear_surface_reg)(struct radeon_device *rdev, int reg); + void (*bandwidth_update)(struct radeon_device *rdev); }; union radeon_asic_config { struct r300_asic r300; }; -/* r100 */ -void r100_vram_init_sizes(struct radeon_device *rdev); /* * IOCTL. @@ -646,6 +678,7 @@ struct radeon_device { struct radeon_irq irq; struct radeon_asic *asic; struct radeon_gem gem; + struct radeon_pm pm; struct mutex cs_mutex; struct radeon_wb wb; bool gpu_lockup; @@ -829,5 +862,6 @@ static inline void radeon_ring_write(struct radeon_device *rdev, uint32_t v) #define radeon_set_clock_gating(rdev, e) (rdev)->asic->set_clock_gating((rdev), (e)) #define radeon_set_surface_reg(rdev, r, f, p, o, s) ((rdev)->asic->set_surface_reg((rdev), (r), (f), (p), (o), (s))) #define radeon_clear_surface_reg(rdev, r) ((rdev)->asic->clear_surface_reg((rdev), (r))) +#define radeon_bandwidth_update(rdev) (rdev)->asic->bandwidth_update((rdev)) #endif diff --git a/drivers/gpu/drm/radeon/radeon_asic.h b/drivers/gpu/drm/radeon/radeon_asic.h index dd903d329406..9a75876e0c3b 100644 --- a/drivers/gpu/drm/radeon/radeon_asic.h +++ b/drivers/gpu/drm/radeon/radeon_asic.h @@ -75,6 +75,7 @@ int r100_set_surface_reg(struct radeon_device *rdev, int reg, uint32_t tiling_flags, uint32_t pitch, uint32_t offset, uint32_t obj_size); int r100_clear_surface_reg(struct radeon_device *rdev, int reg); +void r100_bandwidth_update(struct radeon_device *rdev); static struct radeon_asic r100_asic = { .init = &r100_init, @@ -106,6 +107,7 @@ static struct radeon_asic r100_asic = { .set_clock_gating = &radeon_legacy_set_clock_gating, .set_surface_reg = r100_set_surface_reg, .clear_surface_reg = r100_clear_surface_reg, + .bandwidth_update = &r100_bandwidth_update, }; @@ -165,6 +167,7 @@ static struct radeon_asic r300_asic = { .set_clock_gating = &radeon_legacy_set_clock_gating, .set_surface_reg = r100_set_surface_reg, .clear_surface_reg = r100_clear_surface_reg, + .bandwidth_update = &r100_bandwidth_update, }; /* @@ -204,6 +207,7 @@ static struct radeon_asic r420_asic = { .set_clock_gating = &radeon_atom_set_clock_gating, .set_surface_reg = r100_set_surface_reg, .clear_surface_reg = r100_clear_surface_reg, + .bandwidth_update = &r100_bandwidth_update, }; @@ -250,6 +254,7 @@ static struct radeon_asic rs400_asic = { .set_clock_gating = &radeon_legacy_set_clock_gating, .set_surface_reg = r100_set_surface_reg, .clear_surface_reg = r100_clear_surface_reg, + .bandwidth_update = &r100_bandwidth_update, }; @@ -267,6 +272,7 @@ void rs600_gart_tlb_flush(struct radeon_device *rdev); int rs600_gart_set_page(struct radeon_device *rdev, int i, uint64_t addr); uint32_t rs600_mc_rreg(struct radeon_device *rdev, uint32_t reg); void rs600_mc_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v); +void rs600_bandwidth_update(struct radeon_device *rdev); static struct radeon_asic rs600_asic = { .init = &r300_init, .errata = &rs600_errata, @@ -295,6 +301,7 @@ static struct radeon_asic rs600_asic = { .set_memory_clock = &radeon_atom_set_memory_clock, .set_pcie_lanes = NULL, .set_clock_gating = &radeon_atom_set_clock_gating, + .bandwidth_update = &rs600_bandwidth_update, }; @@ -307,6 +314,7 @@ int rs690_mc_init(struct radeon_device *rdev); void rs690_mc_fini(struct radeon_device *rdev); 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, .errata = &rs690_errata, @@ -337,6 +345,7 @@ static struct radeon_asic rs690_asic = { .set_clock_gating = &radeon_atom_set_clock_gating, .set_surface_reg = r100_set_surface_reg, .clear_surface_reg = r100_clear_surface_reg, + .bandwidth_update = &rs690_bandwidth_update, }; @@ -354,6 +363,7 @@ void rv515_mc_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v); void rv515_ring_start(struct radeon_device *rdev); uint32_t rv515_pcie_rreg(struct radeon_device *rdev, uint32_t reg); void rv515_pcie_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v); +void rv515_bandwidth_update(struct radeon_device *rdev); static struct radeon_asic rv515_asic = { .init = &rv515_init, .errata = &rv515_errata, @@ -384,6 +394,7 @@ static struct radeon_asic rv515_asic = { .set_clock_gating = &radeon_atom_set_clock_gating, .set_surface_reg = r100_set_surface_reg, .clear_surface_reg = r100_clear_surface_reg, + .bandwidth_update = &rv515_bandwidth_update, }; @@ -394,6 +405,7 @@ void r520_errata(struct radeon_device *rdev); void r520_vram_info(struct radeon_device *rdev); int r520_mc_init(struct radeon_device *rdev); void r520_mc_fini(struct radeon_device *rdev); +void r520_bandwidth_update(struct radeon_device *rdev); static struct radeon_asic r520_asic = { .init = &rv515_init, .errata = &r520_errata, @@ -424,6 +436,7 @@ static struct radeon_asic r520_asic = { .set_clock_gating = &radeon_atom_set_clock_gating, .set_surface_reg = r100_set_surface_reg, .clear_surface_reg = r100_clear_surface_reg, + .bandwidth_update = &r520_bandwidth_update, }; /* diff --git a/drivers/gpu/drm/radeon/radeon_device.c b/drivers/gpu/drm/radeon/radeon_device.c index f23083bbba3f..f78db5c8008c 100644 --- a/drivers/gpu/drm/radeon/radeon_device.c +++ b/drivers/gpu/drm/radeon/radeon_device.c @@ -561,6 +561,11 @@ int radeon_device_init(struct radeon_device *rdev, radeon_combios_asic_init(rdev->ddev); } } + /* Initialize clocks */ + r = radeon_clocks_init(rdev); + if (r) { + return r; + } /* Get vram informations */ radeon_vram_info(rdev); @@ -572,11 +577,6 @@ int radeon_device_init(struct radeon_device *rdev, (unsigned)rdev->mc.aper_size >> 20); DRM_INFO("RAM width %dbits %cDR\n", rdev->mc.vram_width, rdev->mc.vram_is_ddr ? 'D' : 'S'); - /* Initialize clocks */ - r = radeon_clocks_init(rdev); - if (r) { - return r; - } /* Initialize memory controller (also test AGP) */ r = radeon_mc_init(rdev); if (r) { diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c index bc312f3d9a0a..a8fa1bb84cf7 100644 --- a/drivers/gpu/drm/radeon/radeon_display.c +++ b/drivers/gpu/drm/radeon/radeon_display.c @@ -187,6 +187,7 @@ static void radeon_crtc_init(struct drm_device *dev, int index) drm_mode_crtc_set_gamma_size(&radeon_crtc->base, 256); radeon_crtc->crtc_id = index; + rdev->mode_info.crtcs[index] = radeon_crtc; radeon_crtc->mode_set.crtc = &radeon_crtc->base; radeon_crtc->mode_set.connectors = (struct drm_connector **)(radeon_crtc + 1); @@ -661,36 +662,51 @@ void radeon_modeset_fini(struct radeon_device *rdev) } } -void radeon_init_disp_bandwidth(struct drm_device *dev) +bool radeon_crtc_scaling_mode_fixup(struct drm_crtc *crtc, + struct drm_display_mode *mode, + struct drm_display_mode *adjusted_mode) { - struct radeon_device *rdev = dev->dev_private; - struct drm_display_mode *modes[2]; - int pixel_bytes[2]; - struct drm_crtc *crtc; - - pixel_bytes[0] = pixel_bytes[1] = 0; - modes[0] = modes[1] = NULL; - - list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { - struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); + struct drm_device *dev = crtc->dev; + struct drm_encoder *encoder; + struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); + struct radeon_encoder *radeon_encoder; + bool first = true; - if (crtc->enabled && crtc->fb) { - modes[radeon_crtc->crtc_id] = &crtc->mode; - pixel_bytes[radeon_crtc->crtc_id] = crtc->fb->bits_per_pixel / 8; + list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { + radeon_encoder = to_radeon_encoder(encoder); + if (encoder->crtc != crtc) + continue; + if (first) { + radeon_crtc->rmx_type = radeon_encoder->rmx_type; + radeon_crtc->devices = radeon_encoder->devices; + memcpy(&radeon_crtc->native_mode, + &radeon_encoder->native_mode, + sizeof(struct radeon_native_mode)); + first = false; + } else { + if (radeon_crtc->rmx_type != radeon_encoder->rmx_type) { + /* WARNING: Right now this can't happen but + * in the future we need to check that scaling + * are consistent accross different encoder + * (ie all encoder can work with the same + * scaling). + */ + DRM_ERROR("Scaling not consistent accross encoder.\n"); + return false; + } } } - - if (ASIC_IS_AVIVO(rdev)) { - radeon_init_disp_bw_avivo(dev, - modes[0], - pixel_bytes[0], - modes[1], - pixel_bytes[1]); + if (radeon_crtc->rmx_type != RMX_OFF) { + fixed20_12 a, b; + a.full = rfixed_const(crtc->mode.vdisplay); + b.full = rfixed_const(radeon_crtc->native_mode.panel_xres); + radeon_crtc->vsc.full = rfixed_div(a, b); + a.full = rfixed_const(crtc->mode.hdisplay); + b.full = rfixed_const(radeon_crtc->native_mode.panel_yres); + radeon_crtc->hsc.full = rfixed_div(a, b); } else { - radeon_init_disp_bw_legacy(dev, - modes[0], - pixel_bytes[0], - modes[1], - pixel_bytes[1]); + radeon_crtc->vsc.full = rfixed_const(1); + radeon_crtc->hsc.full = rfixed_const(1); } + return true; } diff --git a/drivers/gpu/drm/radeon/radeon_encoders.c b/drivers/gpu/drm/radeon/radeon_encoders.c index ea15284e7580..0a92706eac19 100644 --- a/drivers/gpu/drm/radeon/radeon_encoders.c +++ b/drivers/gpu/drm/radeon/radeon_encoders.c @@ -154,7 +154,6 @@ void radeon_rmx_mode_fixup(struct drm_encoder *encoder, if (mode->hdisplay < native_mode->panel_xres || mode->vdisplay < native_mode->panel_yres) { - radeon_encoder->flags |= RADEON_USE_RMX; if (ASIC_IS_AVIVO(rdev)) { adjusted_mode->hdisplay = native_mode->panel_xres; adjusted_mode->vdisplay = native_mode->panel_yres; @@ -197,15 +196,13 @@ void radeon_rmx_mode_fixup(struct drm_encoder *encoder, } } + static bool radeon_atom_mode_fixup(struct drm_encoder *encoder, struct drm_display_mode *mode, struct drm_display_mode *adjusted_mode) { - struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); - radeon_encoder->flags &= ~RADEON_USE_RMX; - drm_mode_set_crtcinfo(adjusted_mode, 0); if (radeon_encoder->rmx_type != RMX_OFF) @@ -808,234 +805,6 @@ atombios_dig_transmitter_setup(struct drm_encoder *encoder, int action) } -static void atom_rv515_force_tv_scaler(struct radeon_device *rdev) -{ - - WREG32(0x659C, 0x0); - WREG32(0x6594, 0x705); - WREG32(0x65A4, 0x10001); - WREG32(0x65D8, 0x0); - WREG32(0x65B0, 0x0); - WREG32(0x65C0, 0x0); - WREG32(0x65D4, 0x0); - WREG32(0x6578, 0x0); - WREG32(0x657C, 0x841880A8); - WREG32(0x6578, 0x1); - WREG32(0x657C, 0x84208680); - WREG32(0x6578, 0x2); - WREG32(0x657C, 0xBFF880B0); - WREG32(0x6578, 0x100); - WREG32(0x657C, 0x83D88088); - WREG32(0x6578, 0x101); - WREG32(0x657C, 0x84608680); - WREG32(0x6578, 0x102); - WREG32(0x657C, 0xBFF080D0); - WREG32(0x6578, 0x200); - WREG32(0x657C, 0x83988068); - WREG32(0x6578, 0x201); - WREG32(0x657C, 0x84A08680); - WREG32(0x6578, 0x202); - WREG32(0x657C, 0xBFF080F8); - WREG32(0x6578, 0x300); - WREG32(0x657C, 0x83588058); - WREG32(0x6578, 0x301); - WREG32(0x657C, 0x84E08660); - WREG32(0x6578, 0x302); - WREG32(0x657C, 0xBFF88120); - WREG32(0x6578, 0x400); - WREG32(0x657C, 0x83188040); - WREG32(0x6578, 0x401); - WREG32(0x657C, 0x85008660); - WREG32(0x6578, 0x402); - WREG32(0x657C, 0xBFF88150); - WREG32(0x6578, 0x500); - WREG32(0x657C, 0x82D88030); - WREG32(0x6578, 0x501); - WREG32(0x657C, 0x85408640); - WREG32(0x6578, 0x502); - WREG32(0x657C, 0xBFF88180); - WREG32(0x6578, 0x600); - WREG32(0x657C, 0x82A08018); - WREG32(0x6578, 0x601); - WREG32(0x657C, 0x85808620); - WREG32(0x6578, 0x602); - WREG32(0x657C, 0xBFF081B8); - WREG32(0x6578, 0x700); - WREG32(0x657C, 0x82608010); - WREG32(0x6578, 0x701); - WREG32(0x657C, 0x85A08600); - WREG32(0x6578, 0x702); - WREG32(0x657C, 0x800081F0); - WREG32(0x6578, 0x800); - WREG32(0x657C, 0x8228BFF8); - WREG32(0x6578, 0x801); - WREG32(0x657C, 0x85E085E0); - WREG32(0x6578, 0x802); - WREG32(0x657C, 0xBFF88228); - WREG32(0x6578, 0x10000); - WREG32(0x657C, 0x82A8BF00); - WREG32(0x6578, 0x10001); - WREG32(0x657C, 0x82A08CC0); - WREG32(0x6578, 0x10002); - WREG32(0x657C, 0x8008BEF8); - WREG32(0x6578, 0x10100); - WREG32(0x657C, 0x81F0BF28); - WREG32(0x6578, 0x10101); - WREG32(0x657C, 0x83608CA0); - WREG32(0x6578, 0x10102); - WREG32(0x657C, 0x8018BED0); - WREG32(0x6578, 0x10200); - WREG32(0x657C, 0x8148BF38); - WREG32(0x6578, 0x10201); - WREG32(0x657C, 0x84408C80); - WREG32(0x6578, 0x10202); - WREG32(0x657C, 0x8008BEB8); - WREG32(0x6578, 0x10300); - WREG32(0x657C, 0x80B0BF78); - WREG32(0x6578, 0x10301); - WREG32(0x657C, 0x85008C20); - WREG32(0x6578, 0x10302); - WREG32(0x657C, 0x8020BEA0); - WREG32(0x6578, 0x10400); - WREG32(0x657C, 0x8028BF90); - WREG32(0x6578, 0x10401); - WREG32(0x657C, 0x85E08BC0); - WREG32(0x6578, 0x10402); - WREG32(0x657C, 0x8018BE90); - WREG32(0x6578, 0x10500); - WREG32(0x657C, 0xBFB8BFB0); - WREG32(0x6578, 0x10501); - WREG32(0x657C, 0x86C08B40); - WREG32(0x6578, 0x10502); - WREG32(0x657C, 0x8010BE90); - WREG32(0x6578, 0x10600); - WREG32(0x657C, 0xBF58BFC8); - WREG32(0x6578, 0x10601); - WREG32(0x657C, 0x87A08AA0); - WREG32(0x6578, 0x10602); - WREG32(0x657C, 0x8010BE98); - WREG32(0x6578, 0x10700); - WREG32(0x657C, 0xBF10BFF0); - WREG32(0x6578, 0x10701); - WREG32(0x657C, 0x886089E0); - WREG32(0x6578, 0x10702); - WREG32(0x657C, 0x8018BEB0); - WREG32(0x6578, 0x10800); - WREG32(0x657C, 0xBED8BFE8); - WREG32(0x6578, 0x10801); - WREG32(0x657C, 0x89408940); - WREG32(0x6578, 0x10802); - WREG32(0x657C, 0xBFE8BED8); - WREG32(0x6578, 0x20000); - WREG32(0x657C, 0x80008000); - WREG32(0x6578, 0x20001); - WREG32(0x657C, 0x90008000); - WREG32(0x6578, 0x20002); - WREG32(0x657C, 0x80008000); - WREG32(0x6578, 0x20003); - WREG32(0x657C, 0x80008000); - WREG32(0x6578, 0x20100); - WREG32(0x657C, 0x80108000); - WREG32(0x6578, 0x20101); - WREG32(0x657C, 0x8FE0BF70); - WREG32(0x6578, 0x20102); - WREG32(0x657C, 0xBFE880C0); - WREG32(0x6578, 0x20103); - WREG32(0x657C, 0x80008000); - WREG32(0x6578, 0x20200); - WREG32(0x657C, 0x8018BFF8); - WREG32(0x6578, 0x20201); - WREG32(0x657C, 0x8F80BF08); - WREG32(0x6578, 0x20202); - WREG32(0x657C, 0xBFD081A0); - WREG32(0x6578, 0x20203); - WREG32(0x657C, 0xBFF88000); - WREG32(0x6578, 0x20300); - WREG32(0x657C, 0x80188000); - WREG32(0x6578, 0x20301); - WREG32(0x657C, 0x8EE0BEC0); - WREG32(0x6578, 0x20302); - WREG32(0x657C, 0xBFB082A0); - WREG32(0x6578, 0x20303); - WREG32(0x657C, 0x80008000); - WREG32(0x6578, 0x20400); - WREG32(0x657C, 0x80188000); - WREG32(0x6578, 0x20401); - WREG32(0x657C, 0x8E00BEA0); - WREG32(0x6578, 0x20402); - WREG32(0x657C, 0xBF8883C0); - WREG32(0x6578, 0x20403); - WREG32(0x657C, 0x80008000); - WREG32(0x6578, 0x20500); - WREG32(0x657C, 0x80188000); - WREG32(0x6578, 0x20501); - WREG32(0x657C, 0x8D00BE90); - WREG32(0x6578, 0x20502); - WREG32(0x657C, 0xBF588500); - WREG32(0x6578, 0x20503); - WREG32(0x657C, 0x80008008); - WREG32(0x6578, 0x20600); - WREG32(0x657C, 0x80188000); - WREG32(0x6578, 0x20601); - WREG32(0x657C, 0x8BC0BE98); - WREG32(0x6578, 0x20602); - WREG32(0x657C, 0xBF308660); - WREG32(0x6578, 0x20603); - WREG32(0x657C, 0x80008008); - WREG32(0x6578, 0x20700); - WREG32(0x657C, 0x80108000); - WREG32(0x6578, 0x20701); - WREG32(0x657C, 0x8A80BEB0); - WREG32(0x6578, 0x20702); - WREG32(0x657C, 0xBF0087C0); - WREG32(0x6578, 0x20703); - WREG32(0x657C, 0x80008008); - WREG32(0x6578, 0x20800); - WREG32(0x657C, 0x80108000); - WREG32(0x6578, 0x20801); - WREG32(0x657C, 0x8920BED0); - WREG32(0x6578, 0x20802); - WREG32(0x657C, 0xBED08920); - WREG32(0x6578, 0x20803); - WREG32(0x657C, 0x80008010); - WREG32(0x6578, 0x30000); - WREG32(0x657C, 0x90008000); - WREG32(0x6578, 0x30001); - WREG32(0x657C, 0x80008000); - WREG32(0x6578, 0x30100); - WREG32(0x657C, 0x8FE0BF90); - WREG32(0x6578, 0x30101); - WREG32(0x657C, 0xBFF880A0); - WREG32(0x6578, 0x30200); - WREG32(0x657C, 0x8F60BF40); - WREG32(0x6578, 0x30201); - WREG32(0x657C, 0xBFE88180); - WREG32(0x6578, 0x30300); - WREG32(0x657C, 0x8EC0BF00); - WREG32(0x6578, 0x30301); - WREG32(0x657C, 0xBFC88280); - WREG32(0x6578, 0x30400); - WREG32(0x657C, 0x8DE0BEE0); - WREG32(0x6578, 0x30401); - WREG32(0x657C, 0xBFA083A0); - WREG32(0x6578, 0x30500); - WREG32(0x657C, 0x8CE0BED0); - WREG32(0x6578, 0x30501); - WREG32(0x657C, 0xBF7884E0); - WREG32(0x6578, 0x30600); - WREG32(0x657C, 0x8BA0BED8); - WREG32(0x6578, 0x30601); - WREG32(0x657C, 0xBF508640); - WREG32(0x6578, 0x30700); - WREG32(0x657C, 0x8A60BEE8); - WREG32(0x6578, 0x30701); - WREG32(0x657C, 0xBF2087A0); - WREG32(0x6578, 0x30800); - WREG32(0x657C, 0x8900BF00); - WREG32(0x6578, 0x30801); - WREG32(0x657C, 0xBF008900); -} - static void atombios_yuv_setup(struct drm_encoder *encoder, bool enable) { @@ -1073,129 +842,6 @@ atombios_yuv_setup(struct drm_encoder *encoder, bool enable) WREG32(reg, temp); } -static void -atombios_overscan_setup(struct drm_encoder *encoder, - struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode) -{ - struct drm_device *dev = encoder->dev; - struct radeon_device *rdev = dev->dev_private; - struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); - struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc); - SET_CRTC_OVERSCAN_PS_ALLOCATION args; - int index = GetIndexIntoMasterTable(COMMAND, SetCRTC_OverScan); - - memset(&args, 0, sizeof(args)); - - args.usOverscanRight = 0; - args.usOverscanLeft = 0; - args.usOverscanBottom = 0; - args.usOverscanTop = 0; - args.ucCRTC = radeon_crtc->crtc_id; - - if (radeon_encoder->flags & RADEON_USE_RMX) { - if (radeon_encoder->rmx_type == RMX_FULL) { - args.usOverscanRight = 0; - args.usOverscanLeft = 0; - args.usOverscanBottom = 0; - args.usOverscanTop = 0; - } else if (radeon_encoder->rmx_type == RMX_CENTER) { - args.usOverscanTop = (adjusted_mode->crtc_vdisplay - mode->crtc_vdisplay) / 2; - args.usOverscanBottom = (adjusted_mode->crtc_vdisplay - mode->crtc_vdisplay) / 2; - args.usOverscanLeft = (adjusted_mode->crtc_hdisplay - mode->crtc_hdisplay) / 2; - args.usOverscanRight = (adjusted_mode->crtc_hdisplay - mode->crtc_hdisplay) / 2; - } else if (radeon_encoder->rmx_type == RMX_ASPECT) { - int a1 = mode->crtc_vdisplay * adjusted_mode->crtc_hdisplay; - int a2 = adjusted_mode->crtc_vdisplay * mode->crtc_hdisplay; - - if (a1 > a2) { - args.usOverscanLeft = (adjusted_mode->crtc_hdisplay - (a2 / mode->crtc_vdisplay)) / 2; - args.usOverscanRight = (adjusted_mode->crtc_hdisplay - (a2 / mode->crtc_vdisplay)) / 2; - } else if (a2 > a1) { - args.usOverscanLeft = (adjusted_mode->crtc_vdisplay - (a1 / mode->crtc_hdisplay)) / 2; - args.usOverscanRight = (adjusted_mode->crtc_vdisplay - (a1 / mode->crtc_hdisplay)) / 2; - } - } - } - - atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); - -} - -static void -atombios_scaler_setup(struct drm_encoder *encoder) -{ - struct drm_device *dev = encoder->dev; - struct radeon_device *rdev = dev->dev_private; - struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); - struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc); - ENABLE_SCALER_PS_ALLOCATION args; - int index = GetIndexIntoMasterTable(COMMAND, EnableScaler); - /* fixme - fill in enc_priv for atom dac */ - enum radeon_tv_std tv_std = TV_STD_NTSC; - - if (!ASIC_IS_AVIVO(rdev) && radeon_crtc->crtc_id) - return; - - memset(&args, 0, sizeof(args)); - - args.ucScaler = radeon_crtc->crtc_id; - - if (radeon_encoder->devices & (ATOM_DEVICE_TV_SUPPORT)) { - switch (tv_std) { - case TV_STD_NTSC: - default: - args.ucTVStandard = ATOM_TV_NTSC; - break; - case TV_STD_PAL: - args.ucTVStandard = ATOM_TV_PAL; - break; - case TV_STD_PAL_M: - args.ucTVStandard = ATOM_TV_PALM; - break; - case TV_STD_PAL_60: - args.ucTVStandard = ATOM_TV_PAL60; - break; - case TV_STD_NTSC_J: - args.ucTVStandard = ATOM_TV_NTSCJ; - break; - case TV_STD_SCART_PAL: - args.ucTVStandard = ATOM_TV_PAL; /* ??? */ - break; - case TV_STD_SECAM: - args.ucTVStandard = ATOM_TV_SECAM; - break; - case TV_STD_PAL_CN: - args.ucTVStandard = ATOM_TV_PALCN; - break; - } - args.ucEnable = SCALER_ENABLE_MULTITAP_MODE; - } else if (radeon_encoder->devices & (ATOM_DEVICE_CV_SUPPORT)) { - args.ucTVStandard = ATOM_TV_CV; - args.ucEnable = SCALER_ENABLE_MULTITAP_MODE; - } else if (radeon_encoder->flags & RADEON_USE_RMX) { - if (radeon_encoder->rmx_type == RMX_FULL) - args.ucEnable = ATOM_SCALER_EXPANSION; - else if (radeon_encoder->rmx_type == RMX_CENTER) - args.ucEnable = ATOM_SCALER_CENTER; - else if (radeon_encoder->rmx_type == RMX_ASPECT) - args.ucEnable = ATOM_SCALER_EXPANSION; - } else { - if (ASIC_IS_AVIVO(rdev)) - args.ucEnable = ATOM_SCALER_DISABLE; - else - args.ucEnable = ATOM_SCALER_CENTER; - } - - atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); - - if (radeon_encoder->devices & (ATOM_DEVICE_CV_SUPPORT | ATOM_DEVICE_TV_SUPPORT) - && rdev->family >= CHIP_RV515 && rdev->family <= CHIP_RV570) { - atom_rv515_force_tv_scaler(rdev); - } - -} - static void radeon_atom_encoder_dpms(struct drm_encoder *encoder, int mode) { @@ -1448,8 +1094,6 @@ radeon_atom_encoder_mode_set(struct drm_encoder *encoder, radeon_encoder->pixel_clock = adjusted_mode->clock; radeon_atombios_encoder_crtc_scratch_regs(encoder, radeon_crtc->crtc_id); - atombios_overscan_setup(encoder, mode, adjusted_mode); - atombios_scaler_setup(encoder); atombios_set_encoder_crtc_source(encoder); if (ASIC_IS_AVIVO(rdev)) { @@ -1667,6 +1311,7 @@ radeon_add_atom_encoder(struct drm_device *dev, uint32_t encoder_id, uint32_t su radeon_encoder->encoder_id = encoder_id; radeon_encoder->devices = supported_device; + radeon_encoder->rmx_type = RMX_OFF; switch (radeon_encoder->encoder_id) { case ENCODER_OBJECT_ID_INTERNAL_LVDS: @@ -1700,14 +1345,8 @@ radeon_add_atom_encoder(struct drm_device *dev, uint32_t encoder_id, uint32_t su case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA: case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: - if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) { - radeon_encoder->rmx_type = RMX_FULL; - drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs, DRM_MODE_ENCODER_LVDS); - radeon_encoder->enc_priv = radeon_atombios_get_lvds_info(radeon_encoder); - } else { - drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs, DRM_MODE_ENCODER_TMDS); - radeon_encoder->enc_priv = radeon_atombios_set_dig_info(radeon_encoder); - } + drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs, DRM_MODE_ENCODER_TMDS); + radeon_encoder->enc_priv = radeon_atombios_set_dig_info(radeon_encoder); drm_encoder_helper_add(encoder, &radeon_atom_dig_helper_funcs); break; } diff --git a/drivers/gpu/drm/radeon/radeon_legacy_crtc.c b/drivers/gpu/drm/radeon/radeon_legacy_crtc.c index 0613790e2a5b..7d06dc98a42a 100644 --- a/drivers/gpu/drm/radeon/radeon_legacy_crtc.c +++ b/drivers/gpu/drm/radeon/radeon_legacy_crtc.c @@ -29,6 +29,171 @@ #include "radeon_fixed.h" #include "radeon.h" +static void radeon_legacy_rmx_mode_set(struct drm_crtc *crtc, + struct drm_display_mode *mode, + struct drm_display_mode *adjusted_mode) +{ + struct drm_device *dev = crtc->dev; + struct radeon_device *rdev = dev->dev_private; + struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); + int xres = mode->hdisplay; + int yres = mode->vdisplay; + bool hscale = true, vscale = true; + int hsync_wid; + int vsync_wid; + int hsync_start; + int blank_width; + u32 scale, inc, crtc_more_cntl; + u32 fp_horz_stretch, fp_vert_stretch, fp_horz_vert_active; + u32 fp_h_sync_strt_wid, fp_crtc_h_total_disp; + u32 fp_v_sync_strt_wid, fp_crtc_v_total_disp; + struct radeon_native_mode *native_mode = &radeon_crtc->native_mode; + + fp_vert_stretch = RREG32(RADEON_FP_VERT_STRETCH) & + (RADEON_VERT_STRETCH_RESERVED | + RADEON_VERT_AUTO_RATIO_INC); + fp_horz_stretch = RREG32(RADEON_FP_HORZ_STRETCH) & + (RADEON_HORZ_FP_LOOP_STRETCH | + RADEON_HORZ_AUTO_RATIO_INC); + + crtc_more_cntl = 0; + if ((rdev->family == CHIP_RS100) || + (rdev->family == CHIP_RS200)) { + /* This is to workaround the asic bug for RMX, some versions + of BIOS dosen't have this register initialized correctly. */ + crtc_more_cntl |= RADEON_CRTC_H_CUTOFF_ACTIVE_EN; + } + + + fp_crtc_h_total_disp = ((((mode->crtc_htotal / 8) - 1) & 0x3ff) + | ((((mode->crtc_hdisplay / 8) - 1) & 0x1ff) << 16)); + + hsync_wid = (mode->crtc_hsync_end - mode->crtc_hsync_start) / 8; + if (!hsync_wid) + hsync_wid = 1; + hsync_start = mode->crtc_hsync_start - 8; + + fp_h_sync_strt_wid = ((hsync_start & 0x1fff) + | ((hsync_wid & 0x3f) << 16) + | ((mode->flags & DRM_MODE_FLAG_NHSYNC) + ? RADEON_CRTC_H_SYNC_POL + : 0)); + + fp_crtc_v_total_disp = (((mode->crtc_vtotal - 1) & 0xffff) + | ((mode->crtc_vdisplay - 1) << 16)); + + vsync_wid = mode->crtc_vsync_end - mode->crtc_vsync_start; + if (!vsync_wid) + vsync_wid = 1; + + fp_v_sync_strt_wid = (((mode->crtc_vsync_start - 1) & 0xfff) + | ((vsync_wid & 0x1f) << 16) + | ((mode->flags & DRM_MODE_FLAG_NVSYNC) + ? RADEON_CRTC_V_SYNC_POL + : 0)); + + fp_horz_vert_active = 0; + + if (native_mode->panel_xres == 0 || + native_mode->panel_yres == 0) { + hscale = false; + vscale = false; + } else { + if (xres > native_mode->panel_xres) + xres = native_mode->panel_xres; + if (yres > native_mode->panel_yres) + yres = native_mode->panel_yres; + + if (xres == native_mode->panel_xres) + hscale = false; + if (yres == native_mode->panel_yres) + vscale = false; + } + + switch (radeon_crtc->rmx_type) { + case RMX_FULL: + case RMX_ASPECT: + if (!hscale) + fp_horz_stretch |= ((xres/8-1) << 16); + else { + inc = (fp_horz_stretch & RADEON_HORZ_AUTO_RATIO_INC) ? 1 : 0; + scale = ((xres + inc) * RADEON_HORZ_STRETCH_RATIO_MAX) + / native_mode->panel_xres + 1; + fp_horz_stretch |= (((scale) & RADEON_HORZ_STRETCH_RATIO_MASK) | + RADEON_HORZ_STRETCH_BLEND | + RADEON_HORZ_STRETCH_ENABLE | + ((native_mode->panel_xres/8-1) << 16)); + } + + if (!vscale) + fp_vert_stretch |= ((yres-1) << 12); + else { + inc = (fp_vert_stretch & RADEON_VERT_AUTO_RATIO_INC) ? 1 : 0; + scale = ((yres + inc) * RADEON_VERT_STRETCH_RATIO_MAX) + / native_mode->panel_yres + 1; + fp_vert_stretch |= (((scale) & RADEON_VERT_STRETCH_RATIO_MASK) | + RADEON_VERT_STRETCH_ENABLE | + RADEON_VERT_STRETCH_BLEND | + ((native_mode->panel_yres-1) << 12)); + } + break; + case RMX_CENTER: + fp_horz_stretch |= ((xres/8-1) << 16); + fp_vert_stretch |= ((yres-1) << 12); + + crtc_more_cntl |= (RADEON_CRTC_AUTO_HORZ_CENTER_EN | + RADEON_CRTC_AUTO_VERT_CENTER_EN); + + blank_width = (mode->crtc_hblank_end - mode->crtc_hblank_start) / 8; + if (blank_width > 110) + blank_width = 110; + + fp_crtc_h_total_disp = (((blank_width) & 0x3ff) + | ((((mode->crtc_hdisplay / 8) - 1) & 0x1ff) << 16)); + + hsync_wid = (mode->crtc_hsync_end - mode->crtc_hsync_start) / 8; + if (!hsync_wid) + hsync_wid = 1; + + fp_h_sync_strt_wid = ((((mode->crtc_hsync_start - mode->crtc_hblank_start) / 8) & 0x1fff) + | ((hsync_wid & 0x3f) << 16) + | ((mode->flags & DRM_MODE_FLAG_NHSYNC) + ? RADEON_CRTC_H_SYNC_POL + : 0)); + + fp_crtc_v_total_disp = (((mode->crtc_vblank_end - mode->crtc_vblank_start) & 0xffff) + | ((mode->crtc_vdisplay - 1) << 16)); + + vsync_wid = mode->crtc_vsync_end - mode->crtc_vsync_start; + if (!vsync_wid) + vsync_wid = 1; + + fp_v_sync_strt_wid = ((((mode->crtc_vsync_start - mode->crtc_vblank_start) & 0xfff) + | ((vsync_wid & 0x1f) << 16) + | ((mode->flags & DRM_MODE_FLAG_NVSYNC) + ? RADEON_CRTC_V_SYNC_POL + : 0))); + + fp_horz_vert_active = (((native_mode->panel_yres) & 0xfff) | + (((native_mode->panel_xres / 8) & 0x1ff) << 16)); + break; + case RMX_OFF: + default: + fp_horz_stretch |= ((xres/8-1) << 16); + fp_vert_stretch |= ((yres-1) << 12); + break; + } + + WREG32(RADEON_FP_HORZ_STRETCH, fp_horz_stretch); + WREG32(RADEON_FP_VERT_STRETCH, fp_vert_stretch); + WREG32(RADEON_CRTC_MORE_CNTL, crtc_more_cntl); + WREG32(RADEON_FP_HORZ_VERT_ACTIVE, fp_horz_vert_active); + WREG32(RADEON_FP_H_SYNC_STRT_WID, fp_h_sync_strt_wid); + WREG32(RADEON_FP_V_SYNC_STRT_WID, fp_v_sync_strt_wid); + WREG32(RADEON_FP_CRTC_H_TOTAL_DISP, fp_crtc_h_total_disp); + WREG32(RADEON_FP_CRTC_V_TOTAL_DISP, fp_crtc_v_total_disp); +} + void radeon_restore_common_regs(struct drm_device *dev) { /* don't need this yet */ @@ -757,6 +922,8 @@ static bool radeon_crtc_mode_fixup(struct drm_crtc *crtc, struct drm_display_mode *mode, struct drm_display_mode *adjusted_mode) { + if (!radeon_crtc_scaling_mode_fixup(crtc, mode, adjusted_mode)) + return false; return true; } @@ -765,16 +932,25 @@ static int radeon_crtc_mode_set(struct drm_crtc *crtc, struct drm_display_mode *adjusted_mode, int x, int y, struct drm_framebuffer *old_fb) { - - DRM_DEBUG("\n"); + struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); + struct drm_device *dev = crtc->dev; + struct radeon_device *rdev = dev->dev_private; /* TODO TV */ - radeon_crtc_set_base(crtc, x, y, old_fb); radeon_set_crtc_timing(crtc, adjusted_mode); radeon_set_pll(crtc, adjusted_mode); - radeon_init_disp_bandwidth(crtc->dev); - + radeon_bandwidth_update(rdev); + if (radeon_crtc->crtc_id == 0) { + radeon_legacy_rmx_mode_set(crtc, mode, adjusted_mode); + } else { + if (radeon_crtc->rmx_type != RMX_OFF) { + /* FIXME: only first crtc has rmx what should we + * do ? + */ + DRM_ERROR("Mode need scaling but only first crtc can do that.\n"); + } + } return 0; } @@ -805,478 +981,3 @@ void radeon_legacy_init_crtc(struct drm_device *dev, radeon_crtc->crtc_offset = RADEON_CRTC2_H_TOTAL_DISP - RADEON_CRTC_H_TOTAL_DISP; drm_crtc_helper_add(&radeon_crtc->base, &legacy_helper_funcs); } - -void radeon_init_disp_bw_legacy(struct drm_device *dev, - struct drm_display_mode *mode1, - uint32_t pixel_bytes1, - struct drm_display_mode *mode2, - uint32_t pixel_bytes2) -{ - struct radeon_device *rdev = dev->dev_private; - fixed20_12 trcd_ff, trp_ff, tras_ff, trbs_ff, tcas_ff; - fixed20_12 sclk_ff, mclk_ff, sclk_eff_ff, sclk_delay_ff; - fixed20_12 peak_disp_bw, mem_bw, pix_clk, pix_clk2, temp_ff, crit_point_ff; - uint32_t temp, data, mem_trcd, mem_trp, mem_tras; - fixed20_12 memtcas_ff[8] = { - fixed_init(1), - fixed_init(2), - fixed_init(3), - fixed_init(0), - fixed_init_half(1), - fixed_init_half(2), - fixed_init(0), - }; - fixed20_12 memtcas_rs480_ff[8] = { - fixed_init(0), - fixed_init(1), - fixed_init(2), - fixed_init(3), - fixed_init(0), - fixed_init_half(1), - fixed_init_half(2), - fixed_init_half(3), - }; - fixed20_12 memtcas2_ff[8] = { - fixed_init(0), - fixed_init(1), - fixed_init(2), - fixed_init(3), - fixed_init(4), - fixed_init(5), - fixed_init(6), - fixed_init(7), - }; - fixed20_12 memtrbs[8] = { - fixed_init(1), - fixed_init_half(1), - fixed_init(2), - fixed_init_half(2), - fixed_init(3), - fixed_init_half(3), - fixed_init(4), - fixed_init_half(4) - }; - fixed20_12 memtrbs_r4xx[8] = { - fixed_init(4), - fixed_init(5), - fixed_init(6), - fixed_init(7), - fixed_init(8), - fixed_init(9), - fixed_init(10), - fixed_init(11) - }; - fixed20_12 min_mem_eff; - fixed20_12 mc_latency_sclk, mc_latency_mclk, k1; - fixed20_12 cur_latency_mclk, cur_latency_sclk; - fixed20_12 disp_latency, disp_latency_overhead, disp_drain_rate, - disp_drain_rate2, read_return_rate; - fixed20_12 time_disp1_drop_priority; - int c; - int cur_size = 16; /* in octawords */ - int critical_point = 0, critical_point2; -/* uint32_t read_return_rate, time_disp1_drop_priority; */ - int stop_req, max_stop_req; - - min_mem_eff.full = rfixed_const_8(0); - /* get modes */ - if ((rdev->disp_priority == 2) && ASIC_IS_R300(rdev)) { - uint32_t mc_init_misc_lat_timer = RREG32(R300_MC_INIT_MISC_LAT_TIMER); - mc_init_misc_lat_timer &= ~(R300_MC_DISP1R_INIT_LAT_MASK << R300_MC_DISP1R_INIT_LAT_SHIFT); - mc_init_misc_lat_timer &= ~(R300_MC_DISP0R_INIT_LAT_MASK << R300_MC_DISP0R_INIT_LAT_SHIFT); - /* check crtc enables */ - if (mode2) - mc_init_misc_lat_timer |= (1 << R300_MC_DISP1R_INIT_LAT_SHIFT); - if (mode1) - mc_init_misc_lat_timer |= (1 << R300_MC_DISP0R_INIT_LAT_SHIFT); - WREG32(R300_MC_INIT_MISC_LAT_TIMER, mc_init_misc_lat_timer); - } - - /* - * determine is there is enough bw for current mode - */ - mclk_ff.full = rfixed_const(rdev->clock.default_mclk); - temp_ff.full = rfixed_const(100); - mclk_ff.full = rfixed_div(mclk_ff, temp_ff); - sclk_ff.full = rfixed_const(rdev->clock.default_sclk); - sclk_ff.full = rfixed_div(sclk_ff, temp_ff); - - temp = (rdev->mc.vram_width / 8) * (rdev->mc.vram_is_ddr ? 2 : 1); - temp_ff.full = rfixed_const(temp); - mem_bw.full = rfixed_mul(mclk_ff, temp_ff); - - pix_clk.full = 0; - pix_clk2.full = 0; - peak_disp_bw.full = 0; - if (mode1) { - temp_ff.full = rfixed_const(1000); - pix_clk.full = rfixed_const(mode1->clock); /* convert to fixed point */ - pix_clk.full = rfixed_div(pix_clk, temp_ff); - temp_ff.full = rfixed_const(pixel_bytes1); - peak_disp_bw.full += rfixed_mul(pix_clk, temp_ff); - } - if (mode2) { - temp_ff.full = rfixed_const(1000); - pix_clk2.full = rfixed_const(mode2->clock); /* convert to fixed point */ - pix_clk2.full = rfixed_div(pix_clk2, temp_ff); - temp_ff.full = rfixed_const(pixel_bytes2); - peak_disp_bw.full += rfixed_mul(pix_clk2, temp_ff); - } - - mem_bw.full = rfixed_mul(mem_bw, min_mem_eff); - if (peak_disp_bw.full >= mem_bw.full) { - DRM_ERROR("You may not have enough display bandwidth for current mode\n" - "If you have flickering problem, try to lower resolution, refresh rate, or color depth\n"); - } - - /* Get values from the EXT_MEM_CNTL register...converting its contents. */ - temp = RREG32(RADEON_MEM_TIMING_CNTL); - if ((rdev->family == CHIP_RV100) || (rdev->flags & RADEON_IS_IGP)) { /* RV100, M6, IGPs */ - mem_trcd = ((temp >> 2) & 0x3) + 1; - mem_trp = ((temp & 0x3)) + 1; - mem_tras = ((temp & 0x70) >> 4) + 1; - } else if (rdev->family == CHIP_R300 || - rdev->family == CHIP_R350) { /* r300, r350 */ - mem_trcd = (temp & 0x7) + 1; - mem_trp = ((temp >> 8) & 0x7) + 1; - mem_tras = ((temp >> 11) & 0xf) + 4; - } else if (rdev->family == CHIP_RV350 || - rdev->family <= CHIP_RV380) { - /* rv3x0 */ - mem_trcd = (temp & 0x7) + 3; - mem_trp = ((temp >> 8) & 0x7) + 3; - mem_tras = ((temp >> 11) & 0xf) + 6; - } else if (rdev->family == CHIP_R420 || - rdev->family == CHIP_R423 || - rdev->family == CHIP_RV410) { - /* r4xx */ - mem_trcd = (temp & 0xf) + 3; - if (mem_trcd > 15) - mem_trcd = 15; - mem_trp = ((temp >> 8) & 0xf) + 3; - if (mem_trp > 15) - mem_trp = 15; - mem_tras = ((temp >> 12) & 0x1f) + 6; - if (mem_tras > 31) - mem_tras = 31; - } else { /* RV200, R200 */ - mem_trcd = (temp & 0x7) + 1; - mem_trp = ((temp >> 8) & 0x7) + 1; - mem_tras = ((temp >> 12) & 0xf) + 4; - } - /* convert to FF */ - trcd_ff.full = rfixed_const(mem_trcd); - trp_ff.full = rfixed_const(mem_trp); - tras_ff.full = rfixed_const(mem_tras); - - /* Get values from the MEM_SDRAM_MODE_REG register...converting its */ - temp = RREG32(RADEON_MEM_SDRAM_MODE_REG); - data = (temp & (7 << 20)) >> 20; - if ((rdev->family == CHIP_RV100) || rdev->flags & RADEON_IS_IGP) { - if (rdev->family == CHIP_RS480) /* don't think rs400 */ - tcas_ff = memtcas_rs480_ff[data]; - else - tcas_ff = memtcas_ff[data]; - } else - tcas_ff = memtcas2_ff[data]; - - if (rdev->family == CHIP_RS400 || - rdev->family == CHIP_RS480) { - /* extra cas latency stored in bits 23-25 0-4 clocks */ - data = (temp >> 23) & 0x7; - if (data < 5) - tcas_ff.full += rfixed_const(data); - } - - if (ASIC_IS_R300(rdev) && !(rdev->flags & RADEON_IS_IGP)) { - /* on the R300, Tcas is included in Trbs. - */ - temp = RREG32(RADEON_MEM_CNTL); - data = (R300_MEM_NUM_CHANNELS_MASK & temp); - if (data == 1) { - if (R300_MEM_USE_CD_CH_ONLY & temp) { - temp = RREG32(R300_MC_IND_INDEX); - temp &= ~R300_MC_IND_ADDR_MASK; - temp |= R300_MC_READ_CNTL_CD_mcind; - WREG32(R300_MC_IND_INDEX, temp); - temp = RREG32(R300_MC_IND_DATA); - data = (R300_MEM_RBS_POSITION_C_MASK & temp); - } else { - temp = RREG32(R300_MC_READ_CNTL_AB); - data = (R300_MEM_RBS_POSITION_A_MASK & temp); - } - } else { - temp = RREG32(R300_MC_READ_CNTL_AB); - data = (R300_MEM_RBS_POSITION_A_MASK & temp); - } - if (rdev->family == CHIP_RV410 || - rdev->family == CHIP_R420 || - rdev->family == CHIP_R423) - trbs_ff = memtrbs_r4xx[data]; - else - trbs_ff = memtrbs[data]; - tcas_ff.full += trbs_ff.full; - } - - sclk_eff_ff.full = sclk_ff.full; - - if (rdev->flags & RADEON_IS_AGP) { - fixed20_12 agpmode_ff; - agpmode_ff.full = rfixed_const(radeon_agpmode); - temp_ff.full = rfixed_const_666(16); - sclk_eff_ff.full -= rfixed_mul(agpmode_ff, temp_ff); - } - /* TODO PCIE lanes may affect this - agpmode == 16?? */ - - if (ASIC_IS_R300(rdev)) { - sclk_delay_ff.full = rfixed_const(250); - } else { - if ((rdev->family == CHIP_RV100) || - rdev->flags & RADEON_IS_IGP) { - if (rdev->mc.vram_is_ddr) - sclk_delay_ff.full = rfixed_const(41); - else - sclk_delay_ff.full = rfixed_const(33); - } else { - if (rdev->mc.vram_width == 128) - sclk_delay_ff.full = rfixed_const(57); - else - sclk_delay_ff.full = rfixed_const(41); - } - } - - mc_latency_sclk.full = rfixed_div(sclk_delay_ff, sclk_eff_ff); - - if (rdev->mc.vram_is_ddr) { - if (rdev->mc.vram_width == 32) { - k1.full = rfixed_const(40); - c = 3; - } else { - k1.full = rfixed_const(20); - c = 1; - } - } else { - k1.full = rfixed_const(40); - c = 3; - } - - temp_ff.full = rfixed_const(2); - mc_latency_mclk.full = rfixed_mul(trcd_ff, temp_ff); - temp_ff.full = rfixed_const(c); - mc_latency_mclk.full += rfixed_mul(tcas_ff, temp_ff); - temp_ff.full = rfixed_const(4); - mc_latency_mclk.full += rfixed_mul(tras_ff, temp_ff); - mc_latency_mclk.full += rfixed_mul(trp_ff, temp_ff); - mc_latency_mclk.full += k1.full; - - mc_latency_mclk.full = rfixed_div(mc_latency_mclk, mclk_ff); - mc_latency_mclk.full += rfixed_div(temp_ff, sclk_eff_ff); - - /* - HW cursor time assuming worst case of full size colour cursor. - */ - temp_ff.full = rfixed_const((2 * (cur_size - (rdev->mc.vram_is_ddr + 1)))); - temp_ff.full += trcd_ff.full; - if (temp_ff.full < tras_ff.full) - temp_ff.full = tras_ff.full; - cur_latency_mclk.full = rfixed_div(temp_ff, mclk_ff); - - temp_ff.full = rfixed_const(cur_size); - cur_latency_sclk.full = rfixed_div(temp_ff, sclk_eff_ff); - /* - Find the total latency for the display data. - */ - disp_latency_overhead.full = rfixed_const(80); - disp_latency_overhead.full = rfixed_div(disp_latency_overhead, sclk_ff); - mc_latency_mclk.full += disp_latency_overhead.full + cur_latency_mclk.full; - mc_latency_sclk.full += disp_latency_overhead.full + cur_latency_sclk.full; - - if (mc_latency_mclk.full > mc_latency_sclk.full) - disp_latency.full = mc_latency_mclk.full; - else - disp_latency.full = mc_latency_sclk.full; - - /* setup Max GRPH_STOP_REQ default value */ - if (ASIC_IS_RV100(rdev)) - max_stop_req = 0x5c; - else - max_stop_req = 0x7c; - - if (mode1) { - /* CRTC1 - Set GRPH_BUFFER_CNTL register using h/w defined optimal values. - GRPH_STOP_REQ <= MIN[ 0x7C, (CRTC_H_DISP + 1) * (bit depth) / 0x10 ] - */ - stop_req = mode1->hdisplay * pixel_bytes1 / 16; - - if (stop_req > max_stop_req) - stop_req = max_stop_req; - - /* - Find the drain rate of the display buffer. - */ - temp_ff.full = rfixed_const((16/pixel_bytes1)); - disp_drain_rate.full = rfixed_div(pix_clk, temp_ff); - - /* - Find the critical point of the display buffer. - */ - crit_point_ff.full = rfixed_mul(disp_drain_rate, disp_latency); - crit_point_ff.full += rfixed_const_half(0); - - critical_point = rfixed_trunc(crit_point_ff); - - if (rdev->disp_priority == 2) { - critical_point = 0; - } - - /* - The critical point should never be above max_stop_req-4. Setting - GRPH_CRITICAL_CNTL = 0 will thus force high priority all the time. - */ - if (max_stop_req - critical_point < 4) - critical_point = 0; - - if (critical_point == 0 && mode2 && rdev->family == CHIP_R300) { - /* some R300 cards have problem with this set to 0, when CRTC2 is enabled.*/ - critical_point = 0x10; - } - - temp = RREG32(RADEON_GRPH_BUFFER_CNTL); - temp &= ~(RADEON_GRPH_STOP_REQ_MASK); - temp |= (stop_req << RADEON_GRPH_STOP_REQ_SHIFT); - temp &= ~(RADEON_GRPH_START_REQ_MASK); - if ((rdev->family == CHIP_R350) && - (stop_req > 0x15)) { - stop_req -= 0x10; - } - temp |= (stop_req << RADEON_GRPH_START_REQ_SHIFT); - temp |= RADEON_GRPH_BUFFER_SIZE; - temp &= ~(RADEON_GRPH_CRITICAL_CNTL | - RADEON_GRPH_CRITICAL_AT_SOF | - RADEON_GRPH_STOP_CNTL); - /* - Write the result into the register. - */ - WREG32(RADEON_GRPH_BUFFER_CNTL, ((temp & ~RADEON_GRPH_CRITICAL_POINT_MASK) | - (critical_point << RADEON_GRPH_CRITICAL_POINT_SHIFT))); - -#if 0 - if ((rdev->family == CHIP_RS400) || - (rdev->family == CHIP_RS480)) { - /* attempt to program RS400 disp regs correctly ??? */ - temp = RREG32(RS400_DISP1_REG_CNTL); - temp &= ~(RS400_DISP1_START_REQ_LEVEL_MASK | - RS400_DISP1_STOP_REQ_LEVEL_MASK); - WREG32(RS400_DISP1_REQ_CNTL1, (temp | - (critical_point << RS400_DISP1_START_REQ_LEVEL_SHIFT) | - (critical_point << RS400_DISP1_STOP_REQ_LEVEL_SHIFT))); - temp = RREG32(RS400_DMIF_MEM_CNTL1); - temp &= ~(RS400_DISP1_CRITICAL_POINT_START_MASK | - RS400_DISP1_CRITICAL_POINT_STOP_MASK); - WREG32(RS400_DMIF_MEM_CNTL1, (temp | - (critical_point << RS400_DISP1_CRITICAL_POINT_START_SHIFT) | - (critical_point << RS400_DISP1_CRITICAL_POINT_STOP_SHIFT))); - } -#endif - - DRM_DEBUG("GRPH_BUFFER_CNTL from to %x\n", - /* (unsigned int)info->SavedReg->grph_buffer_cntl, */ - (unsigned int)RREG32(RADEON_GRPH_BUFFER_CNTL)); - } - - if (mode2) { - u32 grph2_cntl; - stop_req = mode2->hdisplay * pixel_bytes2 / 16; - - if (stop_req > max_stop_req) - stop_req = max_stop_req; - - /* - Find the drain rate of the display buffer. - */ - temp_ff.full = rfixed_const((16/pixel_bytes2)); - disp_drain_rate2.full = rfixed_div(pix_clk2, temp_ff); - - grph2_cntl = RREG32(RADEON_GRPH2_BUFFER_CNTL); - grph2_cntl &= ~(RADEON_GRPH_STOP_REQ_MASK); - grph2_cntl |= (stop_req << RADEON_GRPH_STOP_REQ_SHIFT); - grph2_cntl &= ~(RADEON_GRPH_START_REQ_MASK); - if ((rdev->family == CHIP_R350) && - (stop_req > 0x15)) { - stop_req -= 0x10; - } - grph2_cntl |= (stop_req << RADEON_GRPH_START_REQ_SHIFT); - grph2_cntl |= RADEON_GRPH_BUFFER_SIZE; - grph2_cntl &= ~(RADEON_GRPH_CRITICAL_CNTL | - RADEON_GRPH_CRITICAL_AT_SOF | - RADEON_GRPH_STOP_CNTL); - - if ((rdev->family == CHIP_RS100) || - (rdev->family == CHIP_RS200)) - critical_point2 = 0; - else { - temp = (rdev->mc.vram_width * rdev->mc.vram_is_ddr + 1)/128; - temp_ff.full = rfixed_const(temp); - temp_ff.full = rfixed_mul(mclk_ff, temp_ff); - if (sclk_ff.full < temp_ff.full) - temp_ff.full = sclk_ff.full; - - read_return_rate.full = temp_ff.full; - - if (mode1) { - temp_ff.full = read_return_rate.full - disp_drain_rate.full; - time_disp1_drop_priority.full = rfixed_div(crit_point_ff, temp_ff); - } else { - time_disp1_drop_priority.full = 0; - } - crit_point_ff.full = disp_latency.full + time_disp1_drop_priority.full + disp_latency.full; - crit_point_ff.full = rfixed_mul(crit_point_ff, disp_drain_rate2); - crit_point_ff.full += rfixed_const_half(0); - - critical_point2 = rfixed_trunc(crit_point_ff); - - if (rdev->disp_priority == 2) { - critical_point2 = 0; - } - - if (max_stop_req - critical_point2 < 4) - critical_point2 = 0; - - } - - if (critical_point2 == 0 && rdev->family == CHIP_R300) { - /* some R300 cards have problem with this set to 0 */ - critical_point2 = 0x10; - } - - WREG32(RADEON_GRPH2_BUFFER_CNTL, ((grph2_cntl & ~RADEON_GRPH_CRITICAL_POINT_MASK) | - (critical_point2 << RADEON_GRPH_CRITICAL_POINT_SHIFT))); - - if ((rdev->family == CHIP_RS400) || - (rdev->family == CHIP_RS480)) { -#if 0 - /* attempt to program RS400 disp2 regs correctly ??? */ - temp = RREG32(RS400_DISP2_REQ_CNTL1); - temp &= ~(RS400_DISP2_START_REQ_LEVEL_MASK | - RS400_DISP2_STOP_REQ_LEVEL_MASK); - WREG32(RS400_DISP2_REQ_CNTL1, (temp | - (critical_point2 << RS400_DISP1_START_REQ_LEVEL_SHIFT) | - (critical_point2 << RS400_DISP1_STOP_REQ_LEVEL_SHIFT))); - temp = RREG32(RS400_DISP2_REQ_CNTL2); - temp &= ~(RS400_DISP2_CRITICAL_POINT_START_MASK | - RS400_DISP2_CRITICAL_POINT_STOP_MASK); - WREG32(RS400_DISP2_REQ_CNTL2, (temp | - (critical_point2 << RS400_DISP2_CRITICAL_POINT_START_SHIFT) | - (critical_point2 << RS400_DISP2_CRITICAL_POINT_STOP_SHIFT))); -#endif - WREG32(RS400_DISP2_REQ_CNTL1, 0x105DC1CC); - WREG32(RS400_DISP2_REQ_CNTL2, 0x2749D000); - WREG32(RS400_DMIF_MEM_CNTL1, 0x29CA71DC); - WREG32(RS400_DISP1_REQ_CNTL1, 0x28FBC3AC); - } - - DRM_DEBUG("GRPH2_BUFFER_CNTL from to %x\n", - (unsigned int)RREG32(RADEON_GRPH2_BUFFER_CNTL)); - } -} diff --git a/drivers/gpu/drm/radeon/radeon_legacy_encoders.c b/drivers/gpu/drm/radeon/radeon_legacy_encoders.c index 2c2f42de1d4c..34d0f58eb944 100644 --- a/drivers/gpu/drm/radeon/radeon_legacy_encoders.c +++ b/drivers/gpu/drm/radeon/radeon_legacy_encoders.c @@ -30,170 +30,6 @@ #include "atom.h" -static void radeon_legacy_rmx_mode_set(struct drm_encoder *encoder, - struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode) -{ - struct drm_device *dev = encoder->dev; - struct radeon_device *rdev = dev->dev_private; - struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); - int xres = mode->hdisplay; - int yres = mode->vdisplay; - bool hscale = true, vscale = true; - int hsync_wid; - int vsync_wid; - int hsync_start; - uint32_t scale, inc; - uint32_t fp_horz_stretch, fp_vert_stretch, crtc_more_cntl, fp_horz_vert_active; - uint32_t fp_h_sync_strt_wid, fp_v_sync_strt_wid, fp_crtc_h_total_disp, fp_crtc_v_total_disp; - struct radeon_native_mode *native_mode = &radeon_encoder->native_mode; - - DRM_DEBUG("\n"); - - fp_vert_stretch = RREG32(RADEON_FP_VERT_STRETCH) & - (RADEON_VERT_STRETCH_RESERVED | - RADEON_VERT_AUTO_RATIO_INC); - fp_horz_stretch = RREG32(RADEON_FP_HORZ_STRETCH) & - (RADEON_HORZ_FP_LOOP_STRETCH | - RADEON_HORZ_AUTO_RATIO_INC); - - crtc_more_cntl = 0; - if ((rdev->family == CHIP_RS100) || - (rdev->family == CHIP_RS200)) { - /* This is to workaround the asic bug for RMX, some versions - of BIOS dosen't have this register initialized correctly. */ - crtc_more_cntl |= RADEON_CRTC_H_CUTOFF_ACTIVE_EN; - } - - - fp_crtc_h_total_disp = ((((mode->crtc_htotal / 8) - 1) & 0x3ff) - | ((((mode->crtc_hdisplay / 8) - 1) & 0x1ff) << 16)); - - hsync_wid = (mode->crtc_hsync_end - mode->crtc_hsync_start) / 8; - if (!hsync_wid) - hsync_wid = 1; - hsync_start = mode->crtc_hsync_start - 8; - - fp_h_sync_strt_wid = ((hsync_start & 0x1fff) - | ((hsync_wid & 0x3f) << 16) - | ((mode->flags & DRM_MODE_FLAG_NHSYNC) - ? RADEON_CRTC_H_SYNC_POL - : 0)); - - fp_crtc_v_total_disp = (((mode->crtc_vtotal - 1) & 0xffff) - | ((mode->crtc_vdisplay - 1) << 16)); - - vsync_wid = mode->crtc_vsync_end - mode->crtc_vsync_start; - if (!vsync_wid) - vsync_wid = 1; - - fp_v_sync_strt_wid = (((mode->crtc_vsync_start - 1) & 0xfff) - | ((vsync_wid & 0x1f) << 16) - | ((mode->flags & DRM_MODE_FLAG_NVSYNC) - ? RADEON_CRTC_V_SYNC_POL - : 0)); - - fp_horz_vert_active = 0; - - if (native_mode->panel_xres == 0 || - native_mode->panel_yres == 0) { - hscale = false; - vscale = false; - } else { - if (xres > native_mode->panel_xres) - xres = native_mode->panel_xres; - if (yres > native_mode->panel_yres) - yres = native_mode->panel_yres; - - if (xres == native_mode->panel_xres) - hscale = false; - if (yres == native_mode->panel_yres) - vscale = false; - } - - if (radeon_encoder->flags & RADEON_USE_RMX) { - if (radeon_encoder->rmx_type != RMX_CENTER) { - if (!hscale) - fp_horz_stretch |= ((xres/8-1) << 16); - else { - inc = (fp_horz_stretch & RADEON_HORZ_AUTO_RATIO_INC) ? 1 : 0; - scale = ((xres + inc) * RADEON_HORZ_STRETCH_RATIO_MAX) - / native_mode->panel_xres + 1; - fp_horz_stretch |= (((scale) & RADEON_HORZ_STRETCH_RATIO_MASK) | - RADEON_HORZ_STRETCH_BLEND | - RADEON_HORZ_STRETCH_ENABLE | - ((native_mode->panel_xres/8-1) << 16)); - } - - if (!vscale) - fp_vert_stretch |= ((yres-1) << 12); - else { - inc = (fp_vert_stretch & RADEON_VERT_AUTO_RATIO_INC) ? 1 : 0; - scale = ((yres + inc) * RADEON_VERT_STRETCH_RATIO_MAX) - / native_mode->panel_yres + 1; - fp_vert_stretch |= (((scale) & RADEON_VERT_STRETCH_RATIO_MASK) | - RADEON_VERT_STRETCH_ENABLE | - RADEON_VERT_STRETCH_BLEND | - ((native_mode->panel_yres-1) << 12)); - } - } else if (radeon_encoder->rmx_type == RMX_CENTER) { - int blank_width; - - fp_horz_stretch |= ((xres/8-1) << 16); - fp_vert_stretch |= ((yres-1) << 12); - - crtc_more_cntl |= (RADEON_CRTC_AUTO_HORZ_CENTER_EN | - RADEON_CRTC_AUTO_VERT_CENTER_EN); - - blank_width = (mode->crtc_hblank_end - mode->crtc_hblank_start) / 8; - if (blank_width > 110) - blank_width = 110; - - fp_crtc_h_total_disp = (((blank_width) & 0x3ff) - | ((((mode->crtc_hdisplay / 8) - 1) & 0x1ff) << 16)); - - hsync_wid = (mode->crtc_hsync_end - mode->crtc_hsync_start) / 8; - if (!hsync_wid) - hsync_wid = 1; - - fp_h_sync_strt_wid = ((((mode->crtc_hsync_start - mode->crtc_hblank_start) / 8) & 0x1fff) - | ((hsync_wid & 0x3f) << 16) - | ((mode->flags & DRM_MODE_FLAG_NHSYNC) - ? RADEON_CRTC_H_SYNC_POL - : 0)); - - fp_crtc_v_total_disp = (((mode->crtc_vblank_end - mode->crtc_vblank_start) & 0xffff) - | ((mode->crtc_vdisplay - 1) << 16)); - - vsync_wid = mode->crtc_vsync_end - mode->crtc_vsync_start; - if (!vsync_wid) - vsync_wid = 1; - - fp_v_sync_strt_wid = ((((mode->crtc_vsync_start - mode->crtc_vblank_start) & 0xfff) - | ((vsync_wid & 0x1f) << 16) - | ((mode->flags & DRM_MODE_FLAG_NVSYNC) - ? RADEON_CRTC_V_SYNC_POL - : 0))); - - fp_horz_vert_active = (((native_mode->panel_yres) & 0xfff) | - (((native_mode->panel_xres / 8) & 0x1ff) << 16)); - } - } else { - fp_horz_stretch |= ((xres/8-1) << 16); - fp_vert_stretch |= ((yres-1) << 12); - } - - WREG32(RADEON_FP_HORZ_STRETCH, fp_horz_stretch); - WREG32(RADEON_FP_VERT_STRETCH, fp_vert_stretch); - WREG32(RADEON_CRTC_MORE_CNTL, crtc_more_cntl); - WREG32(RADEON_FP_HORZ_VERT_ACTIVE, fp_horz_vert_active); - WREG32(RADEON_FP_H_SYNC_STRT_WID, fp_h_sync_strt_wid); - WREG32(RADEON_FP_V_SYNC_STRT_WID, fp_v_sync_strt_wid); - WREG32(RADEON_FP_CRTC_H_TOTAL_DISP, fp_crtc_h_total_disp); - WREG32(RADEON_FP_CRTC_V_TOTAL_DISP, fp_crtc_v_total_disp); - -} - static void radeon_legacy_lvds_dpms(struct drm_encoder *encoder, int mode) { struct drm_device *dev = encoder->dev; @@ -287,9 +123,6 @@ static void radeon_legacy_lvds_mode_set(struct drm_encoder *encoder, DRM_DEBUG("\n"); - if (radeon_crtc->crtc_id == 0) - radeon_legacy_rmx_mode_set(encoder, mode, adjusted_mode); - lvds_pll_cntl = RREG32(RADEON_LVDS_PLL_CNTL); lvds_pll_cntl &= ~RADEON_LVDS_PLL_EN; @@ -318,7 +151,7 @@ static void radeon_legacy_lvds_mode_set(struct drm_encoder *encoder, if (radeon_crtc->crtc_id == 0) { if (ASIC_IS_R300(rdev)) { - if (radeon_encoder->flags & RADEON_USE_RMX) + if (radeon_encoder->rmx_type != RMX_OFF) lvds_pll_cntl |= R300_LVDS_SRC_SEL_RMX; } else lvds_gen_cntl &= ~RADEON_LVDS_SEL_CRTC2; @@ -350,8 +183,6 @@ static bool radeon_legacy_lvds_mode_fixup(struct drm_encoder *encoder, drm_mode_set_crtcinfo(adjusted_mode, 0); - radeon_encoder->flags &= ~RADEON_USE_RMX; - if (radeon_encoder->rmx_type != RMX_OFF) radeon_rmx_mode_fixup(encoder, mode, adjusted_mode); @@ -455,9 +286,6 @@ static void radeon_legacy_primary_dac_mode_set(struct drm_encoder *encoder, DRM_DEBUG("\n"); - if (radeon_crtc->crtc_id == 0) - radeon_legacy_rmx_mode_set(encoder, mode, adjusted_mode); - if (radeon_crtc->crtc_id == 0) { if (rdev->family == CHIP_R200 || ASIC_IS_R300(rdev)) { disp_output_cntl = RREG32(RADEON_DISP_OUTPUT_CNTL) & @@ -653,9 +481,6 @@ static void radeon_legacy_tmds_int_mode_set(struct drm_encoder *encoder, DRM_DEBUG("\n"); - if (radeon_crtc->crtc_id == 0) - radeon_legacy_rmx_mode_set(encoder, mode, adjusted_mode); - tmp = tmds_pll_cntl = RREG32(RADEON_TMDS_PLL_CNTL); tmp &= 0xfffff; if (rdev->family == CHIP_RV280) { @@ -711,7 +536,7 @@ static void radeon_legacy_tmds_int_mode_set(struct drm_encoder *encoder, if (radeon_crtc->crtc_id == 0) { if (ASIC_IS_R300(rdev) || rdev->family == CHIP_R200) { fp_gen_cntl &= ~R200_FP_SOURCE_SEL_MASK; - if (radeon_encoder->flags & RADEON_USE_RMX) + if (radeon_encoder->rmx_type != RMX_OFF) fp_gen_cntl |= R200_FP_SOURCE_SEL_RMX; else fp_gen_cntl |= R200_FP_SOURCE_SEL_CRTC1; @@ -820,9 +645,6 @@ static void radeon_legacy_tmds_ext_mode_set(struct drm_encoder *encoder, DRM_DEBUG("\n"); - if (radeon_crtc->crtc_id == 0) - radeon_legacy_rmx_mode_set(encoder, mode, adjusted_mode); - if (rdev->is_atom_bios) { radeon_encoder->pixel_clock = adjusted_mode->clock; atombios_external_tmds_setup(encoder, ATOM_ENABLE); @@ -856,7 +678,7 @@ static void radeon_legacy_tmds_ext_mode_set(struct drm_encoder *encoder, if (radeon_crtc->crtc_id == 0) { if ((rdev->family == CHIP_R200) || ASIC_IS_R300(rdev)) { fp2_gen_cntl &= ~R200_FP2_SOURCE_SEL_MASK; - if (radeon_encoder->flags & RADEON_USE_RMX) + if (radeon_encoder->rmx_type != RMX_OFF) fp2_gen_cntl |= R200_FP2_SOURCE_SEL_RMX; else fp2_gen_cntl |= R200_FP2_SOURCE_SEL_CRTC1; @@ -1014,9 +836,6 @@ static void radeon_legacy_tv_dac_mode_set(struct drm_encoder *encoder, DRM_DEBUG("\n"); - if (radeon_crtc->crtc_id == 0) - radeon_legacy_rmx_mode_set(encoder, mode, adjusted_mode); - if (rdev->family != CHIP_R200) { tv_dac_cntl = RREG32(RADEON_TV_DAC_CNTL); if (rdev->family == CHIP_R420 || @@ -1243,6 +1062,7 @@ radeon_add_legacy_encoder(struct drm_device *dev, uint32_t encoder_id, uint32_t radeon_encoder->encoder_id = encoder_id; radeon_encoder->devices = supported_device; + radeon_encoder->rmx_type = RMX_OFF; switch (radeon_encoder->encoder_id) { case ENCODER_OBJECT_ID_INTERNAL_LVDS: diff --git a/drivers/gpu/drm/radeon/radeon_mode.h b/drivers/gpu/drm/radeon/radeon_mode.h index ba89b59f6e50..3b09a1f2d8f9 100644 --- a/drivers/gpu/drm/radeon/radeon_mode.h +++ b/drivers/gpu/drm/radeon/radeon_mode.h @@ -36,6 +36,9 @@ #include #include #include +#include "radeon_fixed.h" + +struct radeon_device; #define to_radeon_crtc(x) container_of(x, struct radeon_crtc, base) #define to_radeon_connector(x) container_of(x, struct radeon_connector, base) @@ -171,6 +174,18 @@ struct radeon_mode_info { struct atom_context *atom_context; enum radeon_connector_table connector_table; bool mode_config_initialized; + struct radeon_crtc *crtcs[2]; +}; + +struct radeon_native_mode { + /* preferred mode */ + uint32_t panel_xres, panel_yres; + uint32_t hoverplus, hsync_width; + uint32_t hblank; + uint32_t voverplus, vsync_width; + uint32_t vblank; + uint32_t dotclock; + uint32_t flags; }; struct radeon_crtc { @@ -188,19 +203,11 @@ struct radeon_crtc { int cursor_height; uint32_t legacy_display_base_addr; uint32_t legacy_cursor_offset; -}; - -#define RADEON_USE_RMX 1 - -struct radeon_native_mode { - /* preferred mode */ - uint32_t panel_xres, panel_yres; - uint32_t hoverplus, hsync_width; - uint32_t hblank; - uint32_t voverplus, vsync_width; - uint32_t vblank; - uint32_t dotclock; - uint32_t flags; + enum radeon_rmx_type rmx_type; + uint32_t devices; + fixed20_12 vsc; + fixed20_12 hsc; + struct radeon_native_mode native_mode; }; struct radeon_encoder_primary_dac { @@ -386,16 +393,9 @@ void radeon_enc_destroy(struct drm_encoder *encoder); void radeon_copy_fb(struct drm_device *dev, struct drm_gem_object *dst_obj); void radeon_combios_asic_init(struct drm_device *dev); extern int radeon_static_clocks_init(struct drm_device *dev); -void radeon_init_disp_bw_legacy(struct drm_device *dev, - struct drm_display_mode *mode1, - uint32_t pixel_bytes1, - struct drm_display_mode *mode2, - uint32_t pixel_bytes2); -void radeon_init_disp_bw_avivo(struct drm_device *dev, - struct drm_display_mode *mode1, - uint32_t pixel_bytes1, - struct drm_display_mode *mode2, - uint32_t pixel_bytes2); -void radeon_init_disp_bandwidth(struct drm_device *dev); +bool radeon_crtc_scaling_mode_fixup(struct drm_crtc *crtc, + struct drm_display_mode *mode, + struct drm_display_mode *adjusted_mode); +void atom_rv515_force_tv_scaler(struct radeon_device *rdev); #endif diff --git a/drivers/gpu/drm/radeon/radeon_share.h b/drivers/gpu/drm/radeon/radeon_share.h new file mode 100644 index 000000000000..63a773578f17 --- /dev/null +++ b/drivers/gpu/drm/radeon/radeon_share.h @@ -0,0 +1,39 @@ +/* + * Copyright 2008 Advanced Micro Devices, Inc. + * Copyright 2008 Red Hat Inc. + * Copyright 2009 Jerome Glisse. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: Dave Airlie + * Alex Deucher + * Jerome Glisse + */ +#ifndef __RADEON_SHARE_H__ +#define __RADEON_SHARE_H__ + +void r100_vram_init_sizes(struct radeon_device *rdev); + +void rs690_line_buffer_adjust(struct radeon_device *rdev, + struct drm_display_mode *mode1, + struct drm_display_mode *mode2); + +void rv515_bandwidth_avivo_update(struct radeon_device *rdev); + +#endif diff --git a/drivers/gpu/drm/radeon/rs400.c b/drivers/gpu/drm/radeon/rs400.c index daf24e85cba3..96a3c8486d25 100644 --- a/drivers/gpu/drm/radeon/rs400.c +++ b/drivers/gpu/drm/radeon/rs400.c @@ -29,6 +29,7 @@ #include #include "radeon_reg.h" #include "radeon.h" +#include "radeon_share.h" /* rs400,rs480 depends on : */ void r100_hdp_reset(struct radeon_device *rdev); diff --git a/drivers/gpu/drm/radeon/rs600.c b/drivers/gpu/drm/radeon/rs600.c index ab0c967553e6..bccdce7fd379 100644 --- a/drivers/gpu/drm/radeon/rs600.c +++ b/drivers/gpu/drm/radeon/rs600.c @@ -301,6 +301,11 @@ void rs600_vram_info(struct radeon_device *rdev) rdev->mc.vram_width = 128; } +void rs600_bandwidth_update(struct radeon_device *rdev) +{ + /* FIXME: implement, should this be like rs690 ? */ +} + /* * Indirect registers accessor diff --git a/drivers/gpu/drm/radeon/rs690.c b/drivers/gpu/drm/radeon/rs690.c index 79ba85042b5f..97eaee3d28b8 100644 --- a/drivers/gpu/drm/radeon/rs690.c +++ b/drivers/gpu/drm/radeon/rs690.c @@ -28,6 +28,9 @@ #include "drmP.h" #include "radeon_reg.h" #include "radeon.h" +#include "rs690r.h" +#include "atom.h" +#include "atom-bits.h" /* rs690,rs740 depends on : */ void r100_hdp_reset(struct radeon_device *rdev); @@ -138,9 +141,82 @@ void rs690_gpu_init(struct radeon_device *rdev) /* * VRAM info. */ +void rs690_pm_info(struct radeon_device *rdev) +{ + int index = GetIndexIntoMasterTable(DATA, IntegratedSystemInfo); + struct _ATOM_INTEGRATED_SYSTEM_INFO *info; + struct _ATOM_INTEGRATED_SYSTEM_INFO_V2 *info_v2; + void *ptr; + uint16_t data_offset; + uint8_t frev, crev; + fixed20_12 tmp; + + atom_parse_data_header(rdev->mode_info.atom_context, index, NULL, + &frev, &crev, &data_offset); + ptr = rdev->mode_info.atom_context->bios + data_offset; + info = (struct _ATOM_INTEGRATED_SYSTEM_INFO *)ptr; + info_v2 = (struct _ATOM_INTEGRATED_SYSTEM_INFO_V2 *)ptr; + /* Get various system informations from bios */ + switch (crev) { + case 1: + tmp.full = rfixed_const(100); + rdev->pm.igp_sideport_mclk.full = rfixed_const(info->ulBootUpMemoryClock); + rdev->pm.igp_sideport_mclk.full = rfixed_div(rdev->pm.igp_sideport_mclk, tmp); + rdev->pm.igp_system_mclk.full = rfixed_const(le16_to_cpu(info->usK8MemoryClock)); + rdev->pm.igp_ht_link_clk.full = rfixed_const(le16_to_cpu(info->usFSBClock)); + rdev->pm.igp_ht_link_width.full = rfixed_const(info->ucHTLinkWidth); + break; + case 2: + tmp.full = rfixed_const(100); + rdev->pm.igp_sideport_mclk.full = rfixed_const(info_v2->ulBootUpSidePortClock); + rdev->pm.igp_sideport_mclk.full = rfixed_div(rdev->pm.igp_sideport_mclk, tmp); + rdev->pm.igp_system_mclk.full = rfixed_const(info_v2->ulBootUpUMAClock); + rdev->pm.igp_system_mclk.full = rfixed_div(rdev->pm.igp_system_mclk, tmp); + rdev->pm.igp_ht_link_clk.full = rfixed_const(info_v2->ulHTLinkFreq); + rdev->pm.igp_ht_link_clk.full = rfixed_div(rdev->pm.igp_ht_link_clk, tmp); + rdev->pm.igp_ht_link_width.full = rfixed_const(le16_to_cpu(info_v2->usMinHTLinkWidth)); + break; + default: + tmp.full = rfixed_const(100); + /* We assume the slower possible clock ie worst case */ + /* DDR 333Mhz */ + rdev->pm.igp_sideport_mclk.full = rfixed_const(333); + /* FIXME: system clock ? */ + rdev->pm.igp_system_mclk.full = rfixed_const(100); + rdev->pm.igp_system_mclk.full = rfixed_div(rdev->pm.igp_system_mclk, tmp); + rdev->pm.igp_ht_link_clk.full = rfixed_const(200); + rdev->pm.igp_ht_link_width.full = rfixed_const(8); + DRM_ERROR("No integrated system info for your GPU, using safe default\n"); + break; + } + /* Compute various bandwidth */ + /* k8_bandwidth = (memory_clk / 2) * 2 * 8 * 0.5 = memory_clk * 4 */ + tmp.full = rfixed_const(4); + rdev->pm.k8_bandwidth.full = rfixed_mul(rdev->pm.igp_system_mclk, tmp); + /* ht_bandwidth = ht_clk * 2 * ht_width / 8 * 0.8 + * = ht_clk * ht_width / 5 + */ + tmp.full = rfixed_const(5); + rdev->pm.ht_bandwidth.full = rfixed_mul(rdev->pm.igp_ht_link_clk, + rdev->pm.igp_ht_link_width); + rdev->pm.ht_bandwidth.full = rfixed_div(rdev->pm.ht_bandwidth, tmp); + if (tmp.full < rdev->pm.max_bandwidth.full) { + /* HT link is a limiting factor */ + rdev->pm.max_bandwidth.full = tmp.full; + } + /* sideport_bandwidth = (sideport_clk / 2) * 2 * 2 * 0.7 + * = (sideport_clk * 14) / 10 + */ + tmp.full = rfixed_const(14); + rdev->pm.sideport_bandwidth.full = rfixed_mul(rdev->pm.igp_sideport_mclk, tmp); + tmp.full = rfixed_const(10); + rdev->pm.sideport_bandwidth.full = rfixed_div(rdev->pm.sideport_bandwidth, tmp); +} + void rs690_vram_info(struct radeon_device *rdev) { uint32_t tmp; + fixed20_12 a; rs400_gart_adjust_size(rdev); /* DDR for all card after R300 & IGP */ @@ -156,8 +232,404 @@ void rs690_vram_info(struct radeon_device *rdev) rdev->mc.aper_base = drm_get_resource_start(rdev->ddev, 0); rdev->mc.aper_size = drm_get_resource_len(rdev->ddev, 0); + rs690_pm_info(rdev); + /* FIXME: we should enforce default clock in case GPU is not in + * default setup + */ + a.full = rfixed_const(100); + rdev->pm.sclk.full = rfixed_const(rdev->clock.default_sclk); + rdev->pm.sclk.full = rfixed_div(rdev->pm.sclk, a); + a.full = rfixed_const(16); + /* core_bandwidth = sclk(Mhz) * 16 */ + rdev->pm.core_bandwidth.full = rfixed_div(rdev->pm.sclk, a); +} + +void rs690_line_buffer_adjust(struct radeon_device *rdev, + struct drm_display_mode *mode1, + struct drm_display_mode *mode2) +{ + u32 tmp; + + /* + * Line Buffer Setup + * There is a single line buffer shared by both display controllers. + * DC_LB_MEMORY_SPLIT controls how that line buffer is shared between + * the display controllers. The paritioning can either be done + * manually or via one of four preset allocations specified in bits 1:0: + * 0 - line buffer is divided in half and shared between crtc + * 1 - D1 gets 3/4 of the line buffer, D2 gets 1/4 + * 2 - D1 gets the whole buffer + * 3 - D1 gets 1/4 of the line buffer, D2 gets 3/4 + * Setting bit 2 of DC_LB_MEMORY_SPLIT controls switches to manual + * allocation mode. In manual allocation mode, D1 always starts at 0, + * D1 end/2 is specified in bits 14:4; D2 allocation follows D1. + */ + tmp = RREG32(DC_LB_MEMORY_SPLIT) & ~DC_LB_MEMORY_SPLIT_MASK; + tmp &= ~DC_LB_MEMORY_SPLIT_SHIFT_MODE; + /* auto */ + if (mode1 && mode2) { + if (mode1->hdisplay > mode2->hdisplay) { + if (mode1->hdisplay > 2560) + tmp |= DC_LB_MEMORY_SPLIT_D1_3Q_D2_1Q; + else + tmp |= DC_LB_MEMORY_SPLIT_D1HALF_D2HALF; + } else if (mode2->hdisplay > mode1->hdisplay) { + if (mode2->hdisplay > 2560) + tmp |= DC_LB_MEMORY_SPLIT_D1_1Q_D2_3Q; + else + tmp |= DC_LB_MEMORY_SPLIT_D1HALF_D2HALF; + } else + tmp |= AVIVO_DC_LB_MEMORY_SPLIT_D1HALF_D2HALF; + } else if (mode1) { + tmp |= DC_LB_MEMORY_SPLIT_D1_ONLY; + } else if (mode2) { + tmp |= DC_LB_MEMORY_SPLIT_D1_1Q_D2_3Q; + } + WREG32(DC_LB_MEMORY_SPLIT, tmp); } +struct rs690_watermark { + u32 lb_request_fifo_depth; + fixed20_12 num_line_pair; + fixed20_12 estimated_width; + fixed20_12 worst_case_latency; + fixed20_12 consumption_rate; + fixed20_12 active_time; + fixed20_12 dbpp; + fixed20_12 priority_mark_max; + fixed20_12 priority_mark; + fixed20_12 sclk; +}; + +void rs690_crtc_bandwidth_compute(struct radeon_device *rdev, + struct radeon_crtc *crtc, + struct rs690_watermark *wm) +{ + struct drm_display_mode *mode = &crtc->base.mode; + fixed20_12 a, b, c; + fixed20_12 pclk, request_fifo_depth, tolerable_latency, estimated_width; + fixed20_12 consumption_time, line_time, chunk_time, read_delay_latency; + /* FIXME: detect IGP with sideport memory, i don't think there is any + * such product available + */ + bool sideport = false; + + if (!crtc->base.enabled) { + /* FIXME: wouldn't it better to set priority mark to maximum */ + wm->lb_request_fifo_depth = 4; + return; + } + + if (crtc->vsc.full > rfixed_const(2)) + wm->num_line_pair.full = rfixed_const(2); + else + wm->num_line_pair.full = rfixed_const(1); + + b.full = rfixed_const(mode->crtc_hdisplay); + c.full = rfixed_const(256); + a.full = rfixed_mul(wm->num_line_pair, b); + request_fifo_depth.full = rfixed_div(a, c); + if (a.full < rfixed_const(4)) { + wm->lb_request_fifo_depth = 4; + } else { + wm->lb_request_fifo_depth = rfixed_trunc(request_fifo_depth); + } + + /* Determine consumption rate + * pclk = pixel clock period(ns) = 1000 / (mode.clock / 1000) + * vtaps = number of vertical taps, + * vsc = vertical scaling ratio, defined as source/destination + * hsc = horizontal scaling ration, defined as source/destination + */ + a.full = rfixed_const(mode->clock); + b.full = rfixed_const(1000); + a.full = rfixed_div(a, b); + pclk.full = rfixed_div(b, a); + if (crtc->rmx_type != RMX_OFF) { + b.full = rfixed_const(2); + if (crtc->vsc.full > b.full) + b.full = crtc->vsc.full; + b.full = rfixed_mul(b, crtc->hsc); + c.full = rfixed_const(2); + b.full = rfixed_div(b, c); + consumption_time.full = rfixed_div(pclk, b); + } else { + consumption_time.full = pclk.full; + } + a.full = rfixed_const(1); + wm->consumption_rate.full = rfixed_div(a, consumption_time); + + + /* Determine line time + * LineTime = total time for one line of displayhtotal + * LineTime = total number of horizontal pixels + * pclk = pixel clock period(ns) + */ + a.full = rfixed_const(crtc->base.mode.crtc_htotal); + line_time.full = rfixed_mul(a, pclk); + + /* Determine active time + * ActiveTime = time of active region of display within one line, + * hactive = total number of horizontal active pixels + * htotal = total number of horizontal pixels + */ + a.full = rfixed_const(crtc->base.mode.crtc_htotal); + b.full = rfixed_const(crtc->base.mode.crtc_hdisplay); + wm->active_time.full = rfixed_mul(line_time, b); + wm->active_time.full = rfixed_div(wm->active_time, a); + + /* Maximun bandwidth is the minimun bandwidth of all component */ + rdev->pm.max_bandwidth = rdev->pm.core_bandwidth; + if (sideport) { + if (rdev->pm.max_bandwidth.full > rdev->pm.sideport_bandwidth.full && + rdev->pm.sideport_bandwidth.full) + rdev->pm.max_bandwidth = rdev->pm.sideport_bandwidth; + read_delay_latency.full = rfixed_const(370 * 800 * 1000); + read_delay_latency.full = rfixed_div(read_delay_latency, + rdev->pm.igp_sideport_mclk); + } else { + if (rdev->pm.max_bandwidth.full > rdev->pm.k8_bandwidth.full && + rdev->pm.k8_bandwidth.full) + rdev->pm.max_bandwidth = rdev->pm.k8_bandwidth; + if (rdev->pm.max_bandwidth.full > rdev->pm.ht_bandwidth.full && + rdev->pm.ht_bandwidth.full) + rdev->pm.max_bandwidth = rdev->pm.ht_bandwidth; + read_delay_latency.full = rfixed_const(5000); + } + + /* sclk = system clocks(ns) = 1000 / max_bandwidth / 16 */ + a.full = rfixed_const(16); + rdev->pm.sclk.full = rfixed_mul(rdev->pm.max_bandwidth, a); + a.full = rfixed_const(1000); + rdev->pm.sclk.full = rfixed_div(a, rdev->pm.sclk); + /* Determine chunk time + * ChunkTime = the time it takes the DCP to send one chunk of data + * to the LB which consists of pipeline delay and inter chunk gap + * sclk = system clock(ns) + */ + a.full = rfixed_const(256 * 13); + chunk_time.full = rfixed_mul(rdev->pm.sclk, a); + a.full = rfixed_const(10); + chunk_time.full = rfixed_div(chunk_time, a); + + /* Determine the worst case latency + * NumLinePair = Number of line pairs to request(1=2 lines, 2=4 lines) + * WorstCaseLatency = worst case time from urgent to when the MC starts + * to return data + * READ_DELAY_IDLE_MAX = constant of 1us + * ChunkTime = time it takes the DCP to send one chunk of data to the LB + * which consists of pipeline delay and inter chunk gap + */ + if (rfixed_trunc(wm->num_line_pair) > 1) { + a.full = rfixed_const(3); + wm->worst_case_latency.full = rfixed_mul(a, chunk_time); + wm->worst_case_latency.full += read_delay_latency.full; + } else { + a.full = rfixed_const(2); + wm->worst_case_latency.full = rfixed_mul(a, chunk_time); + wm->worst_case_latency.full += read_delay_latency.full; + } + + /* Determine the tolerable latency + * TolerableLatency = Any given request has only 1 line time + * for the data to be returned + * LBRequestFifoDepth = Number of chunk requests the LB can + * put into the request FIFO for a display + * LineTime = total time for one line of display + * ChunkTime = the time it takes the DCP to send one chunk + * of data to the LB which consists of + * pipeline delay and inter chunk gap + */ + if ((2+wm->lb_request_fifo_depth) >= rfixed_trunc(request_fifo_depth)) { + tolerable_latency.full = line_time.full; + } else { + tolerable_latency.full = rfixed_const(wm->lb_request_fifo_depth - 2); + tolerable_latency.full = request_fifo_depth.full - tolerable_latency.full; + tolerable_latency.full = rfixed_mul(tolerable_latency, chunk_time); + tolerable_latency.full = line_time.full - tolerable_latency.full; + } + /* We assume worst case 32bits (4 bytes) */ + wm->dbpp.full = rfixed_const(4 * 8); + + /* Determine the maximum priority mark + * width = viewport width in pixels + */ + a.full = rfixed_const(16); + wm->priority_mark_max.full = rfixed_const(crtc->base.mode.crtc_hdisplay); + wm->priority_mark_max.full = rfixed_div(wm->priority_mark_max, a); + + /* Determine estimated width */ + estimated_width.full = tolerable_latency.full - wm->worst_case_latency.full; + estimated_width.full = rfixed_div(estimated_width, consumption_time); + if (rfixed_trunc(estimated_width) > crtc->base.mode.crtc_hdisplay) { + wm->priority_mark.full = rfixed_const(10); + } else { + a.full = rfixed_const(16); + wm->priority_mark.full = rfixed_div(estimated_width, a); + wm->priority_mark.full = wm->priority_mark_max.full - wm->priority_mark.full; + } +} + +void rs690_bandwidth_update(struct radeon_device *rdev) +{ + struct drm_display_mode *mode0 = NULL; + struct drm_display_mode *mode1 = NULL; + struct rs690_watermark wm0; + struct rs690_watermark wm1; + u32 tmp; + fixed20_12 priority_mark02, priority_mark12, fill_rate; + fixed20_12 a, b; + + if (rdev->mode_info.crtcs[0]->base.enabled) + mode0 = &rdev->mode_info.crtcs[0]->base.mode; + if (rdev->mode_info.crtcs[1]->base.enabled) + mode1 = &rdev->mode_info.crtcs[1]->base.mode; + /* + * Set display0/1 priority up in the memory controller for + * modes if the user specifies HIGH for displaypriority + * option. + */ + if (rdev->disp_priority == 2) { + tmp = RREG32_MC(MC_INIT_MISC_LAT_TIMER); + tmp &= ~MC_DISP1R_INIT_LAT_MASK; + tmp &= ~MC_DISP0R_INIT_LAT_MASK; + if (mode1) + tmp |= (1 << MC_DISP1R_INIT_LAT_SHIFT); + if (mode0) + tmp |= (1 << MC_DISP0R_INIT_LAT_SHIFT); + WREG32_MC(MC_INIT_MISC_LAT_TIMER, tmp); + } + rs690_line_buffer_adjust(rdev, mode0, mode1); + + if ((rdev->family == CHIP_RS690) || (rdev->family == CHIP_RS740)) + WREG32(DCP_CONTROL, 0); + if ((rdev->family == CHIP_RS780) || (rdev->family == CHIP_RS880)) + WREG32(DCP_CONTROL, 2); + + rs690_crtc_bandwidth_compute(rdev, rdev->mode_info.crtcs[0], &wm0); + rs690_crtc_bandwidth_compute(rdev, rdev->mode_info.crtcs[1], &wm1); + + tmp = (wm0.lb_request_fifo_depth - 1); + tmp |= (wm1.lb_request_fifo_depth - 1) << 16; + WREG32(LB_MAX_REQ_OUTSTANDING, tmp); + + if (mode0 && mode1) { + if (rfixed_trunc(wm0.dbpp) > 64) + a.full = rfixed_mul(wm0.dbpp, wm0.num_line_pair); + else + a.full = wm0.num_line_pair.full; + if (rfixed_trunc(wm1.dbpp) > 64) + b.full = rfixed_mul(wm1.dbpp, wm1.num_line_pair); + else + b.full = wm1.num_line_pair.full; + a.full += b.full; + fill_rate.full = rfixed_div(wm0.sclk, a); + if (wm0.consumption_rate.full > fill_rate.full) { + b.full = wm0.consumption_rate.full - fill_rate.full; + b.full = rfixed_mul(b, wm0.active_time); + a.full = rfixed_mul(wm0.worst_case_latency, + wm0.consumption_rate); + a.full = a.full + b.full; + b.full = rfixed_const(16 * 1000); + priority_mark02.full = rfixed_div(a, b); + } else { + a.full = rfixed_mul(wm0.worst_case_latency, + wm0.consumption_rate); + b.full = rfixed_const(16 * 1000); + priority_mark02.full = rfixed_div(a, b); + } + if (wm1.consumption_rate.full > fill_rate.full) { + b.full = wm1.consumption_rate.full - fill_rate.full; + b.full = rfixed_mul(b, wm1.active_time); + a.full = rfixed_mul(wm1.worst_case_latency, + wm1.consumption_rate); + a.full = a.full + b.full; + b.full = rfixed_const(16 * 1000); + priority_mark12.full = rfixed_div(a, b); + } else { + a.full = rfixed_mul(wm1.worst_case_latency, + wm1.consumption_rate); + b.full = rfixed_const(16 * 1000); + priority_mark12.full = rfixed_div(a, b); + } + if (wm0.priority_mark.full > priority_mark02.full) + priority_mark02.full = wm0.priority_mark.full; + if (rfixed_trunc(priority_mark02) < 0) + priority_mark02.full = 0; + if (wm0.priority_mark_max.full > priority_mark02.full) + priority_mark02.full = wm0.priority_mark_max.full; + if (wm1.priority_mark.full > priority_mark12.full) + priority_mark12.full = wm1.priority_mark.full; + if (rfixed_trunc(priority_mark12) < 0) + priority_mark12.full = 0; + if (wm1.priority_mark_max.full > priority_mark12.full) + priority_mark12.full = wm1.priority_mark_max.full; + WREG32(D1MODE_PRIORITY_A_CNT, rfixed_trunc(priority_mark02)); + WREG32(D1MODE_PRIORITY_B_CNT, rfixed_trunc(priority_mark02)); + WREG32(D2MODE_PRIORITY_A_CNT, rfixed_trunc(priority_mark12)); + WREG32(D2MODE_PRIORITY_B_CNT, rfixed_trunc(priority_mark12)); + } else if (mode0) { + if (rfixed_trunc(wm0.dbpp) > 64) + a.full = rfixed_mul(wm0.dbpp, wm0.num_line_pair); + else + a.full = wm0.num_line_pair.full; + fill_rate.full = rfixed_div(wm0.sclk, a); + if (wm0.consumption_rate.full > fill_rate.full) { + b.full = wm0.consumption_rate.full - fill_rate.full; + b.full = rfixed_mul(b, wm0.active_time); + a.full = rfixed_mul(wm0.worst_case_latency, + wm0.consumption_rate); + a.full = a.full + b.full; + b.full = rfixed_const(16 * 1000); + priority_mark02.full = rfixed_div(a, b); + } else { + a.full = rfixed_mul(wm0.worst_case_latency, + wm0.consumption_rate); + b.full = rfixed_const(16 * 1000); + priority_mark02.full = rfixed_div(a, b); + } + if (wm0.priority_mark.full > priority_mark02.full) + priority_mark02.full = wm0.priority_mark.full; + if (rfixed_trunc(priority_mark02) < 0) + priority_mark02.full = 0; + if (wm0.priority_mark_max.full > priority_mark02.full) + priority_mark02.full = wm0.priority_mark_max.full; + WREG32(D1MODE_PRIORITY_A_CNT, rfixed_trunc(priority_mark02)); + WREG32(D1MODE_PRIORITY_B_CNT, rfixed_trunc(priority_mark02)); + WREG32(D2MODE_PRIORITY_A_CNT, MODE_PRIORITY_OFF); + WREG32(D2MODE_PRIORITY_B_CNT, MODE_PRIORITY_OFF); + } else { + if (rfixed_trunc(wm1.dbpp) > 64) + a.full = rfixed_mul(wm1.dbpp, wm1.num_line_pair); + else + a.full = wm1.num_line_pair.full; + fill_rate.full = rfixed_div(wm1.sclk, a); + if (wm1.consumption_rate.full > fill_rate.full) { + b.full = wm1.consumption_rate.full - fill_rate.full; + b.full = rfixed_mul(b, wm1.active_time); + a.full = rfixed_mul(wm1.worst_case_latency, + wm1.consumption_rate); + a.full = a.full + b.full; + b.full = rfixed_const(16 * 1000); + priority_mark12.full = rfixed_div(a, b); + } else { + a.full = rfixed_mul(wm1.worst_case_latency, + wm1.consumption_rate); + b.full = rfixed_const(16 * 1000); + priority_mark12.full = rfixed_div(a, b); + } + if (wm1.priority_mark.full > priority_mark12.full) + priority_mark12.full = wm1.priority_mark.full; + if (rfixed_trunc(priority_mark12) < 0) + priority_mark12.full = 0; + if (wm1.priority_mark_max.full > priority_mark12.full) + priority_mark12.full = wm1.priority_mark_max.full; + WREG32(D1MODE_PRIORITY_A_CNT, MODE_PRIORITY_OFF); + WREG32(D1MODE_PRIORITY_B_CNT, MODE_PRIORITY_OFF); + WREG32(D2MODE_PRIORITY_A_CNT, rfixed_trunc(priority_mark12)); + WREG32(D2MODE_PRIORITY_B_CNT, rfixed_trunc(priority_mark12)); + } +} /* * Indirect registers accessor diff --git a/drivers/gpu/drm/radeon/rs690r.h b/drivers/gpu/drm/radeon/rs690r.h new file mode 100644 index 000000000000..c0d9faa2175b --- /dev/null +++ b/drivers/gpu/drm/radeon/rs690r.h @@ -0,0 +1,99 @@ +/* + * Copyright 2008 Advanced Micro Devices, Inc. + * Copyright 2008 Red Hat Inc. + * Copyright 2009 Jerome Glisse. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: Dave Airlie + * Alex Deucher + * Jerome Glisse + */ +#ifndef RS690R_H +#define RS690R_H + +/* RS690/RS740 registers */ +#define MC_INDEX 0x0078 +# define MC_INDEX_MASK 0x1FF +# define MC_INDEX_WR_EN (1 << 9) +# define MC_INDEX_WR_ACK 0x7F +#define MC_DATA 0x007C +#define HDP_FB_LOCATION 0x0134 +#define DC_LB_MEMORY_SPLIT 0x6520 +#define DC_LB_MEMORY_SPLIT_MASK 0x00000003 +#define DC_LB_MEMORY_SPLIT_SHIFT 0 +#define DC_LB_MEMORY_SPLIT_D1HALF_D2HALF 0 +#define DC_LB_MEMORY_SPLIT_D1_3Q_D2_1Q 1 +#define DC_LB_MEMORY_SPLIT_D1_ONLY 2 +#define DC_LB_MEMORY_SPLIT_D1_1Q_D2_3Q 3 +#define DC_LB_MEMORY_SPLIT_SHIFT_MODE (1 << 2) +#define DC_LB_DISP1_END_ADR_SHIFT 4 +#define DC_LB_DISP1_END_ADR_MASK 0x00007FF0 +#define D1MODE_PRIORITY_A_CNT 0x6548 +#define MODE_PRIORITY_MARK_MASK 0x00007FFF +#define MODE_PRIORITY_OFF (1 << 16) +#define MODE_PRIORITY_ALWAYS_ON (1 << 20) +#define MODE_PRIORITY_FORCE_MASK (1 << 24) +#define D1MODE_PRIORITY_B_CNT 0x654C +#define LB_MAX_REQ_OUTSTANDING 0x6D58 +#define LB_D1_MAX_REQ_OUTSTANDING_MASK 0x0000000F +#define LB_D1_MAX_REQ_OUTSTANDING_SHIFT 0 +#define LB_D2_MAX_REQ_OUTSTANDING_MASK 0x000F0000 +#define LB_D2_MAX_REQ_OUTSTANDING_SHIFT 16 +#define DCP_CONTROL 0x6C9C +#define D2MODE_PRIORITY_A_CNT 0x6D48 +#define D2MODE_PRIORITY_B_CNT 0x6D4C + +/* MC indirect registers */ +#define MC_STATUS_IDLE (1 << 0) +#define MC_MISC_CNTL 0x18 +#define DISABLE_GTW (1 << 1) +#define GART_INDEX_REG_EN (1 << 12) +#define BLOCK_GFX_D3_EN (1 << 14) +#define GART_FEATURE_ID 0x2B +#define HANG_EN (1 << 11) +#define TLB_ENABLE (1 << 18) +#define P2P_ENABLE (1 << 19) +#define GTW_LAC_EN (1 << 25) +#define LEVEL2_GART (0 << 30) +#define LEVEL1_GART (1 << 30) +#define PDC_EN (1 << 31) +#define GART_BASE 0x2C +#define GART_CACHE_CNTRL 0x2E +# define GART_CACHE_INVALIDATE (1 << 0) +#define MC_STATUS 0x90 +#define MCCFG_FB_LOCATION 0x100 +#define MC_FB_START_MASK 0x0000FFFF +#define MC_FB_START_SHIFT 0 +#define MC_FB_TOP_MASK 0xFFFF0000 +#define MC_FB_TOP_SHIFT 16 +#define MCCFG_AGP_LOCATION 0x101 +#define MC_AGP_START_MASK 0x0000FFFF +#define MC_AGP_START_SHIFT 0 +#define MC_AGP_TOP_MASK 0xFFFF0000 +#define MC_AGP_TOP_SHIFT 16 +#define MCCFG_AGP_BASE 0x102 +#define MCCFG_AGP_BASE_2 0x103 +#define MC_INIT_MISC_LAT_TIMER 0x104 +#define MC_DISP0R_INIT_LAT_SHIFT 8 +#define MC_DISP0R_INIT_LAT_MASK 0x00000F00 +#define MC_DISP1R_INIT_LAT_SHIFT 12 +#define MC_DISP1R_INIT_LAT_MASK 0x0000F000 + +#endif diff --git a/drivers/gpu/drm/radeon/rv515.c b/drivers/gpu/drm/radeon/rv515.c index 677929ed8ed3..4fd411893b91 100644 --- a/drivers/gpu/drm/radeon/rv515.c +++ b/drivers/gpu/drm/radeon/rv515.c @@ -27,8 +27,9 @@ */ #include #include "drmP.h" -#include "radeon_reg.h" +#include "rv515r.h" #include "radeon.h" +#include "radeon_share.h" /* rv515 depends on : */ void r100_hdp_reset(struct radeon_device *rdev); @@ -100,25 +101,25 @@ int rv515_mc_init(struct radeon_device *rdev) } /* Write VRAM size in case we are limiting it */ WREG32(RADEON_CONFIG_MEMSIZE, rdev->mc.vram_size); - tmp = REG_SET(RV515_MC_FB_START, rdev->mc.vram_location >> 16); + tmp = REG_SET(MC_FB_START, rdev->mc.vram_location >> 16); WREG32(0x134, tmp); tmp = rdev->mc.vram_location + rdev->mc.vram_size - 1; - tmp = REG_SET(RV515_MC_FB_TOP, tmp >> 16); - tmp |= REG_SET(RV515_MC_FB_START, rdev->mc.vram_location >> 16); - WREG32_MC(RV515_MC_FB_LOCATION, tmp); - WREG32(RS690_HDP_FB_LOCATION, rdev->mc.vram_location >> 16); + tmp = REG_SET(MC_FB_TOP, tmp >> 16); + tmp |= REG_SET(MC_FB_START, rdev->mc.vram_location >> 16); + WREG32_MC(MC_FB_LOCATION, tmp); + WREG32(HDP_FB_LOCATION, rdev->mc.vram_location >> 16); WREG32(0x310, rdev->mc.vram_location); if (rdev->flags & RADEON_IS_AGP) { tmp = rdev->mc.gtt_location + rdev->mc.gtt_size - 1; - tmp = REG_SET(RV515_MC_AGP_TOP, tmp >> 16); - tmp |= REG_SET(RV515_MC_AGP_START, rdev->mc.gtt_location >> 16); - WREG32_MC(RV515_MC_AGP_LOCATION, tmp); - WREG32_MC(RV515_MC_AGP_BASE, rdev->mc.agp_base); - WREG32_MC(RV515_MC_AGP_BASE_2, 0); + tmp = REG_SET(MC_AGP_TOP, tmp >> 16); + tmp |= REG_SET(MC_AGP_START, rdev->mc.gtt_location >> 16); + WREG32_MC(MC_AGP_LOCATION, tmp); + WREG32_MC(MC_AGP_BASE, rdev->mc.agp_base); + WREG32_MC(MC_AGP_BASE_2, 0); } else { - WREG32_MC(RV515_MC_AGP_LOCATION, 0x0FFFFFFF); - WREG32_MC(RV515_MC_AGP_BASE, 0); - WREG32_MC(RV515_MC_AGP_BASE_2, 0); + WREG32_MC(MC_AGP_LOCATION, 0x0FFFFFFF); + WREG32_MC(MC_AGP_BASE, 0); + WREG32_MC(MC_AGP_BASE_2, 0); } return 0; } @@ -136,95 +137,67 @@ void rv515_mc_fini(struct radeon_device *rdev) */ void rv515_ring_start(struct radeon_device *rdev) { - unsigned gb_tile_config; int r; - /* Sub pixel 1/12 so we can have 4K rendering according to doc */ - gb_tile_config = R300_ENABLE_TILING | R300_TILE_SIZE_16; - switch (rdev->num_gb_pipes) { - case 2: - gb_tile_config |= R300_PIPE_COUNT_R300; - break; - case 3: - gb_tile_config |= R300_PIPE_COUNT_R420_3P; - break; - case 4: - gb_tile_config |= R300_PIPE_COUNT_R420; - break; - case 1: - default: - gb_tile_config |= R300_PIPE_COUNT_RV350; - break; - } - r = radeon_ring_lock(rdev, 64); if (r) { return; } - radeon_ring_write(rdev, PACKET0(RADEON_ISYNC_CNTL, 0)); - radeon_ring_write(rdev, - RADEON_ISYNC_ANY2D_IDLE3D | - RADEON_ISYNC_ANY3D_IDLE2D | - RADEON_ISYNC_WAIT_IDLEGUI | - RADEON_ISYNC_CPSCRATCH_IDLEGUI); - radeon_ring_write(rdev, PACKET0(R300_GB_TILE_CONFIG, 0)); - radeon_ring_write(rdev, gb_tile_config); - radeon_ring_write(rdev, PACKET0(RADEON_WAIT_UNTIL, 0)); + radeon_ring_write(rdev, PACKET0(ISYNC_CNTL, 0)); radeon_ring_write(rdev, - RADEON_WAIT_2D_IDLECLEAN | - RADEON_WAIT_3D_IDLECLEAN); + ISYNC_ANY2D_IDLE3D | + ISYNC_ANY3D_IDLE2D | + ISYNC_WAIT_IDLEGUI | + ISYNC_CPSCRATCH_IDLEGUI); + radeon_ring_write(rdev, PACKET0(WAIT_UNTIL, 0)); + radeon_ring_write(rdev, WAIT_2D_IDLECLEAN | WAIT_3D_IDLECLEAN); radeon_ring_write(rdev, PACKET0(0x170C, 0)); radeon_ring_write(rdev, 1 << 31); - radeon_ring_write(rdev, PACKET0(R300_GB_SELECT, 0)); + radeon_ring_write(rdev, PACKET0(GB_SELECT, 0)); radeon_ring_write(rdev, 0); - radeon_ring_write(rdev, PACKET0(R300_GB_ENABLE, 0)); + radeon_ring_write(rdev, PACKET0(GB_ENABLE, 0)); radeon_ring_write(rdev, 0); radeon_ring_write(rdev, PACKET0(0x42C8, 0)); radeon_ring_write(rdev, (1 << rdev->num_gb_pipes) - 1); - radeon_ring_write(rdev, PACKET0(R500_VAP_INDEX_OFFSET, 0)); + radeon_ring_write(rdev, PACKET0(VAP_INDEX_OFFSET, 0)); radeon_ring_write(rdev, 0); - radeon_ring_write(rdev, PACKET0(R300_RB3D_DSTCACHE_CTLSTAT, 0)); - radeon_ring_write(rdev, R300_RB3D_DC_FLUSH | R300_RB3D_DC_FREE); - radeon_ring_write(rdev, PACKET0(R300_RB3D_ZCACHE_CTLSTAT, 0)); - radeon_ring_write(rdev, R300_ZC_FLUSH | R300_ZC_FREE); - radeon_ring_write(rdev, PACKET0(RADEON_WAIT_UNTIL, 0)); - radeon_ring_write(rdev, - RADEON_WAIT_2D_IDLECLEAN | - RADEON_WAIT_3D_IDLECLEAN); - radeon_ring_write(rdev, PACKET0(R300_GB_AA_CONFIG, 0)); + radeon_ring_write(rdev, PACKET0(RB3D_DSTCACHE_CTLSTAT, 0)); + radeon_ring_write(rdev, RB3D_DC_FLUSH | RB3D_DC_FREE); + radeon_ring_write(rdev, PACKET0(ZB_ZCACHE_CTLSTAT, 0)); + radeon_ring_write(rdev, ZC_FLUSH | ZC_FREE); + radeon_ring_write(rdev, PACKET0(WAIT_UNTIL, 0)); + radeon_ring_write(rdev, WAIT_2D_IDLECLEAN | WAIT_3D_IDLECLEAN); + radeon_ring_write(rdev, PACKET0(GB_AA_CONFIG, 0)); radeon_ring_write(rdev, 0); - radeon_ring_write(rdev, PACKET0(R300_RB3D_DSTCACHE_CTLSTAT, 0)); - radeon_ring_write(rdev, R300_RB3D_DC_FLUSH | R300_RB3D_DC_FREE); - radeon_ring_write(rdev, PACKET0(R300_RB3D_ZCACHE_CTLSTAT, 0)); - radeon_ring_write(rdev, R300_ZC_FLUSH | R300_ZC_FREE); - radeon_ring_write(rdev, PACKET0(R300_GB_MSPOS0, 0)); - radeon_ring_write(rdev, - ((6 << R300_MS_X0_SHIFT) | - (6 << R300_MS_Y0_SHIFT) | - (6 << R300_MS_X1_SHIFT) | - (6 << R300_MS_Y1_SHIFT) | - (6 << R300_MS_X2_SHIFT) | - (6 << R300_MS_Y2_SHIFT) | - (6 << R300_MSBD0_Y_SHIFT) | - (6 << R300_MSBD0_X_SHIFT))); - radeon_ring_write(rdev, PACKET0(R300_GB_MSPOS1, 0)); - radeon_ring_write(rdev, - ((6 << R300_MS_X3_SHIFT) | - (6 << R300_MS_Y3_SHIFT) | - (6 << R300_MS_X4_SHIFT) | - (6 << R300_MS_Y4_SHIFT) | - (6 << R300_MS_X5_SHIFT) | - (6 << R300_MS_Y5_SHIFT) | - (6 << R300_MSBD1_SHIFT))); - radeon_ring_write(rdev, PACKET0(R300_GA_ENHANCE, 0)); - radeon_ring_write(rdev, R300_GA_DEADLOCK_CNTL | R300_GA_FASTSYNC_CNTL); - radeon_ring_write(rdev, PACKET0(R300_GA_POLY_MODE, 0)); + radeon_ring_write(rdev, PACKET0(RB3D_DSTCACHE_CTLSTAT, 0)); + radeon_ring_write(rdev, RB3D_DC_FLUSH | RB3D_DC_FREE); + radeon_ring_write(rdev, PACKET0(ZB_ZCACHE_CTLSTAT, 0)); + radeon_ring_write(rdev, ZC_FLUSH | ZC_FREE); + radeon_ring_write(rdev, PACKET0(GB_MSPOS0, 0)); radeon_ring_write(rdev, - R300_FRONT_PTYPE_TRIANGE | R300_BACK_PTYPE_TRIANGE); - radeon_ring_write(rdev, PACKET0(R300_GA_ROUND_MODE, 0)); + ((6 << MS_X0_SHIFT) | + (6 << MS_Y0_SHIFT) | + (6 << MS_X1_SHIFT) | + (6 << MS_Y1_SHIFT) | + (6 << MS_X2_SHIFT) | + (6 << MS_Y2_SHIFT) | + (6 << MSBD0_Y_SHIFT) | + (6 << MSBD0_X_SHIFT))); + radeon_ring_write(rdev, PACKET0(GB_MSPOS1, 0)); radeon_ring_write(rdev, - R300_GEOMETRY_ROUND_NEAREST | - R300_COLOR_ROUND_NEAREST); + ((6 << MS_X3_SHIFT) | + (6 << MS_Y3_SHIFT) | + (6 << MS_X4_SHIFT) | + (6 << MS_Y4_SHIFT) | + (6 << MS_X5_SHIFT) | + (6 << MS_Y5_SHIFT) | + (6 << MSBD1_SHIFT))); + radeon_ring_write(rdev, PACKET0(GA_ENHANCE, 0)); + radeon_ring_write(rdev, GA_DEADLOCK_CNTL | GA_FASTSYNC_CNTL); + radeon_ring_write(rdev, PACKET0(GA_POLY_MODE, 0)); + radeon_ring_write(rdev, FRONT_PTYPE_TRIANGE | BACK_PTYPE_TRIANGE); + radeon_ring_write(rdev, PACKET0(GA_ROUND_MODE, 0)); + radeon_ring_write(rdev, GEOMETRY_ROUND_NEAREST | COLOR_ROUND_NEAREST); radeon_ring_write(rdev, PACKET0(0x20C8, 0)); radeon_ring_write(rdev, 0); radeon_ring_unlock_commit(rdev); @@ -242,8 +215,8 @@ int rv515_mc_wait_for_idle(struct radeon_device *rdev) for (i = 0; i < rdev->usec_timeout; i++) { /* read MC_STATUS */ - tmp = RREG32_MC(RV515_MC_STATUS); - if (tmp & RV515_MC_STATUS_IDLE) { + tmp = RREG32_MC(MC_STATUS); + if (tmp & MC_STATUS_IDLE) { return 0; } DRM_UDELAY(1); @@ -291,33 +264,33 @@ int rv515_ga_reset(struct radeon_device *rdev) reinit_cp = rdev->cp.ready; rdev->cp.ready = false; for (i = 0; i < rdev->usec_timeout; i++) { - WREG32(RADEON_CP_CSQ_MODE, 0); - WREG32(RADEON_CP_CSQ_CNTL, 0); - WREG32(RADEON_RBBM_SOFT_RESET, 0x32005); - (void)RREG32(RADEON_RBBM_SOFT_RESET); + WREG32(CP_CSQ_MODE, 0); + WREG32(CP_CSQ_CNTL, 0); + WREG32(RBBM_SOFT_RESET, 0x32005); + (void)RREG32(RBBM_SOFT_RESET); udelay(200); - WREG32(RADEON_RBBM_SOFT_RESET, 0); + WREG32(RBBM_SOFT_RESET, 0); /* Wait to prevent race in RBBM_STATUS */ mdelay(1); - tmp = RREG32(RADEON_RBBM_STATUS); + tmp = RREG32(RBBM_STATUS); if (tmp & ((1 << 20) | (1 << 26))) { DRM_ERROR("VAP & CP still busy (RBBM_STATUS=0x%08X)\n", tmp); /* GA still busy soft reset it */ WREG32(0x429C, 0x200); - WREG32(R300_VAP_PVS_STATE_FLUSH_REG, 0); + WREG32(VAP_PVS_STATE_FLUSH_REG, 0); WREG32(0x43E0, 0); WREG32(0x43E4, 0); WREG32(0x24AC, 0); } /* Wait to prevent race in RBBM_STATUS */ mdelay(1); - tmp = RREG32(RADEON_RBBM_STATUS); + tmp = RREG32(RBBM_STATUS); if (!(tmp & ((1 << 20) | (1 << 26)))) { break; } } for (i = 0; i < rdev->usec_timeout; i++) { - tmp = RREG32(RADEON_RBBM_STATUS); + tmp = RREG32(RBBM_STATUS); if (!(tmp & ((1 << 20) | (1 << 26)))) { DRM_INFO("GA reset succeed (RBBM_STATUS=0x%08X)\n", tmp); @@ -331,7 +304,7 @@ int rv515_ga_reset(struct radeon_device *rdev) } DRM_UDELAY(1); } - tmp = RREG32(RADEON_RBBM_STATUS); + tmp = RREG32(RBBM_STATUS); DRM_ERROR("Failed to reset GA ! (RBBM_STATUS=0x%08X)\n", tmp); return -1; } @@ -341,7 +314,7 @@ int rv515_gpu_reset(struct radeon_device *rdev) uint32_t status; /* reset order likely matter */ - status = RREG32(RADEON_RBBM_STATUS); + status = RREG32(RBBM_STATUS); /* reset HDP */ r100_hdp_reset(rdev); /* reset rb2d */ @@ -353,12 +326,12 @@ int rv515_gpu_reset(struct radeon_device *rdev) rv515_ga_reset(rdev); } /* reset CP */ - status = RREG32(RADEON_RBBM_STATUS); + status = RREG32(RBBM_STATUS); if (status & (1 << 16)) { r100_cp_reset(rdev); } /* Check if GPU is idle */ - status = RREG32(RADEON_RBBM_STATUS); + status = RREG32(RBBM_STATUS); if (status & (1 << 31)) { DRM_ERROR("Failed to reset GPU (RBBM_STATUS=0x%08X)\n", status); return -1; @@ -377,8 +350,7 @@ static void rv515_vram_get_type(struct radeon_device *rdev) rdev->mc.vram_width = 128; rdev->mc.vram_is_ddr = true; - tmp = RREG32_MC(RV515_MC_CNTL); - tmp &= RV515_MEM_NUM_CHANNELS_MASK; + tmp = RREG32_MC(RV515_MC_CNTL) & MEM_NUM_CHANNELS_MASK; switch (tmp) { case 0: rdev->mc.vram_width = 64; @@ -394,9 +366,19 @@ static void rv515_vram_get_type(struct radeon_device *rdev) void rv515_vram_info(struct radeon_device *rdev) { + fixed20_12 a; + rv515_vram_get_type(rdev); - - r100_vram_init_sizes(rdev); + rdev->mc.vram_size = RREG32(CONFIG_MEMSIZE); + + rdev->mc.aper_base = drm_get_resource_start(rdev->ddev, 0); + rdev->mc.aper_size = drm_get_resource_len(rdev->ddev, 0); + /* FIXME: we should enforce default clock in case GPU is not in + * default setup + */ + a.full = rfixed_const(100); + rdev->pm.sclk.full = rfixed_const(rdev->clock.default_sclk); + rdev->pm.sclk.full = rfixed_div(rdev->pm.sclk, a); } @@ -407,35 +389,35 @@ uint32_t rv515_mc_rreg(struct radeon_device *rdev, uint32_t reg) { uint32_t r; - WREG32(R520_MC_IND_INDEX, 0x7f0000 | (reg & 0xffff)); - r = RREG32(R520_MC_IND_DATA); - WREG32(R520_MC_IND_INDEX, 0); + WREG32(MC_IND_INDEX, 0x7f0000 | (reg & 0xffff)); + r = RREG32(MC_IND_DATA); + WREG32(MC_IND_INDEX, 0); return r; } void rv515_mc_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v) { - WREG32(R520_MC_IND_INDEX, 0xff0000 | ((reg) & 0xffff)); - WREG32(R520_MC_IND_DATA, (v)); - WREG32(R520_MC_IND_INDEX, 0); + WREG32(MC_IND_INDEX, 0xff0000 | ((reg) & 0xffff)); + WREG32(MC_IND_DATA, (v)); + WREG32(MC_IND_INDEX, 0); } uint32_t rv515_pcie_rreg(struct radeon_device *rdev, uint32_t reg) { uint32_t r; - WREG32(RADEON_PCIE_INDEX, ((reg) & 0x7ff)); - (void)RREG32(RADEON_PCIE_INDEX); - r = RREG32(RADEON_PCIE_DATA); + 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(RADEON_PCIE_INDEX, ((reg) & 0x7ff)); - (void)RREG32(RADEON_PCIE_INDEX); - WREG32(RADEON_PCIE_DATA, (v)); - (void)RREG32(RADEON_PCIE_DATA); + WREG32(PCIE_INDEX, ((reg) & 0x7ff)); + (void)RREG32(PCIE_INDEX); + WREG32(PCIE_DATA, (v)); + (void)RREG32(PCIE_DATA); } @@ -450,13 +432,13 @@ static int rv515_debugfs_pipes_info(struct seq_file *m, void *data) struct radeon_device *rdev = dev->dev_private; uint32_t tmp; - tmp = RREG32(R400_GB_PIPE_SELECT); + tmp = RREG32(GB_PIPE_SELECT); seq_printf(m, "GB_PIPE_SELECT 0x%08x\n", tmp); - tmp = RREG32(R500_SU_REG_DEST); + tmp = RREG32(SU_REG_DEST); seq_printf(m, "SU_REG_DEST 0x%08x\n", tmp); - tmp = RREG32(R300_GB_TILE_CONFIG); + tmp = RREG32(GB_TILE_CONFIG); seq_printf(m, "GB_TILE_CONFIG 0x%08x\n", tmp); - tmp = RREG32(R300_DST_PIPE_CONFIG); + tmp = RREG32(DST_PIPE_CONFIG); seq_printf(m, "DST_PIPE_CONFIG 0x%08x\n", tmp); return 0; } @@ -571,3 +553,551 @@ int rv515_init(struct radeon_device *rdev) rdev->config.r300.reg_safe_bm_size = ARRAY_SIZE(r500_reg_safe_bm); return 0; } + +void atom_rv515_force_tv_scaler(struct radeon_device *rdev) +{ + + WREG32(0x659C, 0x0); + WREG32(0x6594, 0x705); + WREG32(0x65A4, 0x10001); + WREG32(0x65D8, 0x0); + WREG32(0x65B0, 0x0); + WREG32(0x65C0, 0x0); + WREG32(0x65D4, 0x0); + WREG32(0x6578, 0x0); + WREG32(0x657C, 0x841880A8); + WREG32(0x6578, 0x1); + WREG32(0x657C, 0x84208680); + WREG32(0x6578, 0x2); + WREG32(0x657C, 0xBFF880B0); + WREG32(0x6578, 0x100); + WREG32(0x657C, 0x83D88088); + WREG32(0x6578, 0x101); + WREG32(0x657C, 0x84608680); + WREG32(0x6578, 0x102); + WREG32(0x657C, 0xBFF080D0); + WREG32(0x6578, 0x200); + WREG32(0x657C, 0x83988068); + WREG32(0x6578, 0x201); + WREG32(0x657C, 0x84A08680); + WREG32(0x6578, 0x202); + WREG32(0x657C, 0xBFF080F8); + WREG32(0x6578, 0x300); + WREG32(0x657C, 0x83588058); + WREG32(0x6578, 0x301); + WREG32(0x657C, 0x84E08660); + WREG32(0x6578, 0x302); + WREG32(0x657C, 0xBFF88120); + WREG32(0x6578, 0x400); + WREG32(0x657C, 0x83188040); + WREG32(0x6578, 0x401); + WREG32(0x657C, 0x85008660); + WREG32(0x6578, 0x402); + WREG32(0x657C, 0xBFF88150); + WREG32(0x6578, 0x500); + WREG32(0x657C, 0x82D88030); + WREG32(0x6578, 0x501); + WREG32(0x657C, 0x85408640); + WREG32(0x6578, 0x502); + WREG32(0x657C, 0xBFF88180); + WREG32(0x6578, 0x600); + WREG32(0x657C, 0x82A08018); + WREG32(0x6578, 0x601); + WREG32(0x657C, 0x85808620); + WREG32(0x6578, 0x602); + WREG32(0x657C, 0xBFF081B8); + WREG32(0x6578, 0x700); + WREG32(0x657C, 0x82608010); + WREG32(0x6578, 0x701); + WREG32(0x657C, 0x85A08600); + WREG32(0x6578, 0x702); + WREG32(0x657C, 0x800081F0); + WREG32(0x6578, 0x800); + WREG32(0x657C, 0x8228BFF8); + WREG32(0x6578, 0x801); + WREG32(0x657C, 0x85E085E0); + WREG32(0x6578, 0x802); + WREG32(0x657C, 0xBFF88228); + WREG32(0x6578, 0x10000); + WREG32(0x657C, 0x82A8BF00); + WREG32(0x6578, 0x10001); + WREG32(0x657C, 0x82A08CC0); + WREG32(0x6578, 0x10002); + WREG32(0x657C, 0x8008BEF8); + WREG32(0x6578, 0x10100); + WREG32(0x657C, 0x81F0BF28); + WREG32(0x6578, 0x10101); + WREG32(0x657C, 0x83608CA0); + WREG32(0x6578, 0x10102); + WREG32(0x657C, 0x8018BED0); + WREG32(0x6578, 0x10200); + WREG32(0x657C, 0x8148BF38); + WREG32(0x6578, 0x10201); + WREG32(0x657C, 0x84408C80); + WREG32(0x6578, 0x10202); + WREG32(0x657C, 0x8008BEB8); + WREG32(0x6578, 0x10300); + WREG32(0x657C, 0x80B0BF78); + WREG32(0x6578, 0x10301); + WREG32(0x657C, 0x85008C20); + WREG32(0x6578, 0x10302); + WREG32(0x657C, 0x8020BEA0); + WREG32(0x6578, 0x10400); + WREG32(0x657C, 0x8028BF90); + WREG32(0x6578, 0x10401); + WREG32(0x657C, 0x85E08BC0); + WREG32(0x6578, 0x10402); + WREG32(0x657C, 0x8018BE90); + WREG32(0x6578, 0x10500); + WREG32(0x657C, 0xBFB8BFB0); + WREG32(0x6578, 0x10501); + WREG32(0x657C, 0x86C08B40); + WREG32(0x6578, 0x10502); + WREG32(0x657C, 0x8010BE90); + WREG32(0x6578, 0x10600); + WREG32(0x657C, 0xBF58BFC8); + WREG32(0x6578, 0x10601); + WREG32(0x657C, 0x87A08AA0); + WREG32(0x6578, 0x10602); + WREG32(0x657C, 0x8010BE98); + WREG32(0x6578, 0x10700); + WREG32(0x657C, 0xBF10BFF0); + WREG32(0x6578, 0x10701); + WREG32(0x657C, 0x886089E0); + WREG32(0x6578, 0x10702); + WREG32(0x657C, 0x8018BEB0); + WREG32(0x6578, 0x10800); + WREG32(0x657C, 0xBED8BFE8); + WREG32(0x6578, 0x10801); + WREG32(0x657C, 0x89408940); + WREG32(0x6578, 0x10802); + WREG32(0x657C, 0xBFE8BED8); + WREG32(0x6578, 0x20000); + WREG32(0x657C, 0x80008000); + WREG32(0x6578, 0x20001); + WREG32(0x657C, 0x90008000); + WREG32(0x6578, 0x20002); + WREG32(0x657C, 0x80008000); + WREG32(0x6578, 0x20003); + WREG32(0x657C, 0x80008000); + WREG32(0x6578, 0x20100); + WREG32(0x657C, 0x80108000); + WREG32(0x6578, 0x20101); + WREG32(0x657C, 0x8FE0BF70); + WREG32(0x6578, 0x20102); + WREG32(0x657C, 0xBFE880C0); + WREG32(0x6578, 0x20103); + WREG32(0x657C, 0x80008000); + WREG32(0x6578, 0x20200); + WREG32(0x657C, 0x8018BFF8); + WREG32(0x6578, 0x20201); + WREG32(0x657C, 0x8F80BF08); + WREG32(0x6578, 0x20202); + WREG32(0x657C, 0xBFD081A0); + WREG32(0x6578, 0x20203); + WREG32(0x657C, 0xBFF88000); + WREG32(0x6578, 0x20300); + WREG32(0x657C, 0x80188000); + WREG32(0x6578, 0x20301); + WREG32(0x657C, 0x8EE0BEC0); + WREG32(0x6578, 0x20302); + WREG32(0x657C, 0xBFB082A0); + WREG32(0x6578, 0x20303); + WREG32(0x657C, 0x80008000); + WREG32(0x6578, 0x20400); + WREG32(0x657C, 0x80188000); + WREG32(0x6578, 0x20401); + WREG32(0x657C, 0x8E00BEA0); + WREG32(0x6578, 0x20402); + WREG32(0x657C, 0xBF8883C0); + WREG32(0x6578, 0x20403); + WREG32(0x657C, 0x80008000); + WREG32(0x6578, 0x20500); + WREG32(0x657C, 0x80188000); + WREG32(0x6578, 0x20501); + WREG32(0x657C, 0x8D00BE90); + WREG32(0x6578, 0x20502); + WREG32(0x657C, 0xBF588500); + WREG32(0x6578, 0x20503); + WREG32(0x657C, 0x80008008); + WREG32(0x6578, 0x20600); + WREG32(0x657C, 0x80188000); + WREG32(0x6578, 0x20601); + WREG32(0x657C, 0x8BC0BE98); + WREG32(0x6578, 0x20602); + WREG32(0x657C, 0xBF308660); + WREG32(0x6578, 0x20603); + WREG32(0x657C, 0x80008008); + WREG32(0x6578, 0x20700); + WREG32(0x657C, 0x80108000); + WREG32(0x6578, 0x20701); + WREG32(0x657C, 0x8A80BEB0); + WREG32(0x6578, 0x20702); + WREG32(0x657C, 0xBF0087C0); + WREG32(0x6578, 0x20703); + WREG32(0x657C, 0x80008008); + WREG32(0x6578, 0x20800); + WREG32(0x657C, 0x80108000); + WREG32(0x6578, 0x20801); + WREG32(0x657C, 0x8920BED0); + WREG32(0x6578, 0x20802); + WREG32(0x657C, 0xBED08920); + WREG32(0x6578, 0x20803); + WREG32(0x657C, 0x80008010); + WREG32(0x6578, 0x30000); + WREG32(0x657C, 0x90008000); + WREG32(0x6578, 0x30001); + WREG32(0x657C, 0x80008000); + WREG32(0x6578, 0x30100); + WREG32(0x657C, 0x8FE0BF90); + WREG32(0x6578, 0x30101); + WREG32(0x657C, 0xBFF880A0); + WREG32(0x6578, 0x30200); + WREG32(0x657C, 0x8F60BF40); + WREG32(0x6578, 0x30201); + WREG32(0x657C, 0xBFE88180); + WREG32(0x6578, 0x30300); + WREG32(0x657C, 0x8EC0BF00); + WREG32(0x6578, 0x30301); + WREG32(0x657C, 0xBFC88280); + WREG32(0x6578, 0x30400); + WREG32(0x657C, 0x8DE0BEE0); + WREG32(0x6578, 0x30401); + WREG32(0x657C, 0xBFA083A0); + WREG32(0x6578, 0x30500); + WREG32(0x657C, 0x8CE0BED0); + WREG32(0x6578, 0x30501); + WREG32(0x657C, 0xBF7884E0); + WREG32(0x6578, 0x30600); + WREG32(0x657C, 0x8BA0BED8); + WREG32(0x6578, 0x30601); + WREG32(0x657C, 0xBF508640); + WREG32(0x6578, 0x30700); + WREG32(0x657C, 0x8A60BEE8); + WREG32(0x6578, 0x30701); + WREG32(0x657C, 0xBF2087A0); + WREG32(0x6578, 0x30800); + WREG32(0x657C, 0x8900BF00); + WREG32(0x6578, 0x30801); + WREG32(0x657C, 0xBF008900); +} + +struct rv515_watermark { + u32 lb_request_fifo_depth; + fixed20_12 num_line_pair; + fixed20_12 estimated_width; + fixed20_12 worst_case_latency; + fixed20_12 consumption_rate; + fixed20_12 active_time; + fixed20_12 dbpp; + fixed20_12 priority_mark_max; + fixed20_12 priority_mark; + fixed20_12 sclk; +}; + +void rv515_crtc_bandwidth_compute(struct radeon_device *rdev, + struct radeon_crtc *crtc, + struct rv515_watermark *wm) +{ + struct drm_display_mode *mode = &crtc->base.mode; + fixed20_12 a, b, c; + fixed20_12 pclk, request_fifo_depth, tolerable_latency, estimated_width; + fixed20_12 consumption_time, line_time, chunk_time, read_delay_latency; + + if (!crtc->base.enabled) { + /* FIXME: wouldn't it better to set priority mark to maximum */ + wm->lb_request_fifo_depth = 4; + return; + } + + if (crtc->vsc.full > rfixed_const(2)) + wm->num_line_pair.full = rfixed_const(2); + else + wm->num_line_pair.full = rfixed_const(1); + + b.full = rfixed_const(mode->crtc_hdisplay); + c.full = rfixed_const(256); + a.full = rfixed_mul(wm->num_line_pair, b); + request_fifo_depth.full = rfixed_div(a, c); + if (a.full < rfixed_const(4)) { + wm->lb_request_fifo_depth = 4; + } else { + wm->lb_request_fifo_depth = rfixed_trunc(request_fifo_depth); + } + + /* Determine consumption rate + * pclk = pixel clock period(ns) = 1000 / (mode.clock / 1000) + * vtaps = number of vertical taps, + * vsc = vertical scaling ratio, defined as source/destination + * hsc = horizontal scaling ration, defined as source/destination + */ + a.full = rfixed_const(mode->clock); + b.full = rfixed_const(1000); + a.full = rfixed_div(a, b); + pclk.full = rfixed_div(b, a); + if (crtc->rmx_type != RMX_OFF) { + b.full = rfixed_const(2); + if (crtc->vsc.full > b.full) + b.full = crtc->vsc.full; + b.full = rfixed_mul(b, crtc->hsc); + c.full = rfixed_const(2); + b.full = rfixed_div(b, c); + consumption_time.full = rfixed_div(pclk, b); + } else { + consumption_time.full = pclk.full; + } + a.full = rfixed_const(1); + wm->consumption_rate.full = rfixed_div(a, consumption_time); + + + /* Determine line time + * LineTime = total time for one line of displayhtotal + * LineTime = total number of horizontal pixels + * pclk = pixel clock period(ns) + */ + a.full = rfixed_const(crtc->base.mode.crtc_htotal); + line_time.full = rfixed_mul(a, pclk); + + /* Determine active time + * ActiveTime = time of active region of display within one line, + * hactive = total number of horizontal active pixels + * htotal = total number of horizontal pixels + */ + a.full = rfixed_const(crtc->base.mode.crtc_htotal); + b.full = rfixed_const(crtc->base.mode.crtc_hdisplay); + wm->active_time.full = rfixed_mul(line_time, b); + wm->active_time.full = rfixed_div(wm->active_time, a); + + /* Determine chunk time + * ChunkTime = the time it takes the DCP to send one chunk of data + * to the LB which consists of pipeline delay and inter chunk gap + * sclk = system clock(Mhz) + */ + a.full = rfixed_const(600 * 1000); + chunk_time.full = rfixed_div(a, rdev->pm.sclk); + read_delay_latency.full = rfixed_const(1000); + + /* Determine the worst case latency + * NumLinePair = Number of line pairs to request(1=2 lines, 2=4 lines) + * WorstCaseLatency = worst case time from urgent to when the MC starts + * to return data + * READ_DELAY_IDLE_MAX = constant of 1us + * ChunkTime = time it takes the DCP to send one chunk of data to the LB + * which consists of pipeline delay and inter chunk gap + */ + if (rfixed_trunc(wm->num_line_pair) > 1) { + a.full = rfixed_const(3); + wm->worst_case_latency.full = rfixed_mul(a, chunk_time); + wm->worst_case_latency.full += read_delay_latency.full; + } else { + wm->worst_case_latency.full = chunk_time.full + read_delay_latency.full; + } + + /* Determine the tolerable latency + * TolerableLatency = Any given request has only 1 line time + * for the data to be returned + * LBRequestFifoDepth = Number of chunk requests the LB can + * put into the request FIFO for a display + * LineTime = total time for one line of display + * ChunkTime = the time it takes the DCP to send one chunk + * of data to the LB which consists of + * pipeline delay and inter chunk gap + */ + if ((2+wm->lb_request_fifo_depth) >= rfixed_trunc(request_fifo_depth)) { + tolerable_latency.full = line_time.full; + } else { + tolerable_latency.full = rfixed_const(wm->lb_request_fifo_depth - 2); + tolerable_latency.full = request_fifo_depth.full - tolerable_latency.full; + tolerable_latency.full = rfixed_mul(tolerable_latency, chunk_time); + tolerable_latency.full = line_time.full - tolerable_latency.full; + } + /* We assume worst case 32bits (4 bytes) */ + wm->dbpp.full = rfixed_const(2 * 16); + + /* Determine the maximum priority mark + * width = viewport width in pixels + */ + a.full = rfixed_const(16); + wm->priority_mark_max.full = rfixed_const(crtc->base.mode.crtc_hdisplay); + wm->priority_mark_max.full = rfixed_div(wm->priority_mark_max, a); + + /* Determine estimated width */ + estimated_width.full = tolerable_latency.full - wm->worst_case_latency.full; + estimated_width.full = rfixed_div(estimated_width, consumption_time); + if (rfixed_trunc(estimated_width) > crtc->base.mode.crtc_hdisplay) { + wm->priority_mark.full = rfixed_const(10); + } else { + a.full = rfixed_const(16); + wm->priority_mark.full = rfixed_div(estimated_width, a); + wm->priority_mark.full = wm->priority_mark_max.full - wm->priority_mark.full; + } +} + +void rv515_bandwidth_avivo_update(struct radeon_device *rdev) +{ + struct drm_display_mode *mode0 = NULL; + struct drm_display_mode *mode1 = NULL; + struct rv515_watermark wm0; + struct rv515_watermark wm1; + u32 tmp; + fixed20_12 priority_mark02, priority_mark12, fill_rate; + fixed20_12 a, b; + + if (rdev->mode_info.crtcs[0]->base.enabled) + mode0 = &rdev->mode_info.crtcs[0]->base.mode; + if (rdev->mode_info.crtcs[1]->base.enabled) + mode1 = &rdev->mode_info.crtcs[1]->base.mode; + rs690_line_buffer_adjust(rdev, mode0, mode1); + + rv515_crtc_bandwidth_compute(rdev, rdev->mode_info.crtcs[0], &wm0); + rv515_crtc_bandwidth_compute(rdev, rdev->mode_info.crtcs[1], &wm1); + + tmp = wm0.lb_request_fifo_depth; + tmp |= wm1.lb_request_fifo_depth << 16; + WREG32(LB_MAX_REQ_OUTSTANDING, tmp); + + if (mode0 && mode1) { + if (rfixed_trunc(wm0.dbpp) > 64) + a.full = rfixed_div(wm0.dbpp, wm0.num_line_pair); + else + a.full = wm0.num_line_pair.full; + if (rfixed_trunc(wm1.dbpp) > 64) + b.full = rfixed_div(wm1.dbpp, wm1.num_line_pair); + else + b.full = wm1.num_line_pair.full; + a.full += b.full; + fill_rate.full = rfixed_div(wm0.sclk, a); + if (wm0.consumption_rate.full > fill_rate.full) { + b.full = wm0.consumption_rate.full - fill_rate.full; + b.full = rfixed_mul(b, wm0.active_time); + a.full = rfixed_const(16); + b.full = rfixed_div(b, a); + a.full = rfixed_mul(wm0.worst_case_latency, + wm0.consumption_rate); + priority_mark02.full = a.full + b.full; + } else { + a.full = rfixed_mul(wm0.worst_case_latency, + wm0.consumption_rate); + b.full = rfixed_const(16 * 1000); + priority_mark02.full = rfixed_div(a, b); + } + if (wm1.consumption_rate.full > fill_rate.full) { + b.full = wm1.consumption_rate.full - fill_rate.full; + b.full = rfixed_mul(b, wm1.active_time); + a.full = rfixed_const(16); + b.full = rfixed_div(b, a); + a.full = rfixed_mul(wm1.worst_case_latency, + wm1.consumption_rate); + priority_mark12.full = a.full + b.full; + } else { + a.full = rfixed_mul(wm1.worst_case_latency, + wm1.consumption_rate); + b.full = rfixed_const(16 * 1000); + priority_mark12.full = rfixed_div(a, b); + } + if (wm0.priority_mark.full > priority_mark02.full) + priority_mark02.full = wm0.priority_mark.full; + if (rfixed_trunc(priority_mark02) < 0) + priority_mark02.full = 0; + if (wm0.priority_mark_max.full > priority_mark02.full) + priority_mark02.full = wm0.priority_mark_max.full; + if (wm1.priority_mark.full > priority_mark12.full) + priority_mark12.full = wm1.priority_mark.full; + if (rfixed_trunc(priority_mark12) < 0) + priority_mark12.full = 0; + if (wm1.priority_mark_max.full > priority_mark12.full) + priority_mark12.full = wm1.priority_mark_max.full; + WREG32(D1MODE_PRIORITY_A_CNT, rfixed_trunc(priority_mark02)); + WREG32(D1MODE_PRIORITY_B_CNT, rfixed_trunc(priority_mark02)); + WREG32(D2MODE_PRIORITY_A_CNT, rfixed_trunc(priority_mark12)); + WREG32(D2MODE_PRIORITY_B_CNT, rfixed_trunc(priority_mark12)); + } else if (mode0) { + if (rfixed_trunc(wm0.dbpp) > 64) + a.full = rfixed_div(wm0.dbpp, wm0.num_line_pair); + else + a.full = wm0.num_line_pair.full; + fill_rate.full = rfixed_div(wm0.sclk, a); + if (wm0.consumption_rate.full > fill_rate.full) { + b.full = wm0.consumption_rate.full - fill_rate.full; + b.full = rfixed_mul(b, wm0.active_time); + a.full = rfixed_const(16); + b.full = rfixed_div(b, a); + a.full = rfixed_mul(wm0.worst_case_latency, + wm0.consumption_rate); + priority_mark02.full = a.full + b.full; + } else { + a.full = rfixed_mul(wm0.worst_case_latency, + wm0.consumption_rate); + b.full = rfixed_const(16); + priority_mark02.full = rfixed_div(a, b); + } + if (wm0.priority_mark.full > priority_mark02.full) + priority_mark02.full = wm0.priority_mark.full; + if (rfixed_trunc(priority_mark02) < 0) + priority_mark02.full = 0; + if (wm0.priority_mark_max.full > priority_mark02.full) + priority_mark02.full = wm0.priority_mark_max.full; + WREG32(D1MODE_PRIORITY_A_CNT, rfixed_trunc(priority_mark02)); + WREG32(D1MODE_PRIORITY_B_CNT, rfixed_trunc(priority_mark02)); + WREG32(D2MODE_PRIORITY_A_CNT, MODE_PRIORITY_OFF); + WREG32(D2MODE_PRIORITY_B_CNT, MODE_PRIORITY_OFF); + } else { + if (rfixed_trunc(wm1.dbpp) > 64) + a.full = rfixed_div(wm1.dbpp, wm1.num_line_pair); + else + a.full = wm1.num_line_pair.full; + fill_rate.full = rfixed_div(wm1.sclk, a); + if (wm1.consumption_rate.full > fill_rate.full) { + b.full = wm1.consumption_rate.full - fill_rate.full; + b.full = rfixed_mul(b, wm1.active_time); + a.full = rfixed_const(16); + b.full = rfixed_div(b, a); + a.full = rfixed_mul(wm1.worst_case_latency, + wm1.consumption_rate); + priority_mark12.full = a.full + b.full; + } else { + a.full = rfixed_mul(wm1.worst_case_latency, + wm1.consumption_rate); + b.full = rfixed_const(16 * 1000); + priority_mark12.full = rfixed_div(a, b); + } + if (wm1.priority_mark.full > priority_mark12.full) + priority_mark12.full = wm1.priority_mark.full; + if (rfixed_trunc(priority_mark12) < 0) + priority_mark12.full = 0; + if (wm1.priority_mark_max.full > priority_mark12.full) + priority_mark12.full = wm1.priority_mark_max.full; + WREG32(D1MODE_PRIORITY_A_CNT, MODE_PRIORITY_OFF); + WREG32(D1MODE_PRIORITY_B_CNT, MODE_PRIORITY_OFF); + WREG32(D2MODE_PRIORITY_A_CNT, rfixed_trunc(priority_mark12)); + WREG32(D2MODE_PRIORITY_B_CNT, rfixed_trunc(priority_mark12)); + } +} + +void rv515_bandwidth_update(struct radeon_device *rdev) +{ + uint32_t tmp; + struct drm_display_mode *mode0 = NULL; + struct drm_display_mode *mode1 = NULL; + + if (rdev->mode_info.crtcs[0]->base.enabled) + mode0 = &rdev->mode_info.crtcs[0]->base.mode; + if (rdev->mode_info.crtcs[1]->base.enabled) + mode1 = &rdev->mode_info.crtcs[1]->base.mode; + /* + * Set display0/1 priority up in the memory controller for + * modes if the user specifies HIGH for displaypriority + * option. + */ + if (rdev->disp_priority == 2) { + tmp = RREG32_MC(MC_MISC_LAT_TIMER); + tmp &= ~MC_DISP1R_INIT_LAT_MASK; + tmp &= ~MC_DISP0R_INIT_LAT_MASK; + if (mode1) + tmp |= (1 << MC_DISP1R_INIT_LAT_SHIFT); + if (mode0) + tmp |= (1 << MC_DISP0R_INIT_LAT_SHIFT); + WREG32_MC(MC_MISC_LAT_TIMER, tmp); + } + rv515_bandwidth_avivo_update(rdev); +} diff --git a/drivers/gpu/drm/radeon/rv515r.h b/drivers/gpu/drm/radeon/rv515r.h new file mode 100644 index 000000000000..f3cf84039906 --- /dev/null +++ b/drivers/gpu/drm/radeon/rv515r.h @@ -0,0 +1,170 @@ +/* + * Copyright 2008 Advanced Micro Devices, Inc. + * Copyright 2008 Red Hat Inc. + * Copyright 2009 Jerome Glisse. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: Dave Airlie + * Alex Deucher + * Jerome Glisse + */ +#ifndef RV515R_H +#define RV515R_H + +/* RV515 registers */ +#define PCIE_INDEX 0x0030 +#define PCIE_DATA 0x0034 +#define MC_IND_INDEX 0x0070 +#define MC_IND_WR_EN (1 << 24) +#define MC_IND_DATA 0x0074 +#define RBBM_SOFT_RESET 0x00F0 +#define CONFIG_MEMSIZE 0x00F8 +#define HDP_FB_LOCATION 0x0134 +#define CP_CSQ_CNTL 0x0740 +#define CP_CSQ_MODE 0x0744 +#define CP_CSQ_ADDR 0x07F0 +#define CP_CSQ_DATA 0x07F4 +#define CP_CSQ_STAT 0x07F8 +#define CP_CSQ2_STAT 0x07FC +#define RBBM_STATUS 0x0E40 +#define DST_PIPE_CONFIG 0x170C +#define WAIT_UNTIL 0x1720 +#define WAIT_2D_IDLE (1 << 14) +#define WAIT_3D_IDLE (1 << 15) +#define WAIT_2D_IDLECLEAN (1 << 16) +#define WAIT_3D_IDLECLEAN (1 << 17) +#define ISYNC_CNTL 0x1724 +#define ISYNC_ANY2D_IDLE3D (1 << 0) +#define ISYNC_ANY3D_IDLE2D (1 << 1) +#define ISYNC_TRIG2D_IDLE3D (1 << 2) +#define ISYNC_TRIG3D_IDLE2D (1 << 3) +#define ISYNC_WAIT_IDLEGUI (1 << 4) +#define ISYNC_CPSCRATCH_IDLEGUI (1 << 5) +#define VAP_INDEX_OFFSET 0x208C +#define VAP_PVS_STATE_FLUSH_REG 0x2284 +#define GB_ENABLE 0x4008 +#define GB_MSPOS0 0x4010 +#define MS_X0_SHIFT 0 +#define MS_Y0_SHIFT 4 +#define MS_X1_SHIFT 8 +#define MS_Y1_SHIFT 12 +#define MS_X2_SHIFT 16 +#define MS_Y2_SHIFT 20 +#define MSBD0_Y_SHIFT 24 +#define MSBD0_X_SHIFT 28 +#define GB_MSPOS1 0x4014 +#define MS_X3_SHIFT 0 +#define MS_Y3_SHIFT 4 +#define MS_X4_SHIFT 8 +#define MS_Y4_SHIFT 12 +#define MS_X5_SHIFT 16 +#define MS_Y5_SHIFT 20 +#define MSBD1_SHIFT 24 +#define GB_TILE_CONFIG 0x4018 +#define ENABLE_TILING (1 << 0) +#define PIPE_COUNT_MASK 0x0000000E +#define PIPE_COUNT_SHIFT 1 +#define TILE_SIZE_8 (0 << 4) +#define TILE_SIZE_16 (1 << 4) +#define TILE_SIZE_32 (2 << 4) +#define SUBPIXEL_1_12 (0 << 16) +#define SUBPIXEL_1_16 (1 << 16) +#define GB_SELECT 0x401C +#define GB_AA_CONFIG 0x4020 +#define GB_PIPE_SELECT 0x402C +#define GA_ENHANCE 0x4274 +#define GA_DEADLOCK_CNTL (1 << 0) +#define GA_FASTSYNC_CNTL (1 << 1) +#define GA_POLY_MODE 0x4288 +#define FRONT_PTYPE_POINT (0 << 4) +#define FRONT_PTYPE_LINE (1 << 4) +#define FRONT_PTYPE_TRIANGE (2 << 4) +#define BACK_PTYPE_POINT (0 << 7) +#define BACK_PTYPE_LINE (1 << 7) +#define BACK_PTYPE_TRIANGE (2 << 7) +#define GA_ROUND_MODE 0x428C +#define GEOMETRY_ROUND_TRUNC (0 << 0) +#define GEOMETRY_ROUND_NEAREST (1 << 0) +#define COLOR_ROUND_TRUNC (0 << 2) +#define COLOR_ROUND_NEAREST (1 << 2) +#define SU_REG_DEST 0x42C8 +#define RB3D_DSTCACHE_CTLSTAT 0x4E4C +#define RB3D_DC_FLUSH (2 << 0) +#define RB3D_DC_FREE (2 << 2) +#define RB3D_DC_FINISH (1 << 4) +#define ZB_ZCACHE_CTLSTAT 0x4F18 +#define ZC_FLUSH (1 << 0) +#define ZC_FREE (1 << 1) +#define DC_LB_MEMORY_SPLIT 0x6520 +#define DC_LB_MEMORY_SPLIT_MASK 0x00000003 +#define DC_LB_MEMORY_SPLIT_SHIFT 0 +#define DC_LB_MEMORY_SPLIT_D1HALF_D2HALF 0 +#define DC_LB_MEMORY_SPLIT_D1_3Q_D2_1Q 1 +#define DC_LB_MEMORY_SPLIT_D1_ONLY 2 +#define DC_LB_MEMORY_SPLIT_D1_1Q_D2_3Q 3 +#define DC_LB_MEMORY_SPLIT_SHIFT_MODE (1 << 2) +#define DC_LB_DISP1_END_ADR_SHIFT 4 +#define DC_LB_DISP1_END_ADR_MASK 0x00007FF0 +#define D1MODE_PRIORITY_A_CNT 0x6548 +#define MODE_PRIORITY_MARK_MASK 0x00007FFF +#define MODE_PRIORITY_OFF (1 << 16) +#define MODE_PRIORITY_ALWAYS_ON (1 << 20) +#define MODE_PRIORITY_FORCE_MASK (1 << 24) +#define D1MODE_PRIORITY_B_CNT 0x654C +#define LB_MAX_REQ_OUTSTANDING 0x6D58 +#define LB_D1_MAX_REQ_OUTSTANDING_MASK 0x0000000F +#define LB_D1_MAX_REQ_OUTSTANDING_SHIFT 0 +#define LB_D2_MAX_REQ_OUTSTANDING_MASK 0x000F0000 +#define LB_D2_MAX_REQ_OUTSTANDING_SHIFT 16 +#define D2MODE_PRIORITY_A_CNT 0x6D48 +#define D2MODE_PRIORITY_B_CNT 0x6D4C + +/* ix[MC] registers */ +#define MC_FB_LOCATION 0x01 +#define MC_FB_START_MASK 0x0000FFFF +#define MC_FB_START_SHIFT 0 +#define MC_FB_TOP_MASK 0xFFFF0000 +#define MC_FB_TOP_SHIFT 16 +#define MC_AGP_LOCATION 0x02 +#define MC_AGP_START_MASK 0x0000FFFF +#define MC_AGP_START_SHIFT 0 +#define MC_AGP_TOP_MASK 0xFFFF0000 +#define MC_AGP_TOP_SHIFT 16 +#define MC_AGP_BASE 0x03 +#define MC_AGP_BASE_2 0x04 +#define MC_CNTL 0x5 +#define MEM_NUM_CHANNELS_MASK 0x00000003 +#define MC_STATUS 0x08 +#define MC_STATUS_IDLE (1 << 4) +#define MC_MISC_LAT_TIMER 0x09 +#define MC_CPR_INIT_LAT_MASK 0x0000000F +#define MC_VF_INIT_LAT_MASK 0x000000F0 +#define MC_DISP0R_INIT_LAT_MASK 0x00000F00 +#define MC_DISP0R_INIT_LAT_SHIFT 8 +#define MC_DISP1R_INIT_LAT_MASK 0x0000F000 +#define MC_DISP1R_INIT_LAT_SHIFT 12 +#define MC_FIXED_INIT_LAT_MASK 0x000F0000 +#define MC_E2R_INIT_LAT_MASK 0x00F00000 +#define SAME_PAGE_PRIO_MASK 0x0F000000 +#define MC_GLOBW_INIT_LAT_MASK 0xF0000000 + + +#endif + -- cgit v1.2.3 From e46074effd5510e7a8fe34b93828d98a50835da2 Mon Sep 17 00:00:00 2001 From: Michel Dänzer Date: Tue, 28 Jul 2009 12:30:55 +0200 Subject: drm/radeon: Don't unreserve twice on failure to validate. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is done later in radeon_object_list_unvalidate(). Doing it twice triggers a BUG in TTM, rendering X on KMS unusable until reboot. Signed-off-by: Michel Dänzer Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/radeon_object.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/gpu/drm/radeon/radeon_object.c b/drivers/gpu/drm/radeon/radeon_object.c index d5b1fd562d88..3961a44c5dce 100644 --- a/drivers/gpu/drm/radeon/radeon_object.c +++ b/drivers/gpu/drm/radeon/radeon_object.c @@ -433,7 +433,6 @@ int radeon_object_list_validate(struct list_head *head, void *fence) robj->tobj.proposed_placement, true, false); if (unlikely(r)) { - radeon_object_list_unreserve(head); DRM_ERROR("radeon: failed to validate.\n"); return r; } -- cgit v1.2.3 From 1ab2e1059916b917af19e4137a4222988bd7a169 Mon Sep 17 00:00:00 2001 From: Michel Dänzer Date: Tue, 28 Jul 2009 12:30:56 +0200 Subject: drm/radeon: Fall back to evicting BOs with memcpy if necessary. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Otherwise if there's no GTT space we would fail the eviction, leading to cascaded failure. Signed-off-by: Michel Dänzer Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/radeon_ttm.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/radeon/radeon_ttm.c b/drivers/gpu/drm/radeon/radeon_ttm.c index 37e1cbcce3a9..f3469b96208c 100644 --- a/drivers/gpu/drm/radeon/radeon_ttm.c +++ b/drivers/gpu/drm/radeon/radeon_ttm.c @@ -355,23 +355,26 @@ static int radeon_bo_move(struct ttm_buffer_object *bo, if (!rdev->cp.ready) { /* use memcpy */ DRM_ERROR("CP is not ready use memcpy.\n"); - return ttm_bo_move_memcpy(bo, evict, no_wait, new_mem); + goto memcpy; } if (old_mem->mem_type == TTM_PL_VRAM && new_mem->mem_type == TTM_PL_SYSTEM) { - return radeon_move_vram_ram(bo, evict, interruptible, + r = radeon_move_vram_ram(bo, evict, interruptible, no_wait, new_mem); } else if (old_mem->mem_type == TTM_PL_SYSTEM && new_mem->mem_type == TTM_PL_VRAM) { - return radeon_move_ram_vram(bo, evict, interruptible, + r = radeon_move_ram_vram(bo, evict, interruptible, no_wait, new_mem); } else { r = radeon_move_blit(bo, evict, no_wait, new_mem, old_mem); - if (unlikely(r)) { - return r; - } } + + if (r) { +memcpy: + r = ttm_bo_move_memcpy(bo, evict, no_wait, new_mem); + } + return r; } -- cgit v1.2.3 From 664f86590295217b2319edf88830e87b800f6c4a Mon Sep 17 00:00:00 2001 From: Michel Dänzer Date: Tue, 28 Jul 2009 12:30:57 +0200 Subject: drm/radeon: Pay more attention to object placement requested by userspace. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Previously we were basically always setting the GTT and VRAM flags regardless of what userspace requested. Signed-off-by: Michel Dänzer Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/radeon_object.c | 25 +++++++++++-------------- 1 file changed, 11 insertions(+), 14 deletions(-) diff --git a/drivers/gpu/drm/radeon/radeon_object.c b/drivers/gpu/drm/radeon/radeon_object.c index 3961a44c5dce..81573c3a9b43 100644 --- a/drivers/gpu/drm/radeon/radeon_object.c +++ b/drivers/gpu/drm/radeon/radeon_object.c @@ -103,16 +103,16 @@ static inline uint32_t radeon_object_flags_from_domain(uint32_t domain) { uint32_t flags = 0; if (domain & RADEON_GEM_DOMAIN_VRAM) { - flags |= TTM_PL_FLAG_VRAM; + flags |= TTM_PL_FLAG_VRAM | TTM_PL_FLAG_WC | TTM_PL_FLAG_UNCACHED; } if (domain & RADEON_GEM_DOMAIN_GTT) { - flags |= TTM_PL_FLAG_TT; + flags |= TTM_PL_FLAG_TT | TTM_PL_FLAG_WC | TTM_PL_FLAG_UNCACHED; } if (domain & RADEON_GEM_DOMAIN_CPU) { - flags |= TTM_PL_FLAG_SYSTEM; + flags |= TTM_PL_FLAG_SYSTEM | TTM_PL_MASK_CACHING; } if (!flags) { - flags |= TTM_PL_FLAG_SYSTEM; + flags |= TTM_PL_FLAG_SYSTEM | TTM_PL_MASK_CACHING; } return flags; } @@ -408,7 +408,6 @@ int radeon_object_list_validate(struct list_head *head, void *fence) struct radeon_object *robj; struct radeon_fence *old_fence = NULL; struct list_head *i; - uint32_t flags; int r; r = radeon_object_list_reserve(head); @@ -419,16 +418,14 @@ int radeon_object_list_validate(struct list_head *head, void *fence) list_for_each(i, head) { lobj = list_entry(i, struct radeon_object_list, list); robj = lobj->robj; - if (lobj->wdomain) { - flags = radeon_object_flags_from_domain(lobj->wdomain); - flags |= TTM_PL_FLAG_TT; - } else { - flags = radeon_object_flags_from_domain(lobj->rdomain); - flags |= TTM_PL_FLAG_TT; - flags |= TTM_PL_FLAG_VRAM; - } if (!robj->pin_count) { - robj->tobj.proposed_placement = flags | TTM_PL_MASK_CACHING; + if (lobj->wdomain) { + robj->tobj.proposed_placement = + radeon_object_flags_from_domain(lobj->wdomain); + } else { + robj->tobj.proposed_placement = + radeon_object_flags_from_domain(lobj->rdomain); + } r = ttm_buffer_object_validate(&robj->tobj, robj->tobj.proposed_placement, true, false); -- cgit v1.2.3 From 7a50f01a4ab89d5c05eb2cf62e206ac0bfc61d2c Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Tue, 21 Jul 2009 20:39:30 +1000 Subject: drm/radeon/kms: vram sizing on certain r100 chips needs workaround. If an rn50/r100/m6/m7 GPU has < 64MB RAM, i.e. 8/16/32, the aperture used to calculate the MC_FB_LOCATION needs to be worked out from the CONFIG_APER_SIZE register, and not the actual vram size. TTM VRAM size was also being initialised wrong, use actual vram size to initialise it. Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/r100.c | 34 ++++++++++++++++++++++------------ drivers/gpu/drm/radeon/r520.c | 4 ++-- drivers/gpu/drm/radeon/r600.c | 5 +++-- drivers/gpu/drm/radeon/radeon.h | 5 ++++- drivers/gpu/drm/radeon/radeon_device.c | 20 +++++++++++--------- drivers/gpu/drm/radeon/radeon_gem.c | 4 ++-- drivers/gpu/drm/radeon/radeon_ttm.c | 4 ++-- drivers/gpu/drm/radeon/rs400.c | 4 ++-- drivers/gpu/drm/radeon/rs600.c | 2 +- drivers/gpu/drm/radeon/rs690.c | 7 ++++--- drivers/gpu/drm/radeon/rv515.c | 7 ++----- drivers/gpu/drm/radeon/rv770.c | 2 +- 12 files changed, 56 insertions(+), 42 deletions(-) diff --git a/drivers/gpu/drm/radeon/r100.c b/drivers/gpu/drm/radeon/r100.c index 0e00fef0b84f..05a44896dffb 100644 --- a/drivers/gpu/drm/radeon/r100.c +++ b/drivers/gpu/drm/radeon/r100.c @@ -173,8 +173,12 @@ void r100_mc_setup(struct radeon_device *rdev) DRM_ERROR("Failed to register debugfs file for R100 MC !\n"); } /* Write VRAM size in case we are limiting it */ - WREG32(RADEON_CONFIG_MEMSIZE, rdev->mc.vram_size); - tmp = rdev->mc.vram_location + rdev->mc.vram_size - 1; + WREG32(RADEON_CONFIG_MEMSIZE, rdev->mc.real_vram_size); + /* Novell bug 204882 for RN50/M6/M7 with 8/16/32MB VRAM, + * if the aperture is 64MB but we have 32MB VRAM + * we report only 32MB VRAM but we have to set MC_FB_LOCATION + * to 64MB, otherwise the gpu accidentially dies */ + tmp = rdev->mc.vram_location + rdev->mc.mc_vram_size - 1; tmp = REG_SET(RADEON_MC_FB_TOP, tmp >> 16); tmp |= REG_SET(RADEON_MC_FB_START, rdev->mc.vram_location >> 16); WREG32(RADEON_MC_FB_LOCATION, tmp); @@ -1447,25 +1451,28 @@ void r100_vram_init_sizes(struct radeon_device *rdev) uint32_t tom; /* read NB_TOM to get the amount of ram stolen for the GPU */ tom = RREG32(RADEON_NB_TOM); - rdev->mc.vram_size = (((tom >> 16) - (tom & 0xffff) + 1) << 16); + rdev->mc.real_vram_size = (((tom >> 16) - (tom & 0xffff) + 1) << 16); /* for IGPs we need to keep VRAM where it was put by the BIOS */ rdev->mc.vram_location = (tom & 0xffff) << 16; - WREG32(RADEON_CONFIG_MEMSIZE, rdev->mc.vram_size); + WREG32(RADEON_CONFIG_MEMSIZE, rdev->mc.real_vram_size); + rdev->mc.mc_vram_size = rdev->mc.real_vram_size; } else { - rdev->mc.vram_size = RREG32(RADEON_CONFIG_MEMSIZE); + rdev->mc.real_vram_size = RREG32(RADEON_CONFIG_MEMSIZE); /* Some production boards of m6 will report 0 * if it's 8 MB */ - if (rdev->mc.vram_size == 0) { - rdev->mc.vram_size = 8192 * 1024; - WREG32(RADEON_CONFIG_MEMSIZE, rdev->mc.vram_size); + if (rdev->mc.real_vram_size == 0) { + rdev->mc.real_vram_size = 8192 * 1024; + WREG32(RADEON_CONFIG_MEMSIZE, rdev->mc.real_vram_size); } /* let driver place VRAM */ rdev->mc.vram_location = 0xFFFFFFFFUL; /* Fix for RN50, M6, M7 with 8/16/32(??) MBs of VRAM - * Novell bug 204882 + along with lots of ubuntu ones */ - if (config_aper_size > rdev->mc.vram_size) - rdev->mc.vram_size = config_aper_size; + if (config_aper_size > rdev->mc.real_vram_size) + rdev->mc.mc_vram_size = config_aper_size; + else + rdev->mc.mc_vram_size = rdev->mc.real_vram_size; } /* work out accessible VRAM */ @@ -1477,8 +1484,11 @@ void r100_vram_init_sizes(struct radeon_device *rdev) if (accessible > rdev->mc.aper_size) accessible = rdev->mc.aper_size; - if (rdev->mc.vram_size > rdev->mc.aper_size) - rdev->mc.vram_size = rdev->mc.aper_size; + if (rdev->mc.mc_vram_size > rdev->mc.aper_size) + rdev->mc.mc_vram_size = rdev->mc.aper_size; + + if (rdev->mc.real_vram_size > rdev->mc.aper_size) + rdev->mc.real_vram_size = rdev->mc.aper_size; } void r100_vram_info(struct radeon_device *rdev) diff --git a/drivers/gpu/drm/radeon/r520.c b/drivers/gpu/drm/radeon/r520.c index 0a981e2ee2f8..09fb0b6ec7dd 100644 --- a/drivers/gpu/drm/radeon/r520.c +++ b/drivers/gpu/drm/radeon/r520.c @@ -95,8 +95,8 @@ int r520_mc_init(struct radeon_device *rdev) "programming pipes. Bad things might happen.\n"); } /* Write VRAM size in case we are limiting it */ - WREG32(RADEON_CONFIG_MEMSIZE, rdev->mc.vram_size); - tmp = rdev->mc.vram_location + rdev->mc.vram_size - 1; + WREG32(RADEON_CONFIG_MEMSIZE, rdev->mc.real_vram_size); + tmp = rdev->mc.vram_location + rdev->mc.mc_vram_size - 1; tmp = REG_SET(R520_MC_FB_TOP, tmp >> 16); tmp |= REG_SET(R520_MC_FB_START, rdev->mc.vram_location >> 16); WREG32_MC(R520_MC_FB_LOCATION, tmp); diff --git a/drivers/gpu/drm/radeon/r600.c b/drivers/gpu/drm/radeon/r600.c index c45559fc97fd..538cd907df69 100644 --- a/drivers/gpu/drm/radeon/r600.c +++ b/drivers/gpu/drm/radeon/r600.c @@ -67,7 +67,7 @@ int r600_mc_init(struct radeon_device *rdev) "programming pipes. Bad things might happen.\n"); } - tmp = rdev->mc.vram_location + rdev->mc.vram_size - 1; + tmp = rdev->mc.vram_location + rdev->mc.mc_vram_size - 1; tmp = REG_SET(R600_MC_FB_TOP, tmp >> 24); tmp |= REG_SET(R600_MC_FB_BASE, rdev->mc.vram_location >> 24); WREG32(R600_MC_VM_FB_LOCATION, tmp); @@ -140,7 +140,8 @@ void r600_vram_get_type(struct radeon_device *rdev) void r600_vram_info(struct radeon_device *rdev) { r600_vram_get_type(rdev); - rdev->mc.vram_size = RREG32(R600_CONFIG_MEMSIZE); + rdev->mc.real_vram_size = RREG32(R600_CONFIG_MEMSIZE); + rdev->mc.mc_vram_size = rdev->mc.real_vram_size; /* Could aper size report 0 ? */ rdev->mc.aper_base = drm_get_resource_start(rdev->ddev, 0); diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h index 63a3fe32e584..045b33b3bf2d 100644 --- a/drivers/gpu/drm/radeon/radeon.h +++ b/drivers/gpu/drm/radeon/radeon.h @@ -332,8 +332,11 @@ struct radeon_mc { unsigned gtt_location; unsigned gtt_size; unsigned vram_location; - unsigned vram_size; + /* for some chips with <= 32MB we need to lie + * about vram size near mc fb location */ + unsigned mc_vram_size; unsigned vram_width; + unsigned real_vram_size; int vram_mtrr; bool vram_is_ddr; }; diff --git a/drivers/gpu/drm/radeon/radeon_device.c b/drivers/gpu/drm/radeon/radeon_device.c index f78db5c8008c..6d1749e44222 100644 --- a/drivers/gpu/drm/radeon/radeon_device.c +++ b/drivers/gpu/drm/radeon/radeon_device.c @@ -121,7 +121,7 @@ int radeon_mc_setup(struct radeon_device *rdev) if (rdev->mc.vram_location != 0xFFFFFFFFUL) { /* vram location was already setup try to put gtt after * if it fits */ - tmp = rdev->mc.vram_location + rdev->mc.vram_size; + tmp = rdev->mc.vram_location + rdev->mc.mc_vram_size; tmp = (tmp + rdev->mc.gtt_size - 1) & ~(rdev->mc.gtt_size - 1); if ((0xFFFFFFFFUL - tmp) >= rdev->mc.gtt_size) { rdev->mc.gtt_location = tmp; @@ -136,13 +136,13 @@ int radeon_mc_setup(struct radeon_device *rdev) } else if (rdev->mc.gtt_location != 0xFFFFFFFFUL) { /* gtt location was already setup try to put vram before * if it fits */ - if (rdev->mc.vram_size < rdev->mc.gtt_location) { + if (rdev->mc.mc_vram_size < rdev->mc.gtt_location) { rdev->mc.vram_location = 0; } else { tmp = rdev->mc.gtt_location + rdev->mc.gtt_size; - tmp += (rdev->mc.vram_size - 1); - tmp &= ~(rdev->mc.vram_size - 1); - if ((0xFFFFFFFFUL - tmp) >= rdev->mc.vram_size) { + tmp += (rdev->mc.mc_vram_size - 1); + tmp &= ~(rdev->mc.mc_vram_size - 1); + if ((0xFFFFFFFFUL - tmp) >= rdev->mc.mc_vram_size) { rdev->mc.vram_location = tmp; } else { printk(KERN_ERR "[drm] vram too big to fit " @@ -152,12 +152,14 @@ int radeon_mc_setup(struct radeon_device *rdev) } } else { rdev->mc.vram_location = 0; - rdev->mc.gtt_location = rdev->mc.vram_size; + rdev->mc.gtt_location = rdev->mc.mc_vram_size; } - DRM_INFO("radeon: VRAM %uM\n", rdev->mc.vram_size >> 20); + DRM_INFO("radeon: VRAM %uM\n", rdev->mc.real_vram_size >> 20); DRM_INFO("radeon: VRAM from 0x%08X to 0x%08X\n", rdev->mc.vram_location, - rdev->mc.vram_location + rdev->mc.vram_size - 1); + rdev->mc.vram_location + rdev->mc.mc_vram_size - 1); + if (rdev->mc.real_vram_size != rdev->mc.mc_vram_size) + DRM_INFO("radeon: VRAM less than aperture workaround enabled\n"); DRM_INFO("radeon: GTT %uM\n", rdev->mc.gtt_size >> 20); DRM_INFO("radeon: GTT from 0x%08X to 0x%08X\n", rdev->mc.gtt_location, @@ -573,7 +575,7 @@ int radeon_device_init(struct radeon_device *rdev, rdev->mc.vram_mtrr = mtrr_add(rdev->mc.aper_base, rdev->mc.aper_size, MTRR_TYPE_WRCOMB, 1); DRM_INFO("Detected VRAM RAM=%uM, BAR=%uM\n", - rdev->mc.vram_size >> 20, + rdev->mc.real_vram_size >> 20, (unsigned)rdev->mc.aper_size >> 20); DRM_INFO("RAM width %dbits %cDR\n", rdev->mc.vram_width, rdev->mc.vram_is_ddr ? 'D' : 'S'); diff --git a/drivers/gpu/drm/radeon/radeon_gem.c b/drivers/gpu/drm/radeon/radeon_gem.c index 12542087b298..cded5180c752 100644 --- a/drivers/gpu/drm/radeon/radeon_gem.c +++ b/drivers/gpu/drm/radeon/radeon_gem.c @@ -157,9 +157,9 @@ int radeon_gem_info_ioctl(struct drm_device *dev, void *data, struct radeon_device *rdev = dev->dev_private; struct drm_radeon_gem_info *args = data; - args->vram_size = rdev->mc.vram_size; + args->vram_size = rdev->mc.real_vram_size; /* FIXME: report somethings that makes sense */ - args->vram_visible = rdev->mc.vram_size - (4 * 1024 * 1024); + args->vram_visible = rdev->mc.real_vram_size - (4 * 1024 * 1024); args->gart_size = rdev->mc.gtt_size; return 0; } diff --git a/drivers/gpu/drm/radeon/radeon_ttm.c b/drivers/gpu/drm/radeon/radeon_ttm.c index f3469b96208c..15c3531377ed 100644 --- a/drivers/gpu/drm/radeon/radeon_ttm.c +++ b/drivers/gpu/drm/radeon/radeon_ttm.c @@ -454,7 +454,7 @@ int radeon_ttm_init(struct radeon_device *rdev) return r; } r = ttm_bo_init_mm(&rdev->mman.bdev, TTM_PL_VRAM, 0, - ((rdev->mc.aper_size) >> PAGE_SHIFT)); + ((rdev->mc.real_vram_size) >> PAGE_SHIFT)); if (r) { DRM_ERROR("Failed initializing VRAM heap.\n"); return r; @@ -471,7 +471,7 @@ int radeon_ttm_init(struct radeon_device *rdev) return r; } DRM_INFO("radeon: %uM of VRAM memory ready\n", - rdev->mc.vram_size / (1024 * 1024)); + rdev->mc.real_vram_size / (1024 * 1024)); r = ttm_bo_init_mm(&rdev->mman.bdev, TTM_PL_TT, 0, ((rdev->mc.gtt_size) >> PAGE_SHIFT)); if (r) { diff --git a/drivers/gpu/drm/radeon/rs400.c b/drivers/gpu/drm/radeon/rs400.c index 96a3c8486d25..b29affd9c5d8 100644 --- a/drivers/gpu/drm/radeon/rs400.c +++ b/drivers/gpu/drm/radeon/rs400.c @@ -233,7 +233,7 @@ int rs400_mc_init(struct radeon_device *rdev) rs400_gpu_init(rdev); rs400_gart_disable(rdev); - rdev->mc.gtt_location = rdev->mc.vram_size; + rdev->mc.gtt_location = rdev->mc.mc_vram_size; rdev->mc.gtt_location += (rdev->mc.gtt_size - 1); rdev->mc.gtt_location &= ~(rdev->mc.gtt_size - 1); r = radeon_mc_setup(rdev); @@ -247,7 +247,7 @@ int rs400_mc_init(struct radeon_device *rdev) "programming pipes. Bad things might happen.\n"); } - tmp = rdev->mc.vram_location + rdev->mc.vram_size - 1; + tmp = rdev->mc.vram_location + rdev->mc.mc_vram_size - 1; tmp = REG_SET(RADEON_MC_FB_TOP, tmp >> 16); tmp |= REG_SET(RADEON_MC_FB_START, rdev->mc.vram_location >> 16); WREG32(RADEON_MC_FB_LOCATION, tmp); diff --git a/drivers/gpu/drm/radeon/rs600.c b/drivers/gpu/drm/radeon/rs600.c index bccdce7fd379..bbea6dee4a94 100644 --- a/drivers/gpu/drm/radeon/rs600.c +++ b/drivers/gpu/drm/radeon/rs600.c @@ -223,7 +223,7 @@ int rs600_mc_init(struct radeon_device *rdev) printk(KERN_WARNING "Failed to wait MC idle while " "programming pipes. Bad things might happen.\n"); } - tmp = rdev->mc.vram_location + rdev->mc.vram_size - 1; + tmp = rdev->mc.vram_location + rdev->mc.mc_vram_size - 1; tmp = REG_SET(RS600_MC_FB_TOP, tmp >> 16); tmp |= REG_SET(RS600_MC_FB_START, rdev->mc.vram_location >> 16); WREG32_MC(RS600_MC_FB_LOCATION, tmp); diff --git a/drivers/gpu/drm/radeon/rs690.c b/drivers/gpu/drm/radeon/rs690.c index 97eaee3d28b8..839595b00728 100644 --- a/drivers/gpu/drm/radeon/rs690.c +++ b/drivers/gpu/drm/radeon/rs690.c @@ -67,7 +67,7 @@ int rs690_mc_init(struct radeon_device *rdev) rs400_gart_disable(rdev); /* Setup GPU memory space */ - rdev->mc.gtt_location = rdev->mc.vram_size; + rdev->mc.gtt_location = rdev->mc.mc_vram_size; rdev->mc.gtt_location += (rdev->mc.gtt_size - 1); rdev->mc.gtt_location &= ~(rdev->mc.gtt_size - 1); rdev->mc.vram_location = 0xFFFFFFFFUL; @@ -82,7 +82,7 @@ int rs690_mc_init(struct radeon_device *rdev) printk(KERN_WARNING "Failed to wait MC idle while " "programming pipes. Bad things might happen.\n"); } - tmp = rdev->mc.vram_location + rdev->mc.vram_size - 1; + tmp = rdev->mc.vram_location + rdev->mc.mc_vram_size - 1; tmp = REG_SET(RS690_MC_FB_TOP, tmp >> 16); tmp |= REG_SET(RS690_MC_FB_START, rdev->mc.vram_location >> 16); WREG32_MC(RS690_MCCFG_FB_LOCATION, tmp); @@ -228,7 +228,8 @@ void rs690_vram_info(struct radeon_device *rdev) } else { rdev->mc.vram_width = 64; } - rdev->mc.vram_size = RREG32(RADEON_CONFIG_MEMSIZE); + rdev->mc.real_vram_size = RREG32(RADEON_CONFIG_MEMSIZE); + rdev->mc.mc_vram_size = rdev->mc.real_vram_size; rdev->mc.aper_base = drm_get_resource_start(rdev->ddev, 0); rdev->mc.aper_size = drm_get_resource_len(rdev->ddev, 0); diff --git a/drivers/gpu/drm/radeon/rv515.c b/drivers/gpu/drm/radeon/rv515.c index 4fd411893b91..551e608702e4 100644 --- a/drivers/gpu/drm/radeon/rv515.c +++ b/drivers/gpu/drm/radeon/rv515.c @@ -100,10 +100,10 @@ int rv515_mc_init(struct radeon_device *rdev) "programming pipes. Bad things might happen.\n"); } /* Write VRAM size in case we are limiting it */ - WREG32(RADEON_CONFIG_MEMSIZE, rdev->mc.vram_size); + WREG32(RADEON_CONFIG_MEMSIZE, rdev->mc.real_vram_size); tmp = REG_SET(MC_FB_START, rdev->mc.vram_location >> 16); WREG32(0x134, tmp); - tmp = rdev->mc.vram_location + rdev->mc.vram_size - 1; + tmp = rdev->mc.vram_location + rdev->mc.mc_vram_size - 1; tmp = REG_SET(MC_FB_TOP, tmp >> 16); tmp |= REG_SET(MC_FB_START, rdev->mc.vram_location >> 16); WREG32_MC(MC_FB_LOCATION, tmp); @@ -369,10 +369,7 @@ void rv515_vram_info(struct radeon_device *rdev) fixed20_12 a; rv515_vram_get_type(rdev); - rdev->mc.vram_size = RREG32(CONFIG_MEMSIZE); - rdev->mc.aper_base = drm_get_resource_start(rdev->ddev, 0); - rdev->mc.aper_size = drm_get_resource_len(rdev->ddev, 0); /* FIXME: we should enforce default clock in case GPU is not in * default setup */ diff --git a/drivers/gpu/drm/radeon/rv770.c b/drivers/gpu/drm/radeon/rv770.c index da50cc51ede3..21d8ffd57308 100644 --- a/drivers/gpu/drm/radeon/rv770.c +++ b/drivers/gpu/drm/radeon/rv770.c @@ -67,7 +67,7 @@ int rv770_mc_init(struct radeon_device *rdev) "programming pipes. Bad things might happen.\n"); } - tmp = rdev->mc.vram_location + rdev->mc.vram_size - 1; + tmp = rdev->mc.vram_location + rdev->mc.mc_vram_size - 1; tmp = REG_SET(R700_MC_FB_TOP, tmp >> 24); tmp |= REG_SET(R700_MC_FB_BASE, rdev->mc.vram_location >> 24); WREG32(R700_MC_VM_FB_LOCATION, tmp); -- cgit v1.2.3 From 4677f15c60421d48566c48c3149474e64977f071 Mon Sep 17 00:00:00 2001 From: Thomas Hellstrom Date: Tue, 21 Jul 2009 17:45:13 +0200 Subject: drm/ttm: Fix an oops and sync object leak. The code was potentially dereferencig a NULL sync object pointer. At the same time a sync object reference was potentially leaked. Signed-off-by: Thomas Hellstrom Signed-off-by: Dave Airlie --- drivers/gpu/drm/ttm/ttm_bo_util.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/ttm/ttm_bo_util.c b/drivers/gpu/drm/ttm/ttm_bo_util.c index bdec583901eb..3e5d0c4ad85c 100644 --- a/drivers/gpu/drm/ttm/ttm_bo_util.c +++ b/drivers/gpu/drm/ttm/ttm_bo_util.c @@ -509,8 +509,8 @@ int ttm_bo_move_accel_cleanup(struct ttm_buffer_object *bo, if (evict) { ret = ttm_bo_wait(bo, false, false, false); spin_unlock(&bo->lock); - driver->sync_obj_unref(&bo->sync_obj); - + if (tmp_obj) + driver->sync_obj_unref(&tmp_obj); if (ret) return ret; @@ -532,6 +532,8 @@ int ttm_bo_move_accel_cleanup(struct ttm_buffer_object *bo, set_bit(TTM_BO_PRIV_FLAG_MOVING, &bo->priv_flags); spin_unlock(&bo->lock); + if (tmp_obj) + driver->sync_obj_unref(&tmp_obj); ret = ttm_buffer_object_transfer(bo, &ghost_obj); if (ret) -- cgit v1.2.3 From 542c6f6df51327dbb180cf4d9b34827e147efe17 Mon Sep 17 00:00:00 2001 From: Thomas Hellstrom Date: Fri, 24 Jul 2009 09:57:34 +0200 Subject: drm/ttm: Fix ttm in-kernel copying of pages with non-standard caching attributes. For x86 this affected highmem pages only, since they were always kmapped cache-coherent, and this is fixed using kmap_atomic_prot(). For other architectures that may not modify the linear kernel map we resort to vmap() for now, since kmap_atomic_prot() generally uses the linear kernel map for lowmem pages. This of course comes with a performance impact and should be optimized when possible. Signed-off-by: Thomas Hellstrom Signed-off-by: Dave Airlie --- drivers/gpu/drm/ttm/ttm_bo_util.c | 63 ++++++++++++++++++++++++++++++++------- 1 file changed, 52 insertions(+), 11 deletions(-) diff --git a/drivers/gpu/drm/ttm/ttm_bo_util.c b/drivers/gpu/drm/ttm/ttm_bo_util.c index 3e5d0c4ad85c..ce2e6f38ea01 100644 --- a/drivers/gpu/drm/ttm/ttm_bo_util.c +++ b/drivers/gpu/drm/ttm/ttm_bo_util.c @@ -136,7 +136,8 @@ static int ttm_copy_io_page(void *dst, void *src, unsigned long page) } static int ttm_copy_io_ttm_page(struct ttm_tt *ttm, void *src, - unsigned long page) + unsigned long page, + pgprot_t prot) { struct page *d = ttm_tt_get_page(ttm, page); void *dst; @@ -145,17 +146,35 @@ static int ttm_copy_io_ttm_page(struct ttm_tt *ttm, void *src, return -ENOMEM; src = (void *)((unsigned long)src + (page << PAGE_SHIFT)); - dst = kmap(d); + +#ifdef CONFIG_X86 + dst = kmap_atomic_prot(d, KM_USER0, prot); +#else + if (prot != PAGE_KERNEL) + dst = vmap(&d, 1, 0, prot); + else + dst = kmap(d); +#endif if (!dst) return -ENOMEM; memcpy_fromio(dst, src, PAGE_SIZE); - kunmap(d); + +#ifdef CONFIG_X86 + kunmap_atomic(dst, KM_USER0); +#else + if (prot != PAGE_KERNEL) + vunmap(dst); + else + kunmap(d); +#endif + return 0; } static int ttm_copy_ttm_io_page(struct ttm_tt *ttm, void *dst, - unsigned long page) + unsigned long page, + pgprot_t prot) { struct page *s = ttm_tt_get_page(ttm, page); void *src; @@ -164,12 +183,28 @@ static int ttm_copy_ttm_io_page(struct ttm_tt *ttm, void *dst, return -ENOMEM; dst = (void *)((unsigned long)dst + (page << PAGE_SHIFT)); - src = kmap(s); +#ifdef CONFIG_X86 + src = kmap_atomic_prot(s, KM_USER0, prot); +#else + if (prot != PAGE_KERNEL) + src = vmap(&s, 1, 0, prot); + else + src = kmap(s); +#endif if (!src) return -ENOMEM; memcpy_toio(dst, src, PAGE_SIZE); - kunmap(s); + +#ifdef CONFIG_X86 + kunmap_atomic(src, KM_USER0); +#else + if (prot != PAGE_KERNEL) + vunmap(src); + else + kunmap(s); +#endif + return 0; } @@ -214,11 +249,17 @@ int ttm_bo_move_memcpy(struct ttm_buffer_object *bo, for (i = 0; i < new_mem->num_pages; ++i) { page = i * dir + add; - if (old_iomap == NULL) - ret = ttm_copy_ttm_io_page(ttm, new_iomap, page); - else if (new_iomap == NULL) - ret = ttm_copy_io_ttm_page(ttm, old_iomap, page); - else + if (old_iomap == NULL) { + pgprot_t prot = ttm_io_prot(old_mem->placement, + PAGE_KERNEL); + ret = ttm_copy_ttm_io_page(ttm, new_iomap, page, + prot); + } else if (new_iomap == NULL) { + pgprot_t prot = ttm_io_prot(new_mem->placement, + PAGE_KERNEL); + ret = ttm_copy_io_ttm_page(ttm, old_iomap, page, + prot); + } else ret = ttm_copy_io_page(new_iomap, old_iomap, page); if (ret) goto out1; -- cgit v1.2.3 From 73ba651fc246fcc3e446da4155e0425b4219d2c4 Mon Sep 17 00:00:00 2001 From: Thomas Hellstrom Date: Fri, 24 Jul 2009 09:57:33 +0200 Subject: x86: Export kmap_atomic_prot() needed for TTM. This functionality is needed to kmap_atomic() highmem pages that may potentially have or are about to set up other mappings with non-standard caching attributes. Signed-off-by: Thomas Hellstrom Signed-off-by: Dave Airlie --- arch/x86/mm/highmem_32.c | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/x86/mm/highmem_32.c b/arch/x86/mm/highmem_32.c index 58f621e81919..2112ed55e7ea 100644 --- a/arch/x86/mm/highmem_32.c +++ b/arch/x86/mm/highmem_32.c @@ -103,6 +103,7 @@ EXPORT_SYMBOL(kmap); EXPORT_SYMBOL(kunmap); EXPORT_SYMBOL(kmap_atomic); EXPORT_SYMBOL(kunmap_atomic); +EXPORT_SYMBOL(kmap_atomic_prot); void __init set_highmem_pages_init(void) { -- cgit v1.2.3 From f121ecfebbea1452a17d57c656def7d1537440f7 Mon Sep 17 00:00:00 2001 From: Thomas Hellstrom Date: Fri, 24 Jul 2009 10:22:36 +0200 Subject: drm/ttm: powerpc: Fix Highmem cache flushing. Temporarily maps highmem pages while flushing to get a valid virtual address to flush. Signed-off-by: Thomas Hellstrom Signed-off-by: Dave Airlie --- drivers/gpu/drm/ttm/ttm_tt.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/ttm/ttm_tt.c b/drivers/gpu/drm/ttm/ttm_tt.c index 81ab81f030a3..9b2248a80cff 100644 --- a/drivers/gpu/drm/ttm/ttm_tt.c +++ b/drivers/gpu/drm/ttm/ttm_tt.c @@ -86,10 +86,16 @@ void ttm_tt_cache_flush(struct page *pages[], unsigned long num_pages) unsigned long i; for (i = 0; i < num_pages; ++i) { - if (pages[i]) { - unsigned long start = (unsigned long)page_address(pages[i]); - flush_dcache_range(start, start + PAGE_SIZE); - } + struct page *page = pages[i]; + void *page_virtual; + + if (unlikely(page == NULL)) + continue; + + page_virtual = kmap_atomic(page, KM_USER0); + flush_dcache_range((unsigned long) page_virtual, + (unsigned long) page_virtual + PAGE_SIZE); + kunmap_atomic(page_virtual, KM_USER0); } #else if (on_each_cpu(ttm_tt_ipi_handler, NULL, 1) != 0) -- cgit v1.2.3 From 3b170c3b2e688665fbc2845ba5bb4304bf38a119 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Fri, 24 Jul 2009 13:47:45 +1000 Subject: drm/radeon/kms: allow interruptible waits for objects. Blocking here isn't something the X server mouse appreciates, avoid the block and let userspace retry the waits. libdrm_radeon userspace library is also expecting EBUSY not ERESTART Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/radeon_fence.c | 2 +- drivers/gpu/drm/radeon/radeon_object.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/radeon/radeon_fence.c b/drivers/gpu/drm/radeon/radeon_fence.c index 96afbf5ae2ad..b4e48dd2e859 100644 --- a/drivers/gpu/drm/radeon/radeon_fence.c +++ b/drivers/gpu/drm/radeon/radeon_fence.c @@ -195,7 +195,7 @@ retry: r = wait_event_interruptible_timeout(rdev->fence_drv.queue, radeon_fence_signaled(fence), timeout); if (unlikely(r == -ERESTARTSYS)) { - return -ERESTART; + return -EBUSY; } } else { r = wait_event_timeout(rdev->fence_drv.queue, diff --git a/drivers/gpu/drm/radeon/radeon_object.c b/drivers/gpu/drm/radeon/radeon_object.c index 81573c3a9b43..dd9ac2fed6d6 100644 --- a/drivers/gpu/drm/radeon/radeon_object.c +++ b/drivers/gpu/drm/radeon/radeon_object.c @@ -309,7 +309,7 @@ int radeon_object_wait(struct radeon_object *robj) } spin_lock(&robj->tobj.lock); if (robj->tobj.sync_obj) { - r = ttm_bo_wait(&robj->tobj, true, false, false); + r = ttm_bo_wait(&robj->tobj, true, true, false); } spin_unlock(&robj->tobj.lock); radeon_object_unreserve(robj); -- cgit v1.2.3 From ecc0b32645bf19a3a240e72be3022ab3b46ad3d0 Mon Sep 17 00:00:00 2001 From: Michel Dänzer Date: Tue, 21 Jul 2009 11:23:57 +0200 Subject: drm/radeon: Add radeon.test parameter for running BO GPU copy tests. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If enabled, during initialization BO GTT->VRAM and VRAM->GTT GPU copies are tested across the whole GTT aperture. This has helped uncover the benchmark copy size bug and verify the maximum aperture size supported by the AGP bridge in my PowerBook. Signed-off-by: Michel Dänzer Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/Makefile | 3 +- drivers/gpu/drm/radeon/radeon.h | 7 ++ drivers/gpu/drm/radeon/radeon_device.c | 3 + drivers/gpu/drm/radeon/radeon_drv.c | 4 + drivers/gpu/drm/radeon/radeon_test.c | 209 +++++++++++++++++++++++++++++++++ 5 files changed, 225 insertions(+), 1 deletion(-) create mode 100644 drivers/gpu/drm/radeon/radeon_test.c diff --git a/drivers/gpu/drm/radeon/Makefile b/drivers/gpu/drm/radeon/Makefile index 5fae1e074b4b..013d38059943 100644 --- a/drivers/gpu/drm/radeon/Makefile +++ b/drivers/gpu/drm/radeon/Makefile @@ -13,7 +13,8 @@ radeon-$(CONFIG_DRM_RADEON_KMS) += radeon_device.o radeon_kms.o \ radeon_encoders.o radeon_display.o radeon_cursor.o radeon_i2c.o \ radeon_clocks.o radeon_fb.o radeon_gem.o radeon_ring.o radeon_irq_kms.o \ radeon_cs.o radeon_bios.o radeon_benchmark.o r100.o r300.o r420.o \ - rs400.o rs600.o rs690.o rv515.o r520.o r600.o rs780.o rv770.o + rs400.o rs600.o rs690.o rv515.o r520.o r600.o rs780.o rv770.o \ + radeon_test.o radeon-$(CONFIG_COMPAT) += radeon_ioc32.o diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h index 045b33b3bf2d..b1d945b8ed6c 100644 --- a/drivers/gpu/drm/radeon/radeon.h +++ b/drivers/gpu/drm/radeon/radeon.h @@ -64,6 +64,7 @@ extern int radeon_agpmode; extern int radeon_vram_limit; extern int radeon_gart_size; extern int radeon_benchmarking; +extern int radeon_testing; extern int radeon_connector_table; /* @@ -534,6 +535,12 @@ struct radeon_pm { void radeon_benchmark(struct radeon_device *rdev); +/* + * Testing + */ +void radeon_test_moves(struct radeon_device *rdev); + + /* * Debugfs */ diff --git a/drivers/gpu/drm/radeon/radeon_device.c b/drivers/gpu/drm/radeon/radeon_device.c index 6d1749e44222..a162ade74b7f 100644 --- a/drivers/gpu/drm/radeon/radeon_device.c +++ b/drivers/gpu/drm/radeon/radeon_device.c @@ -638,6 +638,9 @@ int radeon_device_init(struct radeon_device *rdev, if (!ret) { DRM_INFO("radeon: kernel modesetting successfully initialized.\n"); } + if (radeon_testing) { + radeon_test_moves(rdev); + } if (radeon_benchmarking) { radeon_benchmark(rdev); } diff --git a/drivers/gpu/drm/radeon/radeon_drv.c b/drivers/gpu/drm/radeon/radeon_drv.c index 84ba69f48784..3cfcee17dc56 100644 --- a/drivers/gpu/drm/radeon/radeon_drv.c +++ b/drivers/gpu/drm/radeon/radeon_drv.c @@ -89,6 +89,7 @@ int radeon_agpmode = 0; int radeon_vram_limit = 0; int radeon_gart_size = 512; /* default gart size */ int radeon_benchmarking = 0; +int radeon_testing = 0; int radeon_connector_table = 0; #endif @@ -117,6 +118,9 @@ module_param_named(gartsize, radeon_gart_size, int, 0600); MODULE_PARM_DESC(benchmark, "Run benchmark"); module_param_named(benchmark, radeon_benchmarking, int, 0444); +MODULE_PARM_DESC(test, "Run tests"); +module_param_named(test, radeon_testing, int, 0444); + MODULE_PARM_DESC(connector_table, "Force connector table"); module_param_named(connector_table, radeon_connector_table, int, 0444); #endif diff --git a/drivers/gpu/drm/radeon/radeon_test.c b/drivers/gpu/drm/radeon/radeon_test.c new file mode 100644 index 000000000000..03c33cf4e14c --- /dev/null +++ b/drivers/gpu/drm/radeon/radeon_test.c @@ -0,0 +1,209 @@ +/* + * Copyright 2009 VMware, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: Michel Dänzer + */ +#include +#include +#include "radeon_reg.h" +#include "radeon.h" + + +/* Test BO GTT->VRAM and VRAM->GTT GPU copies across the whole GTT aperture */ +void radeon_test_moves(struct radeon_device *rdev) +{ + struct radeon_object *vram_obj = NULL; + struct radeon_object **gtt_obj = NULL; + struct radeon_fence *fence = NULL; + uint64_t gtt_addr, vram_addr; + unsigned i, n, size; + int r; + + size = 1024 * 1024; + + /* Number of tests = + * (Total GTT - IB pool - writeback page - ring buffer) / test size + */ + n = (rdev->mc.gtt_size - RADEON_IB_POOL_SIZE*64*1024 - 4096 - + rdev->cp.ring_size) / size; + + gtt_obj = kzalloc(n * sizeof(*gtt_obj), GFP_KERNEL); + if (!gtt_obj) { + DRM_ERROR("Failed to allocate %d pointers\n", n); + r = 1; + goto out_cleanup; + } + + r = radeon_object_create(rdev, NULL, size, true, RADEON_GEM_DOMAIN_VRAM, + false, &vram_obj); + if (r) { + DRM_ERROR("Failed to create VRAM object\n"); + goto out_cleanup; + } + + r = radeon_object_pin(vram_obj, RADEON_GEM_DOMAIN_VRAM, &vram_addr); + if (r) { + DRM_ERROR("Failed to pin VRAM object\n"); + goto out_cleanup; + } + + for (i = 0; i < n; i++) { + void *gtt_map, *vram_map; + void **gtt_start, **gtt_end; + void **vram_start, **vram_end; + + r = radeon_object_create(rdev, NULL, size, true, + RADEON_GEM_DOMAIN_GTT, false, gtt_obj + i); + if (r) { + DRM_ERROR("Failed to create GTT object %d\n", i); + goto out_cleanup; + } + + r = radeon_object_pin(gtt_obj[i], RADEON_GEM_DOMAIN_GTT, >t_addr); + if (r) { + DRM_ERROR("Failed to pin GTT object %d\n", i); + goto out_cleanup; + } + + r = radeon_object_kmap(gtt_obj[i], >t_map); + if (r) { + DRM_ERROR("Failed to map GTT object %d\n", i); + goto out_cleanup; + } + + for (gtt_start = gtt_map, gtt_end = gtt_map + size; + gtt_start < gtt_end; + gtt_start++) + *gtt_start = gtt_start; + + radeon_object_kunmap(gtt_obj[i]); + + r = radeon_fence_create(rdev, &fence); + if (r) { + DRM_ERROR("Failed to create GTT->VRAM fence %d\n", i); + goto out_cleanup; + } + + r = radeon_copy(rdev, gtt_addr, vram_addr, size / 4096, fence); + if (r) { + DRM_ERROR("Failed GTT->VRAM copy %d\n", i); + goto out_cleanup; + } + + r = radeon_fence_wait(fence, false); + if (r) { + DRM_ERROR("Failed to wait for GTT->VRAM fence %d\n", i); + goto out_cleanup; + } + + radeon_fence_unref(&fence); + + r = radeon_object_kmap(vram_obj, &vram_map); + if (r) { + DRM_ERROR("Failed to map VRAM object after copy %d\n", i); + goto out_cleanup; + } + + for (gtt_start = gtt_map, gtt_end = gtt_map + size, + vram_start = vram_map, vram_end = vram_map + size; + vram_start < vram_end; + gtt_start++, vram_start++) { + if (*vram_start != gtt_start) { + DRM_ERROR("Incorrect GTT->VRAM copy %d: Got 0x%p, " + "expected 0x%p (GTT map 0x%p-0x%p)\n", + i, *vram_start, gtt_start, gtt_map, + gtt_end); + radeon_object_kunmap(vram_obj); + goto out_cleanup; + } + *vram_start = vram_start; + } + + radeon_object_kunmap(vram_obj); + + r = radeon_fence_create(rdev, &fence); + if (r) { + DRM_ERROR("Failed to create VRAM->GTT fence %d\n", i); + goto out_cleanup; + } + + r = radeon_copy(rdev, vram_addr, gtt_addr, size / 4096, fence); + if (r) { + DRM_ERROR("Failed VRAM->GTT copy %d\n", i); + goto out_cleanup; + } + + r = radeon_fence_wait(fence, false); + if (r) { + DRM_ERROR("Failed to wait for VRAM->GTT fence %d\n", i); + goto out_cleanup; + } + + radeon_fence_unref(&fence); + + r = radeon_object_kmap(gtt_obj[i], >t_map); + if (r) { + DRM_ERROR("Failed to map GTT object after copy %d\n", i); + goto out_cleanup; + } + + for (gtt_start = gtt_map, gtt_end = gtt_map + size, + vram_start = vram_map, vram_end = vram_map + size; + gtt_start < gtt_end; + gtt_start++, vram_start++) { + if (*gtt_start != vram_start) { + DRM_ERROR("Incorrect VRAM->GTT copy %d: Got 0x%p, " + "expected 0x%p (VRAM map 0x%p-0x%p)\n", + i, *gtt_start, vram_start, vram_map, + vram_end); + radeon_object_kunmap(gtt_obj[i]); + goto out_cleanup; + } + } + + radeon_object_kunmap(gtt_obj[i]); + + DRM_INFO("Tested GTT->VRAM and VRAM->GTT copy for GTT offset 0x%llx\n", + gtt_addr - rdev->mc.gtt_location); + } + +out_cleanup: + if (vram_obj) { + radeon_object_unpin(vram_obj); + radeon_object_unref(&vram_obj); + } + if (gtt_obj) { + for (i = 0; i < n; i++) { + if (gtt_obj[i]) { + radeon_object_unpin(gtt_obj[i]); + radeon_object_unref(>t_obj[i]); + } + } + kfree(gtt_obj); + } + if (fence) { + radeon_fence_unref(&fence); + } + if (r) { + printk(KERN_WARNING "Error while testing BO move.\n"); + } +} + -- cgit v1.2.3 From ea3c13bd8c2ed1d3670bd72e60f562a427355fdf Mon Sep 17 00:00:00 2001 From: Michel Dänzer Date: Mon, 20 Jul 2009 01:44:03 +0200 Subject: drm/radeon: Fix size used for benchmarking BO copies. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The incorrect size caused benchmark results to be inflated by a factor of 4. Signed-off-by: Michel Dänzer Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/radeon_benchmark.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/radeon/radeon_benchmark.c b/drivers/gpu/drm/radeon/radeon_benchmark.c index c44403a2ca76..2e938f7496fb 100644 --- a/drivers/gpu/drm/radeon/radeon_benchmark.c +++ b/drivers/gpu/drm/radeon/radeon_benchmark.c @@ -63,7 +63,7 @@ void radeon_benchmark_move(struct radeon_device *rdev, unsigned bsize, if (r) { goto out_cleanup; } - r = radeon_copy_dma(rdev, saddr, daddr, size >> 14, fence); + r = radeon_copy_dma(rdev, saddr, daddr, size / 4096, fence); if (r) { goto out_cleanup; } @@ -88,7 +88,7 @@ void radeon_benchmark_move(struct radeon_device *rdev, unsigned bsize, if (r) { goto out_cleanup; } - r = radeon_copy_blit(rdev, saddr, daddr, size >> 14, fence); + r = radeon_copy_blit(rdev, saddr, daddr, size / 4096, fence); if (r) { goto out_cleanup; } -- cgit v1.2.3 From b42db2b12df7b4f7b2ace581a7726cb5bcb2d658 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Wed, 29 Jul 2009 16:56:52 +1000 Subject: drm/ttm: fix highuser vs dma32 confusion. DMA32 and highmem are sort of exclusive. Noticed by AndrewR on #radeon. Signed-off-by: Dave Airlie --- drivers/gpu/drm/ttm/ttm_tt.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/ttm/ttm_tt.c b/drivers/gpu/drm/ttm/ttm_tt.c index 9b2248a80cff..b8b6c4a5f983 100644 --- a/drivers/gpu/drm/ttm/ttm_tt.c +++ b/drivers/gpu/drm/ttm/ttm_tt.c @@ -137,13 +137,15 @@ static void ttm_tt_free_page_directory(struct ttm_tt *ttm) static struct page *ttm_tt_alloc_page(unsigned page_flags) { - gfp_t gfp_flags = GFP_HIGHUSER; + gfp_t gfp_flags = GFP_USER; if (page_flags & TTM_PAGE_FLAG_ZERO_ALLOC) gfp_flags |= __GFP_ZERO; if (page_flags & TTM_PAGE_FLAG_DMA32) gfp_flags |= __GFP_DMA32; + else + gfp_flags |= __GFP_HIGHMEM; return alloc_page(gfp_flags); } -- cgit v1.2.3 From ed8f0d9e708a1a7c9222e7d0a35d97521e904223 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Wed, 29 Jul 2009 17:07:38 +1000 Subject: drm/radeon: set fb aperture sizes for framebuffer handoff. This will allow efi/vesa to handoff to radeon. Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/radeon_fb.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/gpu/drm/radeon/radeon_fb.c b/drivers/gpu/drm/radeon/radeon_fb.c index 36d2f5588f20..3206c0ad7b6c 100644 --- a/drivers/gpu/drm/radeon/radeon_fb.c +++ b/drivers/gpu/drm/radeon/radeon_fb.c @@ -602,6 +602,11 @@ int radeonfb_create(struct radeon_device *rdev, info->var.width = -1; info->var.xres = fb_width; info->var.yres = fb_height; + + /* setup aperture base/size for vesafb takeover */ + info->aperture_base = rdev->ddev->mode_config.fb_base; + info->aperture_size = rdev->mc.real_vram_size; + info->fix.mmio_start = 0; info->fix.mmio_len = 0; info->pixmap.size = 64*1024; -- cgit v1.2.3 From ec79be26875f6c1468784876cb99192b7f41c7a5 Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Wed, 29 Jul 2009 21:07:47 +0200 Subject: PM / ACPI: HP G7000 Notebook needs a SCI_EN resume quirk This fixes regression (battery "vanishing" on resume) introduced by commit d0c71fe7ebc180f1b7bc7da1d39a07fc19eec768 ("ACPI Suspend: Enable ACPI during resume if SCI_EN is not set") and also the issue with the "screaming" IRQ 9. Fixes http://bugzilla.kernel.org/show_bug.cgi?id=13745 Reported-and-tested-by: Alan Jenkins Cc: stable@kernel.org Signed-off-by: Bartlomiej Zolnierkiewicz Acked-by: Len Brown Signed-off-by: Rafael J. Wysocki --- drivers/acpi/sleep.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/acpi/sleep.c b/drivers/acpi/sleep.c index 01574a066534..42159a28f433 100644 --- a/drivers/acpi/sleep.c +++ b/drivers/acpi/sleep.c @@ -397,6 +397,14 @@ static struct dmi_system_id __initdata acpisleep_dmi_table[] = { }, }, { + .callback = init_set_sci_en_on_resume, + .ident = "Hewlett-Packard HP G7000 Notebook PC", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), + DMI_MATCH(DMI_PRODUCT_NAME, "HP G7000 Notebook PC"), + }, + }, + { .callback = init_old_suspend_ordering, .ident = "Panasonic CF51-2L", .matches = { -- cgit v1.2.3 From dddac6a7b445de95515f64fdf82fe5dc36c02f26 Mon Sep 17 00:00:00 2001 From: Alan Jenkins Date: Wed, 29 Jul 2009 21:07:55 +0200 Subject: PM / Hibernate: Replace bdget call with simple atomic_inc of i_count Create bdgrab(). This function copies an existing reference to a block_device. It is safe to call from any context. Hibernation code wishes to copy a reference to the active swap device. Right now it calls bdget() under a spinlock, but this is wrong because bdget() can sleep. It doesn't need a full bdget() because we already hold a reference to active swap devices (and the spinlock protects against swapoff). Fixes http://bugzilla.kernel.org/show_bug.cgi?id=13827 Signed-off-by: Alan Jenkins Signed-off-by: Rafael J. Wysocki --- fs/block_dev.c | 10 ++++++++++ include/linux/fs.h | 1 + mm/swapfile.c | 4 ++-- 3 files changed, 13 insertions(+), 2 deletions(-) diff --git a/fs/block_dev.c b/fs/block_dev.c index 3a6d4fb2a329..94dfda24c06e 100644 --- a/fs/block_dev.c +++ b/fs/block_dev.c @@ -564,6 +564,16 @@ struct block_device *bdget(dev_t dev) EXPORT_SYMBOL(bdget); +/** + * bdgrab -- Grab a reference to an already referenced block device + * @bdev: Block device to grab a reference to. + */ +struct block_device *bdgrab(struct block_device *bdev) +{ + atomic_inc(&bdev->bd_inode->i_count); + return bdev; +} + long nr_blockdev_pages(void) { struct block_device *bdev; diff --git a/include/linux/fs.h b/include/linux/fs.h index 0872372184fe..a36ffa5a77a4 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -1946,6 +1946,7 @@ extern void putname(const char *name); extern int register_blkdev(unsigned int, const char *); extern void unregister_blkdev(unsigned int, const char *); extern struct block_device *bdget(dev_t); +extern struct block_device *bdgrab(struct block_device *bdev); extern void bd_set_size(struct block_device *, loff_t size); extern void bd_forget(struct inode *inode); extern void bdput(struct block_device *); diff --git a/mm/swapfile.c b/mm/swapfile.c index d1ade1a48ee7..8ffdc0d23c53 100644 --- a/mm/swapfile.c +++ b/mm/swapfile.c @@ -753,7 +753,7 @@ int swap_type_of(dev_t device, sector_t offset, struct block_device **bdev_p) if (!bdev) { if (bdev_p) - *bdev_p = bdget(sis->bdev->bd_dev); + *bdev_p = bdgrab(sis->bdev); spin_unlock(&swap_lock); return i; @@ -765,7 +765,7 @@ int swap_type_of(dev_t device, sector_t offset, struct block_device **bdev_p) struct swap_extent, list); if (se->start_block == offset) { if (bdev_p) - *bdev_p = bdget(sis->bdev->bd_dev); + *bdev_p = bdgrab(sis->bdev); spin_unlock(&swap_lock); bdput(bdev); -- cgit v1.2.3 From e043e42bdb66885b3ac10d27a01ccb9972e2b0a3 Mon Sep 17 00:00:00 2001 From: OGAWA Hirofumi Date: Wed, 29 Jul 2009 12:15:56 -0700 Subject: pty: avoid forcing 'low_latency' tty flag We really don't want to mark the pty as a low-latency device, because as Alan points out, the ->write method can be called from an IRQ (ppp?), and that means we can't use ->low_latency=1 as we take mutexes in the low_latency case. So rather than using low_latency to force the written data to be pushed to the ldisc handling at 'write()' time, just make the reader side (or the poll function) do the flush when it checks whether there is data to be had. This also fixes the problem with lost data in an emacs compile buffer (bugzilla 13815), and we can thus revert the low_latency pty hack (commit 3a54297478e6578f96fd54bf4daa1751130aca86: "pty: quickfix for the pty ENXIO timing problems"). Signed-off-by: OGAWA Hirofumi Tested-by: Aneesh Kumar K.V [ Modified to do the tty_flush_to_ldisc() inside input_available_p() so that it triggers for both read and poll() - Linus] Signed-off-by: Linus Torvalds --- drivers/char/n_tty.c | 1 + drivers/char/pty.c | 2 -- drivers/char/tty_buffer.c | 13 +++++++++++++ include/linux/tty.h | 1 + 4 files changed, 15 insertions(+), 2 deletions(-) diff --git a/drivers/char/n_tty.c b/drivers/char/n_tty.c index ff47907ff1bf..973be2f44195 100644 --- a/drivers/char/n_tty.c +++ b/drivers/char/n_tty.c @@ -1583,6 +1583,7 @@ static int n_tty_open(struct tty_struct *tty) static inline int input_available_p(struct tty_struct *tty, int amt) { + tty_flush_to_ldisc(tty); if (tty->icanon) { if (tty->canon_data) return 1; diff --git a/drivers/char/pty.c b/drivers/char/pty.c index 3850a68f265a..6e6942c45f5b 100644 --- a/drivers/char/pty.c +++ b/drivers/char/pty.c @@ -52,7 +52,6 @@ static void pty_close(struct tty_struct *tty, struct file *filp) return; tty->link->packet = 0; set_bit(TTY_OTHER_CLOSED, &tty->link->flags); - tty_flip_buffer_push(tty->link); wake_up_interruptible(&tty->link->read_wait); wake_up_interruptible(&tty->link->write_wait); if (tty->driver->subtype == PTY_TYPE_MASTER) { @@ -208,7 +207,6 @@ static int pty_open(struct tty_struct *tty, struct file *filp) clear_bit(TTY_OTHER_CLOSED, &tty->link->flags); set_bit(TTY_THROTTLED, &tty->flags); retval = 0; - tty->low_latency = 1; out: return retval; } diff --git a/drivers/char/tty_buffer.c b/drivers/char/tty_buffer.c index 810ee25d66a4..3108991c5c8b 100644 --- a/drivers/char/tty_buffer.c +++ b/drivers/char/tty_buffer.c @@ -461,6 +461,19 @@ static void flush_to_ldisc(struct work_struct *work) tty_ldisc_deref(disc); } +/** + * tty_flush_to_ldisc + * @tty: tty to push + * + * Push the terminal flip buffers to the line discipline. + * + * Must not be called from IRQ context. + */ +void tty_flush_to_ldisc(struct tty_struct *tty) +{ + flush_to_ldisc(&tty->buf.work.work); +} + /** * tty_flip_buffer_push - terminal * @tty: tty to push diff --git a/include/linux/tty.h b/include/linux/tty.h index 1488d8c81aac..e8c6c9136c97 100644 --- a/include/linux/tty.h +++ b/include/linux/tty.h @@ -394,6 +394,7 @@ extern void __do_SAK(struct tty_struct *tty); extern void disassociate_ctty(int priv); extern void no_tty(void); extern void tty_flip_buffer_push(struct tty_struct *tty); +extern void tty_flush_to_ldisc(struct tty_struct *tty); extern void tty_buffer_free_all(struct tty_struct *tty); extern void tty_buffer_flush(struct tty_struct *tty); extern void tty_buffer_init(struct tty_struct *tty); -- cgit v1.2.3 From f5886c7f96f2542382d3a983c5f13e03d7fc5259 Mon Sep 17 00:00:00 2001 From: Catalin Marinas Date: Wed, 29 Jul 2009 16:26:57 +0100 Subject: kmemleak: Protect the seq start/next/stop sequence by rcu_read_lock() Objects passed to kmemleak_seq_next() have an incremented reference count (hence not freed) but they may point via object_list.next to other freed objects. To avoid this, the whole start/next/stop sequence must be protected by rcu_read_lock(). Signed-off-by: Catalin Marinas Signed-off-by: Linus Torvalds --- mm/kmemleak.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/mm/kmemleak.c b/mm/kmemleak.c index 5aabd41ffb8f..487267310a84 100644 --- a/mm/kmemleak.c +++ b/mm/kmemleak.c @@ -1217,7 +1217,6 @@ static void *kmemleak_seq_start(struct seq_file *seq, loff_t *pos) } object = NULL; out: - rcu_read_unlock(); return object; } @@ -1233,13 +1232,11 @@ static void *kmemleak_seq_next(struct seq_file *seq, void *v, loff_t *pos) ++(*pos); - rcu_read_lock(); list_for_each_continue_rcu(n, &object_list) { next_obj = list_entry(n, struct kmemleak_object, object_list); if (get_object(next_obj)) break; } - rcu_read_unlock(); put_object(prev_obj); return next_obj; @@ -1255,6 +1252,7 @@ static void kmemleak_seq_stop(struct seq_file *seq, void *v) * kmemleak_seq_start may return ERR_PTR if the scan_mutex * waiting was interrupted, so only release it if !IS_ERR. */ + rcu_read_unlock(); mutex_unlock(&scan_mutex); if (v) put_object(v); -- cgit v1.2.3 From 0e014e92ba93d905bcb39881dce2d38807b90c34 Mon Sep 17 00:00:00 2001 From: Peter Korsgaard Date: Fri, 17 Jul 2009 22:33:37 +0200 Subject: i2c-s3c2410: s3c24xx_i2c_init: don't clobber IICLC value s3c24xx_i2c_init() was overwriting the IICLC value set just above in s3c24xx_i2c_clockrate() with zero, effectively disabling the platform line control setting. Signed-off-by: Peter Korsgaard Signed-off-by: Ben Dooks --- drivers/i2c/busses/i2c-s3c2410.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/drivers/i2c/busses/i2c-s3c2410.c b/drivers/i2c/busses/i2c-s3c2410.c index 8f42a4536cdf..20bb0ceb027b 100644 --- a/drivers/i2c/busses/i2c-s3c2410.c +++ b/drivers/i2c/busses/i2c-s3c2410.c @@ -763,11 +763,6 @@ static int s3c24xx_i2c_init(struct s3c24xx_i2c *i2c) dev_info(i2c->dev, "bus frequency set to %d KHz\n", freq); dev_dbg(i2c->dev, "S3C2410_IICCON=0x%02lx\n", iicon); - /* check for s3c2440 i2c controller */ - - if (s3c24xx_i2c_is2440(i2c)) - writel(0x0, i2c->regs + S3C2440_IICLC); - return 0; } -- cgit v1.2.3 From 783fd6fa4c144e3f6913e6fed89de10a6dd715a5 Mon Sep 17 00:00:00 2001 From: Roel Kluin Date: Fri, 17 Jul 2009 15:24:00 +0200 Subject: i2c: strncpy does not null terminate string strlcpy() will always null terminate the string. Signed-off-by: Roel Kluin Signed-off-by: Ben Dooks --- drivers/i2c/busses/i2c-omap.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c index fdd83277c8a8..f2b82ee39adf 100644 --- a/drivers/i2c/busses/i2c-omap.c +++ b/drivers/i2c/busses/i2c-omap.c @@ -879,7 +879,7 @@ omap_i2c_probe(struct platform_device *pdev) i2c_set_adapdata(adap, dev); adap->owner = THIS_MODULE; adap->class = I2C_CLASS_HWMON; - strncpy(adap->name, "OMAP I2C adapter", sizeof(adap->name)); + strlcpy(adap->name, "OMAP I2C adapter", sizeof(adap->name)); adap->algo = &omap_i2c_algo; adap->dev.parent = &pdev->dev; -- cgit v1.2.3 From ccb3bc16b4891a82649d4bccbeefe60b1d9a62e2 Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Wed, 22 Jul 2009 23:58:39 +0900 Subject: i2c-sh_mobile: change module_init() to subsys_initcall() Convert the i2c-sh_mobile i2c bus driver to use subsys_initcall() instead of module_init(). This change makes the driver register a bit earlier which together with earlier platform data moves the time for probe(). The earlier probe() makes it possible to use i2c_get_adapter() and i2c_transfer() from device_initcall(). The same strategy is used by other i2c bus drivers such as i2c-pxa.c and i2c-s3c2410.c. Signed-off-by: Magnus Damm [ben-linux@fluff.org: minor subject updaye] Signed-off-by: Ben Dooks --- drivers/i2c/busses/i2c-sh_mobile.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/i2c/busses/i2c-sh_mobile.c b/drivers/i2c/busses/i2c-sh_mobile.c index 4f3d99cd1692..820487d0d5c7 100644 --- a/drivers/i2c/busses/i2c-sh_mobile.c +++ b/drivers/i2c/busses/i2c-sh_mobile.c @@ -637,7 +637,7 @@ static void __exit sh_mobile_i2c_adap_exit(void) platform_driver_unregister(&sh_mobile_i2c_driver); } -module_init(sh_mobile_i2c_adap_init); +subsys_initcall(sh_mobile_i2c_adap_init); module_exit(sh_mobile_i2c_adap_exit); MODULE_DESCRIPTION("SuperH Mobile I2C Bus Controller driver"); -- cgit v1.2.3 From bfb6b6588af5ff762222cee79152d2be738ccc06 Mon Sep 17 00:00:00 2001 From: "Sonasath, Moiz" Date: Tue, 21 Jul 2009 10:14:06 -0500 Subject: i2c-omap: Bug in reading the RXSTAT/TXSTAT values from the I2C_BUFFSTAT register Fix bug in reading the I2C_BUFFSTAT register for getting byte count on RX/TX interrupt. On Interrupt: I2C_STAT[RDR], read 'RXSTAT' from I2C_BUFFSTAT[8-13] On Interrupt: I2C_STAT[XDR] read 'TXSTAT' from I2C_BUFFSTAT[0-5] Signed-off-by: Jagadeesh Pakaravoor Signed-off-by: Moiz Sonasath Signed-off-by: Vikram pandita [ben-linux@fluff.org: fixed mail format and added i2c-omap to subject] Signed-off-by: Ben Dooks --- drivers/i2c/busses/i2c-omap.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c index f2b82ee39adf..a69665788513 100644 --- a/drivers/i2c/busses/i2c-omap.c +++ b/drivers/i2c/busses/i2c-omap.c @@ -692,9 +692,10 @@ omap_i2c_isr(int this_irq, void *dev_id) if (dev->fifo_size) { if (stat & OMAP_I2C_STAT_RRDY) num_bytes = dev->fifo_size; - else - num_bytes = omap_i2c_read_reg(dev, - OMAP_I2C_BUFSTAT_REG); + else /* read RXSTAT on RDR interrupt */ + num_bytes = (omap_i2c_read_reg(dev, + OMAP_I2C_BUFSTAT_REG) + >> 8) & 0x3F; } while (num_bytes) { num_bytes--; @@ -731,9 +732,10 @@ omap_i2c_isr(int this_irq, void *dev_id) if (dev->fifo_size) { if (stat & OMAP_I2C_STAT_XRDY) num_bytes = dev->fifo_size; - else + else /* read TXSTAT on XDR interrupt */ num_bytes = omap_i2c_read_reg(dev, - OMAP_I2C_BUFSTAT_REG); + OMAP_I2C_BUFSTAT_REG) + & 0x3F; } while (num_bytes) { num_bytes--; -- cgit v1.2.3 From 04c688dd7a65935568b44629bfaa122eddf76e94 Mon Sep 17 00:00:00 2001 From: "Sonasath, Moiz" Date: Tue, 21 Jul 2009 10:14:40 -0500 Subject: i2c-omap: In case of a NACK|ARDY|AL return from the ISR In case of a NACK or ARDY or AL interrupt, complete the request. There is no need to service the RRDY/RDR or XRDY/XDR interrupts. Refer TRM SWPU114: Figure 18-31.I2C Master Transmitter Mode, Interrupt Method, in F/S and HS Modes http://focus.ti.com/pdfs/wtbu/SWPU114T_PrelimFinalEPDF_06_25_2009.pdf Signed-off-by: Moiz Sonasath Signed-off-by: Vikram pandita [ben-linux@fluff.org: fixed mail format and added i2c-omap to subject] Signed-off-by: Ben Dooks --- drivers/i2c/busses/i2c-omap.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c index a69665788513..5c508ccf4384 100644 --- a/drivers/i2c/busses/i2c-omap.c +++ b/drivers/i2c/busses/i2c-omap.c @@ -685,8 +685,10 @@ omap_i2c_isr(int this_irq, void *dev_id) err |= OMAP_I2C_STAT_AL; } if (stat & (OMAP_I2C_STAT_ARDY | OMAP_I2C_STAT_NACK | - OMAP_I2C_STAT_AL)) + OMAP_I2C_STAT_AL)) { omap_i2c_complete_cmd(dev, err); + return IRQ_HANDLED; + } if (stat & (OMAP_I2C_STAT_RRDY | OMAP_I2C_STAT_RDR)) { u8 num_bytes = 1; if (dev->fifo_size) { -- cgit v1.2.3 From cd086d3aa6f7f7bf4d4e1f9fa09af0f0b6bb99ec Mon Sep 17 00:00:00 2001 From: "Sonasath, Moiz" Date: Tue, 21 Jul 2009 10:15:12 -0500 Subject: i2c-omap: OMAP3430 Silicon Errata 1.153 When an XRDY/XDR is hit, wait for XUDF before writing data to DATA_REG. Otherwise some data bytes can be lost while transferring them from the memory to the I2C interface. Do a Busy-wait for XUDF, before writing data to DATA_REG. While waiting if there is NACK | AL, set the appropriate error flags, ack the pending interrupts and return from the ISR. Signed-off-by: Moiz Sonasath Signed-off-by: Vikram pandita [ben-linux@fluff.org: fixed mail format and added i2c-omap to subject] Signed-off-by: Ben Dooks --- drivers/i2c/busses/i2c-omap.c | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c index 5c508ccf4384..d258b02aef44 100644 --- a/drivers/i2c/busses/i2c-omap.c +++ b/drivers/i2c/busses/i2c-omap.c @@ -672,9 +672,10 @@ omap_i2c_isr(int this_irq, void *dev_id) break; } + err = 0; +complete: omap_i2c_write_reg(dev, OMAP_I2C_STAT_REG, stat); - err = 0; if (stat & OMAP_I2C_STAT_NACK) { err |= OMAP_I2C_STAT_NACK; omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, @@ -764,6 +765,27 @@ omap_i2c_isr(int this_irq, void *dev_id) "data to send\n"); break; } + + /* + * OMAP3430 Errata 1.153: When an XRDY/XDR + * is hit, wait for XUDF before writing data + * to DATA_REG. Otherwise some data bytes can + * be lost while transferring them from the + * memory to the I2C interface. + */ + + if (cpu_is_omap34xx()) { + 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)); + err |= OMAP_I2C_STAT_XUDF; + goto complete; + } + cpu_relax(); + stat = omap_i2c_read_reg(dev, OMAP_I2C_STAT_REG); + } + } + omap_i2c_write_reg(dev, OMAP_I2C_DATA_REG, w); } omap_i2c_ack_stat(dev, -- cgit v1.2.3 From 51fbb4bab6c8710eb897ab3fb06efbbc921f3a8d Mon Sep 17 00:00:00 2001 From: Matthew Wilcox Date: Wed, 29 Jul 2009 15:02:03 -0700 Subject: markup_oops: fix it with 32-bit userspace on a 64-bit kernel A 32-bit perl can't handle 64-bit addresses without using the BigInt package. Signed-off-by: Matthew Wilcox Acked-by: Arjan van de Ven Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- scripts/markup_oops.pl | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/scripts/markup_oops.pl b/scripts/markup_oops.pl index 528492bcba5b..89774011965d 100644 --- a/scripts/markup_oops.pl +++ b/scripts/markup_oops.pl @@ -1,6 +1,7 @@ #!/usr/bin/perl use File::Basename; +use Math::BigInt; # Copyright 2008, Intel Corporation # @@ -172,8 +173,8 @@ while () { parse_x86_regs($line); } -my $decodestart = hex($target) - hex($func_offset); -my $decodestop = hex($target) + 8192; +my $decodestart = Math::BigInt->from_hex("0x$target") - Math::BigInt->from_hex("0x$func_offset"); +my $decodestop = Math::BigInt->from_hex("0x$target") + 8192; if ($target eq "0") { print "No oops found!\n"; print "Usage: \n"; -- cgit v1.2.3 From e084b2d95e48b31aa45f9c49ffc6cdae8bdb21d4 Mon Sep 17 00:00:00 2001 From: Mel Gorman Date: Wed, 29 Jul 2009 15:02:04 -0700 Subject: page-allocator: preserve PFN ordering when __GFP_COLD is set Fix a post-2.6.24 performace regression caused by 3dfa5721f12c3d5a441448086bee156887daa961 ("page-allocator: preserve PFN ordering when __GFP_COLD is set"). Narayanan reports "The regression is around 15%. There is no disk controller as our setup is based on Samsung OneNAND used as a memory mapped device on a OMAP2430 based board." The page allocator tries to preserve contiguous PFN ordering when returning pages such that repeated callers to the allocator have a strong chance of getting physically contiguous pages, particularly when external fragmentation is low. However, of the bulk of the allocations have __GFP_COLD set as they are due to aio_read() for example, then the PFNs are in reverse PFN order. This can cause performance degration when used with IO controllers that could have merged the requests. This patch attempts to preserve the contiguous ordering of PFNs for users of __GFP_COLD. Signed-off-by: Mel Gorman Reported-by: Narayananu Gopalakrishnan Tested-by: Narayanan Gopalakrishnan Cc: KAMEZAWA Hiroyuki Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- mm/page_alloc.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/mm/page_alloc.c b/mm/page_alloc.c index caa92689aac9..ae28c22a7fdb 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -882,7 +882,7 @@ retry_reserve: */ static int rmqueue_bulk(struct zone *zone, unsigned int order, unsigned long count, struct list_head *list, - int migratetype) + int migratetype, int cold) { int i; @@ -901,7 +901,10 @@ static int rmqueue_bulk(struct zone *zone, unsigned int order, * merge IO requests if the physical pages are ordered * properly. */ - list_add(&page->lru, list); + if (likely(cold == 0)) + list_add(&page->lru, list); + else + list_add_tail(&page->lru, list); set_page_private(page, migratetype); list = &page->lru; } @@ -1119,7 +1122,8 @@ again: local_irq_save(flags); if (!pcp->count) { pcp->count = rmqueue_bulk(zone, 0, - pcp->batch, &pcp->list, migratetype); + pcp->batch, &pcp->list, + migratetype, cold); if (unlikely(!pcp->count)) goto failed; } @@ -1138,7 +1142,8 @@ again: /* Allocate more to the pcp list if necessary */ if (unlikely(&page->lru == &pcp->list)) { pcp->count += rmqueue_bulk(zone, 0, - pcp->batch, &pcp->list, migratetype); + pcp->batch, &pcp->list, + migratetype, cold); page = list_entry(pcp->list.next, struct page, lru); } -- cgit v1.2.3 From 6583bb64fc370842b32a87c67750c26f6d559af0 Mon Sep 17 00:00:00 2001 From: David Rientjes Date: Wed, 29 Jul 2009 15:02:06 -0700 Subject: mm: avoid endless looping for oom killed tasks If a task is oom killed and still cannot find memory when trying with no watermarks, it's better to fail the allocation attempt than to loop endlessly. Direct reclaim has already failed and the oom killer will be a no-op since current has yet to die, so there is no other alternative for allocations that are not __GFP_NOFAIL. Acked-by: Mel Gorman Signed-off-by: David Rientjes Acked-by: Hugh Dickins Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- mm/page_alloc.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/mm/page_alloc.c b/mm/page_alloc.c index ae28c22a7fdb..2dbb2fc68837 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -1794,6 +1794,10 @@ rebalance: if (p->flags & PF_MEMALLOC) goto nopage; + /* Avoid allocations with no watermarks from looping endlessly */ + if (test_thread_flag(TIF_MEMDIE) && !(gfp_mask & __GFP_NOFAIL)) + goto nopage; + /* Try direct reclaim and then allocating */ page = __alloc_pages_direct_reclaim(gfp_mask, order, zonelist, high_zoneidx, -- cgit v1.2.3 From 933b787b57ca8bdc0fc8fb2cbf67b5e6d21beb84 Mon Sep 17 00:00:00 2001 From: Rik van Riel Date: Wed, 29 Jul 2009 15:02:07 -0700 Subject: mm: copy over oom_adj value at fork time Fix a post-2.6.31 regression which was introduced by 2ff05b2b4eac2e63d345fc731ea151a060247f53 ("oom: move oom_adj value from task_struct to mm_struct"). After moving the oom_adj value from the task struct to the mm_struct, the oom_adj value was no longer properly inherited by child processes. Copying over the oom_adj value at fork time fixes that bug. [kosaki.motohiro@jp.fujitsu.com: test for current->mm before dereferencing it] Signed-off-by: Rik van Riel Reported-by: Paul Menage Cc: KOSAKI Motohiro Acked-by: David Rientjes Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- kernel/fork.c | 1 + 1 file changed, 1 insertion(+) diff --git a/kernel/fork.c b/kernel/fork.c index 9b42695f0d14..29b532e718f7 100644 --- a/kernel/fork.c +++ b/kernel/fork.c @@ -426,6 +426,7 @@ static struct mm_struct * mm_init(struct mm_struct * mm, struct task_struct *p) init_rwsem(&mm->mmap_sem); INIT_LIST_HEAD(&mm->mmlist); mm->flags = (current->mm) ? current->mm->flags : default_dump_filter; + mm->oom_adj = (current->mm) ? current->mm->oom_adj : 0; mm->core_state = NULL; mm->nr_ptes = 0; set_mm_counter(mm, file_rss, 0); -- cgit v1.2.3 From 11c7da4b0ca76a57f51c996c883c480e203cf5a9 Mon Sep 17 00:00:00 2001 From: Hidetoshi Seto Date: Wed, 29 Jul 2009 15:02:08 -0700 Subject: kexec: fix omitting offset in extended crashkernel syntax Setting "crashkernel=512M-2G:64M,2G-:128M" does not work but it turns to work if it has a trailing-whitespace, like "crashkernel=512M-2G:64M,2G-:128M ". It was because of a bug in the parser, running over the cmdline. This patch adds a check of the termination. Reported-by: Jin Dongming Signed-off-by: Hidetoshi Seto Tested-by: Jin Dongming Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- kernel/kexec.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel/kexec.c b/kernel/kexec.c index ae1c35201cc8..f336e2107f98 100644 --- a/kernel/kexec.c +++ b/kernel/kexec.c @@ -1228,7 +1228,7 @@ static int __init parse_crashkernel_mem(char *cmdline, } while (*cur++ == ','); if (*crash_size > 0) { - while (*cur != ' ' && *cur != '@') + while (*cur && *cur != ' ' && *cur != '@') cur++; if (*cur == '@') { cur++; -- cgit v1.2.3 From 3d768213a6c34a27fac1804143da8cf18b8b175f Mon Sep 17 00:00:00 2001 From: Lu Zhihe Date: Wed, 29 Jul 2009 15:02:09 -0700 Subject: edac: x38 fix mchbar high register addr Intel X38 MCHBAR is a 64bits register, base from 0x48, so its higher base is 0x4C. Signed-off-by: Lu Zhihe Signed-off-by: Doug Thompson Cc: [2.6.30.x] Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/edac/x38_edac.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/edac/x38_edac.c b/drivers/edac/x38_edac.c index 2406c2ce2844..d4ec60593176 100644 --- a/drivers/edac/x38_edac.c +++ b/drivers/edac/x38_edac.c @@ -30,7 +30,7 @@ /* Intel X38 register addresses - device 0 function 0 - DRAM Controller */ #define X38_MCHBAR_LOW 0x48 /* MCH Memory Mapped Register BAR */ -#define X38_MCHBAR_HIGH 0x4b +#define X38_MCHBAR_HIGH 0x4c #define X38_MCHBAR_MASK 0xfffffc000ULL /* bits 35:14 */ #define X38_MMR_WINDOW_SIZE 16384 -- cgit v1.2.3 From c42b110caeb128819104d057acdaa1ae564b7c8d Mon Sep 17 00:00:00 2001 From: Pawel Osciak Date: Wed, 29 Jul 2009 15:02:10 -0700 Subject: s3c-fb: fix off-by-one bug in loop indexes Fixed off-by-one bug in loop indexes - some elements beyond windows' array were accessed, which might result in memory access violations when removing/suspending the device. Signed-off-by: Pawel Osciak Reviewed-by: Kyungmin Park Signed-off-by: Marek Szyprowski Cc: Krzysztof Helt Cc: Ben Dooks Cc: Russell King Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/video/s3c-fb.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/video/s3c-fb.c b/drivers/video/s3c-fb.c index bb63c07e13de..5a72083dc67c 100644 --- a/drivers/video/s3c-fb.c +++ b/drivers/video/s3c-fb.c @@ -964,7 +964,7 @@ static int __devexit s3c_fb_remove(struct platform_device *pdev) struct s3c_fb *sfb = platform_get_drvdata(pdev); int win; - for (win = 0; win <= S3C_FB_MAX_WIN; win++) + for (win = 0; win < S3C_FB_MAX_WIN; win++) if (sfb->windows[win]) s3c_fb_release_win(sfb, sfb->windows[win]); @@ -988,7 +988,7 @@ static int s3c_fb_suspend(struct platform_device *pdev, pm_message_t state) struct s3c_fb_win *win; int win_no; - for (win_no = S3C_FB_MAX_WIN; win_no >= 0; win_no--) { + for (win_no = S3C_FB_MAX_WIN - 1; win_no >= 0; win_no--) { win = sfb->windows[win_no]; if (!win) continue; -- cgit v1.2.3 From ddb22195cb3dc5175ba3aac5e957d0e34cd2ee73 Mon Sep 17 00:00:00 2001 From: Jouni Hogander Date: Wed, 29 Jul 2009 15:02:11 -0700 Subject: spi: omap2_mcspi supports wake events Currently mcspi wake-ups are not enabled. This might cause cases where OMAP is not waking up on mcspi events. Signed-off-by: Jouni Hogander Signed-off-by: Tony Lindgren Signed-off-by: David Brownell Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/spi/omap2_mcspi.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/drivers/spi/omap2_mcspi.c b/drivers/spi/omap2_mcspi.c index eee4b6e0af2c..2b64091b0f1f 100644 --- a/drivers/spi/omap2_mcspi.c +++ b/drivers/spi/omap2_mcspi.c @@ -59,6 +59,8 @@ /* per-register bitmasks: */ +#define OMAP2_MCSPI_SYSCONFIG_SMARTIDLE (2 << 3) +#define OMAP2_MCSPI_SYSCONFIG_ENAWAKEUP (1 << 2) #define OMAP2_MCSPI_SYSCONFIG_AUTOIDLE (1 << 0) #define OMAP2_MCSPI_SYSCONFIG_SOFTRESET (1 << 1) @@ -90,6 +92,7 @@ #define OMAP2_MCSPI_CHCTRL_EN (1 << 0) +#define OMAP2_MCSPI_WAKEUPENABLE_WKEN (1 << 0) /* We have 2 DMA channels per CS, one for RX and one for TX */ struct omap2_mcspi_dma { @@ -873,8 +876,12 @@ static int __init omap2_mcspi_reset(struct omap2_mcspi *mcspi) } while (!(tmp & OMAP2_MCSPI_SYSSTATUS_RESETDONE)); mcspi_write_reg(master, OMAP2_MCSPI_SYSCONFIG, - /* (3 << 8) | (2 << 3) | */ - OMAP2_MCSPI_SYSCONFIG_AUTOIDLE); + OMAP2_MCSPI_SYSCONFIG_AUTOIDLE | + OMAP2_MCSPI_SYSCONFIG_ENAWAKEUP | + OMAP2_MCSPI_SYSCONFIG_SMARTIDLE); + + mcspi_write_reg(master, OMAP2_MCSPI_WAKEUPENABLE, + OMAP2_MCSPI_WAKEUPENABLE_WKEN); omap2_mcspi_set_master_mode(master); -- cgit v1.2.3 From 57c5c28dbc835c67a9c23912bab56b7f165e7715 Mon Sep 17 00:00:00 2001 From: Eero Nurkkala Date: Wed, 29 Jul 2009 15:02:12 -0700 Subject: spi: omap2_mcspi rxdma bugfix When data is read through DMA, the last element must be read separately through the RX register. It cannot be transferred by the DMA. For further details see e.g. OMAP35x TRM (table 19-16). Without the fix the driver causes extra clocks to be clocked to the bus after DMA RX operations. This can cause interesting behaviour with some devices. Signed-off-by: Juuso Oikarinen Signed-off-by: Eero Nurkkala [aaro.koskinen@nokia.com: Simplified the patch while keeping the idea.] Signed-off-by: Aaro Koskinen Signed-off-by: David Brownell Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/spi/omap2_mcspi.c | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/drivers/spi/omap2_mcspi.c b/drivers/spi/omap2_mcspi.c index 2b64091b0f1f..9b80ad36dbba 100644 --- a/drivers/spi/omap2_mcspi.c +++ b/drivers/spi/omap2_mcspi.c @@ -272,7 +272,7 @@ omap2_mcspi_txrx_dma(struct spi_device *spi, struct spi_transfer *xfer) if (rx != NULL) { omap_set_dma_transfer_params(mcspi_dma->dma_rx_channel, - data_type, element_count, 1, + data_type, element_count - 1, 1, OMAP_DMA_SYNC_ELEMENT, mcspi_dma->dma_rx_sync_dev, 1); @@ -303,6 +303,25 @@ omap2_mcspi_txrx_dma(struct spi_device *spi, struct spi_transfer *xfer) if (rx != NULL) { wait_for_completion(&mcspi_dma->dma_rx_completion); dma_unmap_single(NULL, xfer->rx_dma, count, DMA_FROM_DEVICE); + omap2_mcspi_set_enable(spi, 0); + if (likely(mcspi_read_cs_reg(spi, OMAP2_MCSPI_CHSTAT0) + & OMAP2_MCSPI_CHSTAT_RXS)) { + u32 w; + + w = mcspi_read_cs_reg(spi, OMAP2_MCSPI_RX0); + if (word_len <= 8) + ((u8 *)xfer->rx_buf)[element_count - 1] = w; + else if (word_len <= 16) + ((u16 *)xfer->rx_buf)[element_count - 1] = w; + else /* word_len <= 32 */ + ((u32 *)xfer->rx_buf)[element_count - 1] = w; + } else { + dev_err(&spi->dev, "DMA RX last word empty"); + count -= (word_len <= 8) ? 1 : + (word_len <= 16) ? 2 : + /* word_len <= 32 */ 4; + } + omap2_mcspi_set_enable(spi, 1); } return count; } -- cgit v1.2.3 From 659098141d02eb8e3545be8969d262e02d2f3f98 Mon Sep 17 00:00:00 2001 From: Thadeu Lima de Souza Cascardo Date: Wed, 29 Jul 2009 15:02:13 -0700 Subject: rtc: mark if rtc-cmos drivers were successfully registered rtc-cmos has two drivers, one PNP and one platform. When PNP has not succeeded probing, platform is registered. However, it tries to unregister both drivers unconditionally, instead of only unregistering those that were successfully registered. This causes runtime warnings to be emitted from the driver core code. Fix this with a boolean variable for each driver indicating whether registering was successful. Signed-off-by: Thadeu Lima de Souza Cascardo Cc: David Brownell Cc: Bjorn Helgaas Cc: Alessandro Zummo Cc: Ingo Molnar Cc: David Brownell Cc: Kay Sievers Cc: Greg KH Cc: Ozan Caglayan Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/rtc/rtc-cmos.c | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/drivers/rtc/rtc-cmos.c b/drivers/rtc/rtc-cmos.c index 23e10b6263d6..f7a4701bf863 100644 --- a/drivers/rtc/rtc-cmos.c +++ b/drivers/rtc/rtc-cmos.c @@ -1174,23 +1174,34 @@ static struct platform_driver cmos_platform_driver = { } }; +#ifdef CONFIG_PNP +static bool pnp_driver_registered; +#endif +static bool platform_driver_registered; + static int __init cmos_init(void) { int retval = 0; #ifdef CONFIG_PNP - pnp_register_driver(&cmos_pnp_driver); + retval = pnp_register_driver(&cmos_pnp_driver); + if (retval == 0) + pnp_driver_registered = true; #endif - if (!cmos_rtc.dev) + if (!cmos_rtc.dev) { retval = platform_driver_probe(&cmos_platform_driver, cmos_platform_probe); + if (retval == 0) + platform_driver_registered = true; + } if (retval == 0) return 0; #ifdef CONFIG_PNP - pnp_unregister_driver(&cmos_pnp_driver); + if (pnp_driver_registered) + pnp_unregister_driver(&cmos_pnp_driver); #endif return retval; } @@ -1199,9 +1210,11 @@ module_init(cmos_init); static void __exit cmos_exit(void) { #ifdef CONFIG_PNP - pnp_unregister_driver(&cmos_pnp_driver); + if (pnp_driver_registered) + pnp_unregister_driver(&cmos_pnp_driver); #endif - platform_driver_unregister(&cmos_platform_driver); + if (platform_driver_registered) + platform_driver_unregister(&cmos_platform_driver); } module_exit(cmos_exit); -- cgit v1.2.3 From e4c6f8bed01f9f9a5c607bd689bf67e7b8a36bd8 Mon Sep 17 00:00:00 2001 From: Eric Sandeen Date: Wed, 29 Jul 2009 15:02:16 -0700 Subject: hugetlbfs: fix i_blocks accounting As reported in Red Hat bz #509671, i_blocks for files on hugetlbfs get accounting wrong when doing something like: $ > foo $ date > foo date: write error: Invalid argument $ /usr/bin/stat foo File: `foo' Size: 0 Blocks: 18446744073709547520 IO Block: 2097152 regular ... This is because hugetlb_unreserve_pages() is unconditionally removing blocks_per_huge_page(h) on each call rather than using the freed amount. If there were 0 blocks, it goes negative, resulting in the above. This is a regression from commit a5516438959d90b071ff0a484ce4f3f523dc3152 ("hugetlb: modular state for hugetlb page size") which did: - inode->i_blocks -= BLOCKS_PER_HUGEPAGE * freed; + inode->i_blocks -= blocks_per_huge_page(h); so just put back the freed multiplier, and it's all happy again. Signed-off-by: Eric Sandeen Acked-by: Andi Kleen Cc: William Lee Irwin III Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- mm/hugetlb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mm/hugetlb.c b/mm/hugetlb.c index d0351e31f474..cafdcee154e8 100644 --- a/mm/hugetlb.c +++ b/mm/hugetlb.c @@ -2370,7 +2370,7 @@ void hugetlb_unreserve_pages(struct inode *inode, long offset, long freed) long chg = region_truncate(&inode->i_mapping->private_list, offset); spin_lock(&inode->i_lock); - inode->i_blocks -= blocks_per_huge_page(h); + inode->i_blocks -= (blocks_per_huge_page(h) * freed); spin_unlock(&inode->i_lock); hugetlb_put_quota(inode->i_mapping, (chg - freed)); -- cgit v1.2.3 From 3fc7b4b220c7e830a5b3ce0ea5f85a635e0c50f0 Mon Sep 17 00:00:00 2001 From: Roland Dreier Date: Wed, 29 Jul 2009 15:04:02 -0700 Subject: lib: export generic atomic64_t functions The generic atomic64_t implementation in lib/ did not export the functions it defined, which means that modules that use atomic64_t would not link on platforms (such as 32-bit powerpc). For example, trying to build a kernel with CONFIG_NET_RDS on such a platform would fail with: ERROR: "atomic64_read" [net/rds/rds.ko] undefined! ERROR: "atomic64_set" [net/rds/rds.ko] undefined! Fix this by exporting the atomic64_t functions to modules. (I export the entire API even if it's not all currently used by in-tree modules to avoid having to continue fixing this in dribs and drabs) Signed-off-by: Roland Dreier Acked-by: Paul Mackerras Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- lib/atomic64.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/lib/atomic64.c b/lib/atomic64.c index c5e725562416..8bee16ec7524 100644 --- a/lib/atomic64.c +++ b/lib/atomic64.c @@ -13,6 +13,7 @@ #include #include #include +#include #include /* @@ -52,6 +53,7 @@ long long atomic64_read(const atomic64_t *v) spin_unlock_irqrestore(lock, flags); return val; } +EXPORT_SYMBOL(atomic64_read); void atomic64_set(atomic64_t *v, long long i) { @@ -62,6 +64,7 @@ void atomic64_set(atomic64_t *v, long long i) v->counter = i; spin_unlock_irqrestore(lock, flags); } +EXPORT_SYMBOL(atomic64_set); void atomic64_add(long long a, atomic64_t *v) { @@ -72,6 +75,7 @@ void atomic64_add(long long a, atomic64_t *v) v->counter += a; spin_unlock_irqrestore(lock, flags); } +EXPORT_SYMBOL(atomic64_add); long long atomic64_add_return(long long a, atomic64_t *v) { @@ -84,6 +88,7 @@ long long atomic64_add_return(long long a, atomic64_t *v) spin_unlock_irqrestore(lock, flags); return val; } +EXPORT_SYMBOL(atomic64_add_return); void atomic64_sub(long long a, atomic64_t *v) { @@ -94,6 +99,7 @@ void atomic64_sub(long long a, atomic64_t *v) v->counter -= a; spin_unlock_irqrestore(lock, flags); } +EXPORT_SYMBOL(atomic64_sub); long long atomic64_sub_return(long long a, atomic64_t *v) { @@ -106,6 +112,7 @@ long long atomic64_sub_return(long long a, atomic64_t *v) spin_unlock_irqrestore(lock, flags); return val; } +EXPORT_SYMBOL(atomic64_sub_return); long long atomic64_dec_if_positive(atomic64_t *v) { @@ -120,6 +127,7 @@ long long atomic64_dec_if_positive(atomic64_t *v) spin_unlock_irqrestore(lock, flags); return val; } +EXPORT_SYMBOL(atomic64_dec_if_positive); long long atomic64_cmpxchg(atomic64_t *v, long long o, long long n) { @@ -134,6 +142,7 @@ long long atomic64_cmpxchg(atomic64_t *v, long long o, long long n) spin_unlock_irqrestore(lock, flags); return val; } +EXPORT_SYMBOL(atomic64_cmpxchg); long long atomic64_xchg(atomic64_t *v, long long new) { @@ -147,6 +156,7 @@ long long atomic64_xchg(atomic64_t *v, long long new) spin_unlock_irqrestore(lock, flags); return val; } +EXPORT_SYMBOL(atomic64_xchg); int atomic64_add_unless(atomic64_t *v, long long a, long long u) { @@ -162,6 +172,7 @@ int atomic64_add_unless(atomic64_t *v, long long a, long long u) spin_unlock_irqrestore(lock, flags); return ret; } +EXPORT_SYMBOL(atomic64_add_unless); static int init_atomic64_lock(void) { -- cgit v1.2.3 From b317c833211b7fbf902163de766f09554090e0bf Mon Sep 17 00:00:00 2001 From: Kristoffer Ericson Date: Wed, 29 Jul 2009 15:04:03 -0700 Subject: drivers/video/backlight/jornada720_bl.c: fix build Signed-off-by: Kristoffer Ericson Cc: Richard Purdie Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/video/backlight/jornada720_bl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/video/backlight/jornada720_bl.c b/drivers/video/backlight/jornada720_bl.c index c3ebb6b41ce1..7aed2565c1bd 100644 --- a/drivers/video/backlight/jornada720_bl.c +++ b/drivers/video/backlight/jornada720_bl.c @@ -72,7 +72,7 @@ static int jornada_bl_update_status(struct backlight_device *bd) if (jornada_ssp_byte(SETBRIGHTNESS) != TXDUMMY) { printk(KERN_INFO "bl : failed to set brightness\n"); ret = -ETIMEDOUT; - goto out + goto out; } /* at this point we expect that the mcu has accepted -- cgit v1.2.3 From 096b7fe012d66ed55e98bc8022405ede0cc80e96 Mon Sep 17 00:00:00 2001 From: Li Zefan Date: Wed, 29 Jul 2009 15:04:04 -0700 Subject: cgroups: fix pid namespace bug The bug was introduced by commit cc31edceee04a7b87f2be48f9489ebb72d264844 ("cgroups: convert tasks file to use a seq_file with shared pid array"). We cache a pid array for all threads that are opening the same "tasks" file, but the pids in the array are always from the namespace of the last process that opened the file, so all other threads will read pids from that namespace instead of their own namespaces. To fix it, we maintain a list of pid arrays, which is keyed by pid_ns. The list will be of length 1 at most time. Reported-by: Paul Menage Idea-by: Paul Menage Signed-off-by: Li Zefan Reviewed-by: Serge Hallyn Cc: Balbir Singh Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/linux/cgroup.h | 11 +++--- kernel/cgroup.c | 96 +++++++++++++++++++++++++++++++++++++------------- 2 files changed, 76 insertions(+), 31 deletions(-) diff --git a/include/linux/cgroup.h b/include/linux/cgroup.h index 665fa70e4094..20411d2876f8 100644 --- a/include/linux/cgroup.h +++ b/include/linux/cgroup.h @@ -179,14 +179,11 @@ struct cgroup { */ struct list_head release_list; - /* pids_mutex protects the fields below */ + /* pids_mutex protects pids_list and cached pid arrays. */ struct rw_semaphore pids_mutex; - /* Array of process ids in the cgroup */ - pid_t *tasks_pids; - /* How many files are using the current tasks_pids array */ - int pids_use_count; - /* Length of the current tasks_pids array */ - int pids_length; + + /* Linked list of struct cgroup_pids */ + struct list_head pids_list; /* For RCU-protected deletion */ struct rcu_head rcu_head; diff --git a/kernel/cgroup.c b/kernel/cgroup.c index 3737a682cdf5..250dac05680f 100644 --- a/kernel/cgroup.c +++ b/kernel/cgroup.c @@ -47,6 +47,7 @@ #include #include #include +#include #include @@ -960,6 +961,7 @@ static void init_cgroup_housekeeping(struct cgroup *cgrp) INIT_LIST_HEAD(&cgrp->children); INIT_LIST_HEAD(&cgrp->css_sets); INIT_LIST_HEAD(&cgrp->release_list); + INIT_LIST_HEAD(&cgrp->pids_list); init_rwsem(&cgrp->pids_mutex); } static void init_cgroup_root(struct cgroupfs_root *root) @@ -2201,12 +2203,30 @@ err: return ret; } +/* + * Cache pids for all threads in the same pid namespace that are + * opening the same "tasks" file. + */ +struct cgroup_pids { + /* The node in cgrp->pids_list */ + struct list_head list; + /* The cgroup those pids belong to */ + struct cgroup *cgrp; + /* The namepsace those pids belong to */ + struct pid_namespace *ns; + /* Array of process ids in the cgroup */ + pid_t *tasks_pids; + /* How many files are using the this tasks_pids array */ + int use_count; + /* Length of the current tasks_pids array */ + int length; +}; + static int cmppid(const void *a, const void *b) { return *(pid_t *)a - *(pid_t *)b; } - /* * seq_file methods for the "tasks" file. The seq_file position is the * next pid to display; the seq_file iterator is a pointer to the pid @@ -2221,45 +2241,47 @@ static void *cgroup_tasks_start(struct seq_file *s, loff_t *pos) * after a seek to the start). Use a binary-search to find the * next pid to display, if any */ - struct cgroup *cgrp = s->private; + struct cgroup_pids *cp = s->private; + struct cgroup *cgrp = cp->cgrp; int index = 0, pid = *pos; int *iter; down_read(&cgrp->pids_mutex); if (pid) { - int end = cgrp->pids_length; + int end = cp->length; while (index < end) { int mid = (index + end) / 2; - if (cgrp->tasks_pids[mid] == pid) { + if (cp->tasks_pids[mid] == pid) { index = mid; break; - } else if (cgrp->tasks_pids[mid] <= pid) + } else if (cp->tasks_pids[mid] <= pid) index = mid + 1; else end = mid; } } /* If we're off the end of the array, we're done */ - if (index >= cgrp->pids_length) + if (index >= cp->length) return NULL; /* Update the abstract position to be the actual pid that we found */ - iter = cgrp->tasks_pids + index; + iter = cp->tasks_pids + index; *pos = *iter; return iter; } static void cgroup_tasks_stop(struct seq_file *s, void *v) { - struct cgroup *cgrp = s->private; + struct cgroup_pids *cp = s->private; + struct cgroup *cgrp = cp->cgrp; up_read(&cgrp->pids_mutex); } static void *cgroup_tasks_next(struct seq_file *s, void *v, loff_t *pos) { - struct cgroup *cgrp = s->private; + struct cgroup_pids *cp = s->private; int *p = v; - int *end = cgrp->tasks_pids + cgrp->pids_length; + int *end = cp->tasks_pids + cp->length; /* * Advance to the next pid in the array. If this goes off the @@ -2286,26 +2308,33 @@ static struct seq_operations cgroup_tasks_seq_operations = { .show = cgroup_tasks_show, }; -static void release_cgroup_pid_array(struct cgroup *cgrp) +static void release_cgroup_pid_array(struct cgroup_pids *cp) { + struct cgroup *cgrp = cp->cgrp; + down_write(&cgrp->pids_mutex); - BUG_ON(!cgrp->pids_use_count); - if (!--cgrp->pids_use_count) { - kfree(cgrp->tasks_pids); - cgrp->tasks_pids = NULL; - cgrp->pids_length = 0; + BUG_ON(!cp->use_count); + if (!--cp->use_count) { + list_del(&cp->list); + put_pid_ns(cp->ns); + kfree(cp->tasks_pids); + kfree(cp); } up_write(&cgrp->pids_mutex); } static int cgroup_tasks_release(struct inode *inode, struct file *file) { - struct cgroup *cgrp = __d_cgrp(file->f_dentry->d_parent); + struct seq_file *seq; + struct cgroup_pids *cp; if (!(file->f_mode & FMODE_READ)) return 0; - release_cgroup_pid_array(cgrp); + seq = file->private_data; + cp = seq->private; + + release_cgroup_pid_array(cp); return seq_release(inode, file); } @@ -2324,6 +2353,8 @@ static struct file_operations cgroup_tasks_operations = { static int cgroup_tasks_open(struct inode *unused, struct file *file) { struct cgroup *cgrp = __d_cgrp(file->f_dentry->d_parent); + struct pid_namespace *ns = current->nsproxy->pid_ns; + struct cgroup_pids *cp; pid_t *pidarray; int npids; int retval; @@ -2350,20 +2381,37 @@ static int cgroup_tasks_open(struct inode *unused, struct file *file) * array if necessary */ down_write(&cgrp->pids_mutex); - kfree(cgrp->tasks_pids); - cgrp->tasks_pids = pidarray; - cgrp->pids_length = npids; - cgrp->pids_use_count++; + + list_for_each_entry(cp, &cgrp->pids_list, list) { + if (ns == cp->ns) + goto found; + } + + cp = kzalloc(sizeof(*cp), GFP_KERNEL); + if (!cp) { + up_write(&cgrp->pids_mutex); + kfree(pidarray); + return -ENOMEM; + } + cp->cgrp = cgrp; + cp->ns = ns; + get_pid_ns(ns); + list_add(&cp->list, &cgrp->pids_list); +found: + kfree(cp->tasks_pids); + cp->tasks_pids = pidarray; + cp->length = npids; + cp->use_count++; up_write(&cgrp->pids_mutex); file->f_op = &cgroup_tasks_operations; retval = seq_open(file, &cgroup_tasks_seq_operations); if (retval) { - release_cgroup_pid_array(cgrp); + release_cgroup_pid_array(cp); return retval; } - ((struct seq_file *)file->private_data)->private = cgrp; + ((struct seq_file *)file->private_data)->private = cp; return 0; } -- cgit v1.2.3 From f0d83679a8d471dc8b646919f70595d6fe8c9606 Mon Sep 17 00:00:00 2001 From: Sebastian Heutling Date: Wed, 29 Jul 2009 15:04:05 -0700 Subject: eeprom/at25: bugfix "not ready" timeout after write Under certain circumstances msleep(1) within the loop, which waits for the EEPROM to be finished, might take longer than the timeout. On the next loop the status register might now return to be ready and therefore the loop finishes. The following check now tests if a timeout occurred and if so returns an error although the device reported it was ready. This fix replaces testing the occurrence of the timeout by testing the "not ready" bit in the status register. Signed-off-by: Sebastian Heutling Signed-off-by: David Brownell Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/misc/eeprom/at25.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/misc/eeprom/at25.c b/drivers/misc/eeprom/at25.c index b34cb5f79eea..2e535a0ccd5e 100644 --- a/drivers/misc/eeprom/at25.c +++ b/drivers/misc/eeprom/at25.c @@ -173,6 +173,7 @@ at25_ee_write(struct at25_data *at25, const char *buf, loff_t off, unsigned segment; unsigned offset = (unsigned) off; u8 *cp = bounce + 1; + int sr; *cp = AT25_WREN; status = spi_write(at25->spi, cp, 1); @@ -214,7 +215,6 @@ at25_ee_write(struct at25_data *at25, const char *buf, loff_t off, timeout = jiffies + msecs_to_jiffies(EE_TIMEOUT); retries = 0; do { - int sr; sr = spi_w8r8(at25->spi, AT25_RDSR); if (sr < 0 || (sr & AT25_SR_nRDY)) { @@ -228,7 +228,7 @@ at25_ee_write(struct at25_data *at25, const char *buf, loff_t off, break; } while (retries++ < 3 || time_before_eq(jiffies, timeout)); - if (time_after(jiffies, timeout)) { + if ((sr < 0) || (sr & AT25_SR_nRDY)) { dev_err(&at25->spi->dev, "write %d bytes offset %d, " "timeout after %u msecs\n", -- cgit v1.2.3 From 887032670d47366a8c8f25396ea7c14b7b2cc620 Mon Sep 17 00:00:00 2001 From: KAMEZAWA Hiroyuki Date: Wed, 29 Jul 2009 15:04:06 -0700 Subject: cgroup avoid permanent sleep at rmdir After commit ec64f51545fffbc4cb968f0cea56341a4b07e85a ("cgroup: fix frequent -EBUSY at rmdir"), cgroup's rmdir (especially against memcg) doesn't return -EBUSY by temporary ref counts. That commit expects all refs after pre_destroy() is temporary but...it wasn't. Then, rmdir can wait permanently. This patch tries to fix that and change followings. - set CGRP_WAIT_ON_RMDIR flag before pre_destroy(). - clear CGRP_WAIT_ON_RMDIR flag when the subsys finds racy case. if there are sleeping ones, wakes them up. - rmdir() sleeps only when CGRP_WAIT_ON_RMDIR flag is set. Tested-by: Daisuke Nishimura Reported-by: Daisuke Nishimura Reviewed-by: Paul Menage Acked-by: Balbir Sigh Signed-off-by: KAMEZAWA Hiroyuki Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/linux/cgroup.h | 17 ++++++++++++++++ kernel/cgroup.c | 55 ++++++++++++++++++++++++++++++++++---------------- mm/memcontrol.c | 23 ++++++++++++++++++--- 3 files changed, 75 insertions(+), 20 deletions(-) diff --git a/include/linux/cgroup.h b/include/linux/cgroup.h index 20411d2876f8..90bba9e62286 100644 --- a/include/linux/cgroup.h +++ b/include/linux/cgroup.h @@ -362,6 +362,23 @@ int cgroup_task_count(const struct cgroup *cgrp); /* Return true if cgrp is a descendant of the task's cgroup */ int cgroup_is_descendant(const struct cgroup *cgrp, struct task_struct *task); +/* + * When the subsys has to access css and may add permanent refcnt to css, + * it should take care of racy conditions with rmdir(). Following set of + * functions, is for stop/restart rmdir if necessary. + * Because these will call css_get/put, "css" should be alive css. + * + * cgroup_exclude_rmdir(); + * ...do some jobs which may access arbitrary empty cgroup + * cgroup_release_and_wakeup_rmdir(); + * + * When someone removes a cgroup while cgroup_exclude_rmdir() holds it, + * it sleeps and cgroup_release_and_wakeup_rmdir() will wake him up. + */ + +void cgroup_exclude_rmdir(struct cgroup_subsys_state *css); +void cgroup_release_and_wakeup_rmdir(struct cgroup_subsys_state *css); + /* * Control Group subsystem type. * See Documentation/cgroups/cgroups.txt for details diff --git a/kernel/cgroup.c b/kernel/cgroup.c index 250dac05680f..b6eadfe30e7b 100644 --- a/kernel/cgroup.c +++ b/kernel/cgroup.c @@ -735,16 +735,28 @@ static void cgroup_d_remove_dir(struct dentry *dentry) * reference to css->refcnt. In general, this refcnt is expected to goes down * to zero, soon. * - * CGRP_WAIT_ON_RMDIR flag is modified under cgroup's inode->i_mutex; + * CGRP_WAIT_ON_RMDIR flag is set under cgroup's inode->i_mutex; */ DECLARE_WAIT_QUEUE_HEAD(cgroup_rmdir_waitq); -static void cgroup_wakeup_rmdir_waiters(const struct cgroup *cgrp) +static void cgroup_wakeup_rmdir_waiter(struct cgroup *cgrp) { - if (unlikely(test_bit(CGRP_WAIT_ON_RMDIR, &cgrp->flags))) + if (unlikely(test_and_clear_bit(CGRP_WAIT_ON_RMDIR, &cgrp->flags))) wake_up_all(&cgroup_rmdir_waitq); } +void cgroup_exclude_rmdir(struct cgroup_subsys_state *css) +{ + css_get(css); +} + +void cgroup_release_and_wakeup_rmdir(struct cgroup_subsys_state *css) +{ + cgroup_wakeup_rmdir_waiter(css->cgroup); + css_put(css); +} + + static int rebind_subsystems(struct cgroupfs_root *root, unsigned long final_bits) { @@ -1359,7 +1371,7 @@ int cgroup_attach_task(struct cgroup *cgrp, struct task_struct *tsk) * wake up rmdir() waiter. the rmdir should fail since the cgroup * is no longer empty. */ - cgroup_wakeup_rmdir_waiters(cgrp); + cgroup_wakeup_rmdir_waiter(cgrp); return 0; } @@ -2743,34 +2755,43 @@ again: } mutex_unlock(&cgroup_mutex); + /* + * In general, subsystem has no css->refcnt after pre_destroy(). But + * in racy cases, subsystem may have to get css->refcnt after + * pre_destroy() and it makes rmdir return with -EBUSY. This sometimes + * make rmdir return -EBUSY too often. To avoid that, we use waitqueue + * for cgroup's rmdir. CGRP_WAIT_ON_RMDIR is for synchronizing rmdir + * and subsystem's reference count handling. Please see css_get/put + * and css_tryget() and cgroup_wakeup_rmdir_waiter() implementation. + */ + set_bit(CGRP_WAIT_ON_RMDIR, &cgrp->flags); + /* * Call pre_destroy handlers of subsys. Notify subsystems * that rmdir() request comes. */ ret = cgroup_call_pre_destroy(cgrp); - if (ret) + if (ret) { + clear_bit(CGRP_WAIT_ON_RMDIR, &cgrp->flags); return ret; + } mutex_lock(&cgroup_mutex); parent = cgrp->parent; if (atomic_read(&cgrp->count) || !list_empty(&cgrp->children)) { + clear_bit(CGRP_WAIT_ON_RMDIR, &cgrp->flags); mutex_unlock(&cgroup_mutex); return -EBUSY; } - /* - * css_put/get is provided for subsys to grab refcnt to css. In typical - * case, subsystem has no reference after pre_destroy(). But, under - * hierarchy management, some *temporal* refcnt can be hold. - * To avoid returning -EBUSY to a user, waitqueue is used. If subsys - * is really busy, it should return -EBUSY at pre_destroy(). wake_up - * is called when css_put() is called and refcnt goes down to 0. - */ - set_bit(CGRP_WAIT_ON_RMDIR, &cgrp->flags); prepare_to_wait(&cgroup_rmdir_waitq, &wait, TASK_INTERRUPTIBLE); - if (!cgroup_clear_css_refs(cgrp)) { mutex_unlock(&cgroup_mutex); - schedule(); + /* + * Because someone may call cgroup_wakeup_rmdir_waiter() before + * prepare_to_wait(), we need to check this flag. + */ + if (test_bit(CGRP_WAIT_ON_RMDIR, &cgrp->flags)) + schedule(); finish_wait(&cgroup_rmdir_waitq, &wait); clear_bit(CGRP_WAIT_ON_RMDIR, &cgrp->flags); if (signal_pending(current)) @@ -3342,7 +3363,7 @@ void __css_put(struct cgroup_subsys_state *css) set_bit(CGRP_RELEASABLE, &cgrp->flags); check_for_release(cgrp); } - cgroup_wakeup_rmdir_waiters(cgrp); + cgroup_wakeup_rmdir_waiter(cgrp); } rcu_read_unlock(); } diff --git a/mm/memcontrol.c b/mm/memcontrol.c index e717964cb5a0..fd4529d86de5 100644 --- a/mm/memcontrol.c +++ b/mm/memcontrol.c @@ -1207,6 +1207,12 @@ static int mem_cgroup_move_account(struct page_cgroup *pc, ret = 0; out: unlock_page_cgroup(pc); + /* + * We charges against "to" which may not have any tasks. Then, "to" + * can be under rmdir(). But in current implementation, caller of + * this function is just force_empty() and it's garanteed that + * "to" is never removed. So, we don't check rmdir status here. + */ return ret; } @@ -1428,6 +1434,7 @@ __mem_cgroup_commit_charge_swapin(struct page *page, struct mem_cgroup *ptr, return; if (!ptr) return; + cgroup_exclude_rmdir(&ptr->css); pc = lookup_page_cgroup(page); mem_cgroup_lru_del_before_commit_swapcache(page); __mem_cgroup_commit_charge(ptr, pc, ctype); @@ -1457,8 +1464,12 @@ __mem_cgroup_commit_charge_swapin(struct page *page, struct mem_cgroup *ptr, } rcu_read_unlock(); } - /* add this page(page_cgroup) to the LRU we want. */ - + /* + * At swapin, we may charge account against cgroup which has no tasks. + * So, rmdir()->pre_destroy() can be called while we do this charge. + * In that case, we need to call pre_destroy() again. check it here. + */ + cgroup_release_and_wakeup_rmdir(&ptr->css); } void mem_cgroup_commit_charge_swapin(struct page *page, struct mem_cgroup *ptr) @@ -1664,7 +1675,7 @@ void mem_cgroup_end_migration(struct mem_cgroup *mem, if (!mem) return; - + cgroup_exclude_rmdir(&mem->css); /* at migration success, oldpage->mapping is NULL. */ if (oldpage->mapping) { target = oldpage; @@ -1704,6 +1715,12 @@ void mem_cgroup_end_migration(struct mem_cgroup *mem, */ if (ctype == MEM_CGROUP_CHARGE_TYPE_MAPPED) mem_cgroup_uncharge_page(target); + /* + * At migration, we may charge account against cgroup which has no tasks + * So, rmdir()->pre_destroy() can be called while we do this charge. + * In that case, we need to call pre_destroy() again. check it here. + */ + cgroup_release_and_wakeup_rmdir(&mem->css); } /* -- cgit v1.2.3 From 1fc28b70fe2dbf87e061b6ce5091a1f8e4e5d4e7 Mon Sep 17 00:00:00 2001 From: Mel Gorman Date: Wed, 29 Jul 2009 15:04:08 -0700 Subject: page-allocator: allow too high-order warning messages to be suppressed with __GFP_NOWARN The page allocator warns once when an order >= MAX_ORDER is specified. This is to catch callers of the allocator that are always falling back to their worst-case when it was not expected. However, there are cases where the caller is behaving correctly but cannot suppress the warning. This patch allows the warning to be suppressed by the callers by specifying __GFP_NOWARN. Signed-off-by: Mel Gorman Acked-by: David Rientjes Cc: Arnaldo Carvalho de Melo Cc: "David S. Miller" Cc: "Rafael J. Wysocki" Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- mm/page_alloc.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/mm/page_alloc.c b/mm/page_alloc.c index 2dbb2fc68837..d052abbe3063 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -1745,8 +1745,10 @@ __alloc_pages_slowpath(gfp_t gfp_mask, unsigned int order, * be using allocators in order of preference for an area that is * too large. */ - if (WARN_ON_ONCE(order >= MAX_ORDER)) + if (order >= MAX_ORDER) { + WARN_ON_ONCE(!(gfp_mask & __GFP_NOWARN)); return NULL; + } /* * GFP_THISNODE (meaning __GFP_THISNODE, __GFP_NORETRY and -- cgit v1.2.3 From b62f495dad04fa94b5083aec638ff3072bccaaca Mon Sep 17 00:00:00 2001 From: Mel Gorman Date: Wed, 29 Jul 2009 15:04:09 -0700 Subject: profile: suppress warning about large allocations when profile=1 is specified When profile= is used, a large buffer is allocated early at boot. This can be larger than what the page allocator can provide so it prints a warning. However, the caller is able to handle the situation so this patch suppresses the warning. Signed-off-by: Mel Gorman Cc: "Rafael J. Wysocki" Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- kernel/profile.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/kernel/profile.c b/kernel/profile.c index 69911b5745eb..419250ebec4d 100644 --- a/kernel/profile.c +++ b/kernel/profile.c @@ -117,11 +117,12 @@ int __ref profile_init(void) cpumask_copy(prof_cpu_mask, cpu_possible_mask); - prof_buffer = kzalloc(buffer_bytes, GFP_KERNEL); + prof_buffer = kzalloc(buffer_bytes, GFP_KERNEL|__GFP_NOWARN); if (prof_buffer) return 0; - prof_buffer = alloc_pages_exact(buffer_bytes, GFP_KERNEL|__GFP_ZERO); + prof_buffer = alloc_pages_exact(buffer_bytes, + GFP_KERNEL|__GFP_ZERO|__GFP_NOWARN); if (prof_buffer) return 0; -- cgit v1.2.3 From 1c29b3ff4f2d847464f7be3a0e179c6dfc69bd02 Mon Sep 17 00:00:00 2001 From: Mel Gorman Date: Wed, 29 Jul 2009 15:04:10 -0700 Subject: net-dccp: suppress warning about large allocations from DCCP The DCCP protocol tries to allocate some large hash tables during initialisation using the largest size possible. This can be larger than what the page allocator can provide so it prints a warning. However, the caller is able to handle the situation so this patch suppresses the warning. Signed-off-by: Mel Gorman Acked-by: Arnaldo Carvalho de Melo Cc: "David S. Miller" Cc: "Rafael J. Wysocki" Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- net/dccp/proto.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/net/dccp/proto.c b/net/dccp/proto.c index 94ca8eaace7d..3281013ce038 100644 --- a/net/dccp/proto.c +++ b/net/dccp/proto.c @@ -1066,7 +1066,7 @@ static int __init dccp_init(void) (dccp_hashinfo.ehash_size - 1)) dccp_hashinfo.ehash_size--; dccp_hashinfo.ehash = (struct inet_ehash_bucket *) - __get_free_pages(GFP_ATOMIC, ehash_order); + __get_free_pages(GFP_ATOMIC|__GFP_NOWARN, ehash_order); } while (!dccp_hashinfo.ehash && --ehash_order > 0); if (!dccp_hashinfo.ehash) { @@ -1091,7 +1091,7 @@ static int __init dccp_init(void) bhash_order > 0) continue; dccp_hashinfo.bhash = (struct inet_bind_hashbucket *) - __get_free_pages(GFP_ATOMIC, bhash_order); + __get_free_pages(GFP_ATOMIC|__GFP_NOWARN, bhash_order); } while (!dccp_hashinfo.bhash && --bhash_order >= 0); if (!dccp_hashinfo.bhash) { -- cgit v1.2.3 From 5c8053652328693d10551131432ef3573e77ed2d Mon Sep 17 00:00:00 2001 From: Catalin Marinas Date: Wed, 29 Jul 2009 15:04:11 -0700 Subject: fs/ramfs/file-nommu.c needs include/linux/sched.h This file makes use of various macros defined in files like asm/current.h or asm-generic/resource.h. All these files can be included via sched.h. The building of the !MMU ARM kernel (with additional patches) fails without this change. Signed-off-by: Catalin Marinas Acked-by: David Howells Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/ramfs/file-nommu.c | 1 + 1 file changed, 1 insertion(+) diff --git a/fs/ramfs/file-nommu.c b/fs/ramfs/file-nommu.c index ebb2c417912c..11f0c06316de 100644 --- a/fs/ramfs/file-nommu.c +++ b/fs/ramfs/file-nommu.c @@ -20,6 +20,7 @@ #include #include #include +#include #include #include "internal.h" -- cgit v1.2.3 From f5a55efa140f5e9c9dd0f398fef54f20cdb74ec9 Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Wed, 29 Jul 2009 15:04:12 -0700 Subject: pps.h needs Found with make headers_check /usr/include/linux/pps.h:52: found __[us]{8,16,32,64} type without #include Signed-off-by: Dave Jones Cc: Rodolfo Giometti Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/linux/pps.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/include/linux/pps.h b/include/linux/pps.h index cfe5c7214ec6..0194ab06177b 100644 --- a/include/linux/pps.h +++ b/include/linux/pps.h @@ -22,6 +22,8 @@ #ifndef _PPS_H_ #define _PPS_H_ +#include + #define PPS_VERSION "5.3.6" #define PPS_MAX_SOURCES 16 /* should be enough... */ -- cgit v1.2.3 From cab8bd3410d448279e3bd0fbf96d31db0bf770fa Mon Sep 17 00:00:00 2001 From: Hidetoshi Seto Date: Wed, 29 Jul 2009 15:04:14 -0700 Subject: sysrq, kdump: make sysrq-c consistent commit d6580a9f15238b87e618310c862231ae3f352d2d ("kexec: sysrq: simplify sysrq-c handler") changed the behavior of sysrq-c to unconditional dereference of NULL pointer. So in cases with CONFIG_KEXEC, where crash_kexec() was directly called from sysrq-c before, now it can be said that a step of "real oops" was inserted before starting kdump. However, in contrast to oops via SysRq-c from keyboard which results in panic due to in_interrupt(), oops via "echo c > /proc/sysrq-trigger" will not become panic unless panic_on_oops=1. It means that even if dump is properly configured to be taken on panic, the sysrq-c from proc interface might not start crashdump while the sysrq-c from keyboard can start crashdump. This confuses traditional users of kdump, i.e. people who expect sysrq-c to do common behavior in both of the keyboard and proc interface. This patch brings the keyboard and proc interface behavior of sysrq-c in line, by forcing panic_on_oops=1 before oops in sysrq-c handler. And some updates in documentation are included, to clarify that there is no longer dependency with CONFIG_KEXEC, and that now the system can just crash by sysrq-c if no dump mechanism is configured. Signed-off-by: Hidetoshi Seto Cc: Lai Jiangshan Cc: Ken'ichi Ohmichi Acked-by: Neil Horman Acked-by: Vivek Goyal Cc: Brayan Arraes Cc: Eric W. Biederman Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- Documentation/sysrq.txt | 7 ++++--- drivers/char/sysrq.c | 8 +++++--- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/Documentation/sysrq.txt b/Documentation/sysrq.txt index cf42b820ff9d..d56a01775423 100644 --- a/Documentation/sysrq.txt +++ b/Documentation/sysrq.txt @@ -66,7 +66,8 @@ On all - write a character to /proc/sysrq-trigger. e.g.: 'b' - Will immediately reboot the system without syncing or unmounting your disks. -'c' - Will perform a kexec reboot in order to take a crashdump. +'c' - Will perform a system crash by a NULL pointer dereference. + A crashdump will be taken if configured. 'd' - Shows all locks that are held. @@ -141,8 +142,8 @@ useful when you want to exit a program that will not let you switch consoles. re'B'oot is good when you're unable to shut down. But you should also 'S'ync and 'U'mount first. -'C'rashdump can be used to manually trigger a crashdump when the system is hung. -The kernel needs to have been built with CONFIG_KEXEC enabled. +'C'rash can be used to manually trigger a crashdump when the system is hung. +Note that this just triggers a crash if there is no dump mechanism available. 'S'ync is great when your system is locked up, it allows you to sync your disks and will certainly lessen the chance of data loss and fscking. Note diff --git a/drivers/char/sysrq.c b/drivers/char/sysrq.c index 0db35857e4d8..5d7a02f63e1c 100644 --- a/drivers/char/sysrq.c +++ b/drivers/char/sysrq.c @@ -35,7 +35,6 @@ #include #include #include -#include #include #include @@ -124,9 +123,12 @@ static struct sysrq_key_op sysrq_unraw_op = { static void sysrq_handle_crash(int key, struct tty_struct *tty) { char *killer = NULL; + + panic_on_oops = 1; /* force panic */ + wmb(); *killer = 1; } -static struct sysrq_key_op sysrq_crashdump_op = { +static struct sysrq_key_op sysrq_crash_op = { .handler = sysrq_handle_crash, .help_msg = "Crash", .action_msg = "Trigger a crash", @@ -401,7 +403,7 @@ static struct sysrq_key_op *sysrq_key_table[36] = { */ NULL, /* a */ &sysrq_reboot_op, /* b */ - &sysrq_crashdump_op, /* c & ibm_emac driver debug */ + &sysrq_crash_op, /* c & ibm_emac driver debug */ &sysrq_showlocks_op, /* d */ &sysrq_term_op, /* e */ &sysrq_moom_op, /* f */ -- cgit v1.2.3 From a9e58f25734e153b8c6516d904e2398fb8b0b23d Mon Sep 17 00:00:00 2001 From: Anton Vorontsov Date: Wed, 29 Jul 2009 15:04:16 -0700 Subject: sdhci: get rid of "frequency too high" flood when using eSDHC Since commit 8dfd0374be84793360db7fff2e635d2cd3bbcb21 ("MMC core: limit minimum initialization frequency to 400kHz") MMC core checks for minimum frequency, and that causes following messages flood when using eSDHC controllers: ... mmc0: Minimum clock frequency too high for identification mode mmc0: Minimum clock frequency too high for identification mode ... The warnings are legitimate, since if we'd use 133 MHz clocks for standard SDHCI controllers, we'd not able to scale frequency down to 400 kHz. But eSDHC controllers have a non-standard SD clock management, so we can divide clock by 256 * 16, not just 256. This patch introduces get_min_clock() callback for sdhci core and implements it for sdhci-of driver, and thus fixes the issue. Signed-off-by: Anton Vorontsov Cc: Matt Fleming Cc: Ian Molton Cc: "Roberto A. Foglietta" Cc: Pierre Ossman Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/mmc/host/sdhci-of.c | 8 ++++++++ drivers/mmc/host/sdhci.c | 5 ++++- drivers/mmc/host/sdhci.h | 1 + 3 files changed, 13 insertions(+), 1 deletion(-) diff --git a/drivers/mmc/host/sdhci-of.c b/drivers/mmc/host/sdhci-of.c index d79fa55c3b89..908844327db0 100644 --- a/drivers/mmc/host/sdhci-of.c +++ b/drivers/mmc/host/sdhci-of.c @@ -158,6 +158,13 @@ static unsigned int esdhc_get_max_clock(struct sdhci_host *host) return of_host->clock; } +static unsigned int esdhc_get_min_clock(struct sdhci_host *host) +{ + struct sdhci_of_host *of_host = sdhci_priv(host); + + return of_host->clock / 256 / 16; +} + static unsigned int esdhc_get_timeout_clock(struct sdhci_host *host) { struct sdhci_of_host *of_host = sdhci_priv(host); @@ -184,6 +191,7 @@ static struct sdhci_of_data sdhci_esdhc = { .set_clock = esdhc_set_clock, .enable_dma = esdhc_enable_dma, .get_max_clock = esdhc_get_max_clock, + .get_min_clock = esdhc_get_min_clock, .get_timeout_clock = esdhc_get_timeout_clock, }, }; diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c index 6779b4ecab18..62041c7e9246 100644 --- a/drivers/mmc/host/sdhci.c +++ b/drivers/mmc/host/sdhci.c @@ -1766,7 +1766,10 @@ int sdhci_add_host(struct sdhci_host *host) * Set host parameters. */ mmc->ops = &sdhci_ops; - mmc->f_min = host->max_clk / 256; + if (host->ops->get_min_clock) + mmc->f_min = host->ops->get_min_clock(host); + else + mmc->f_min = host->max_clk / 256; mmc->f_max = host->max_clk; mmc->caps = MMC_CAP_SDIO_IRQ; diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h index 831ddf7dcb49..c77e9ff30223 100644 --- a/drivers/mmc/host/sdhci.h +++ b/drivers/mmc/host/sdhci.h @@ -302,6 +302,7 @@ struct sdhci_ops { int (*enable_dma)(struct sdhci_host *host); unsigned int (*get_max_clock)(struct sdhci_host *host); + unsigned int (*get_min_clock)(struct sdhci_host *host); unsigned int (*get_timeout_clock)(struct sdhci_host *host); }; -- cgit v1.2.3 From 534acc057b5a08ec33fa57cdd2f5a09ef124e7f2 Mon Sep 17 00:00:00 2001 From: Dave Hansen Date: Wed, 29 Jul 2009 15:04:18 -0700 Subject: lib: flexible array implementation Once a structure goes over PAGE_SIZE*2, we see occasional allocation failures. Some people have chosen to switch over to things like vmalloc() that will let them keep array-like access to such a large structures. But, vmalloc() has plenty of downsides. Here's an alternative. I think it's what Andrew was suggesting here: http://lkml.org/lkml/2009/7/2/518 I call it a flexible array. It does all of its work in PAGE_SIZE bits, so never does an order>0 allocation. The base level has PAGE_SIZE-2*sizeof(int) bytes of storage for pointers to the second level. So, with a 32-bit arch, you get about 4MB (4183112 bytes) of total storage when the objects pack nicely into a page. It is half that on 64-bit because the pointers are twice the size. There's a table detailing this in the code. There are kerneldocs for the functions, but here's an overview: flex_array_alloc() - dynamically allocate a base structure flex_array_free() - free the array and all of the second-level pages flex_array_free_parts() - free the second-level pages, but not the base (for static bases) flex_array_put() - copy into the array at the given index flex_array_get() - copy out of the array at the given index flex_array_prealloc() - preallocate the second-level pages between the given indexes to guarantee no allocs will occur at put() time. We could also potentially just pass the "element_size" into each of the API functions instead of storing it internally. That would get us one more base pointer on 32-bit. I've been testing this by running it in userspace. The header and patch that I've been using are here, as well as the little script I'm using to generate the size table which goes in the kerneldocs. http://sr71.net/~dave/linux/flexarray/ [akpm@linux-foundation.org: coding-style fixes] Signed-off-by: Dave Hansen Reviewed-by: KAMEZAWA Hiroyuki Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/linux/flex_array.h | 47 ++++++++ lib/Makefile | 2 +- lib/flex_array.c | 269 +++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 317 insertions(+), 1 deletion(-) create mode 100644 include/linux/flex_array.h create mode 100644 lib/flex_array.c diff --git a/include/linux/flex_array.h b/include/linux/flex_array.h new file mode 100644 index 000000000000..23c1ec79a31b --- /dev/null +++ b/include/linux/flex_array.h @@ -0,0 +1,47 @@ +#ifndef _FLEX_ARRAY_H +#define _FLEX_ARRAY_H + +#include +#include + +#define FLEX_ARRAY_PART_SIZE PAGE_SIZE +#define FLEX_ARRAY_BASE_SIZE PAGE_SIZE + +struct flex_array_part; + +/* + * This is meant to replace cases where an array-like + * structure has gotten too big to fit into kmalloc() + * and the developer is getting tempted to use + * vmalloc(). + */ + +struct flex_array { + union { + struct { + int element_size; + int total_nr_elements; + struct flex_array_part *parts[0]; + }; + /* + * This little trick makes sure that + * sizeof(flex_array) == PAGE_SIZE + */ + char padding[FLEX_ARRAY_BASE_SIZE]; + }; +}; + +#define FLEX_ARRAY_INIT(size, total) { { {\ + .element_size = (size), \ + .total_nr_elements = (total), \ +} } } + +struct flex_array *flex_array_alloc(int element_size, int total, gfp_t flags); +int flex_array_prealloc(struct flex_array *fa, int start, int end, gfp_t flags); +void flex_array_free(struct flex_array *fa); +void flex_array_free_parts(struct flex_array *fa); +int flex_array_put(struct flex_array *fa, int element_nr, void *src, + gfp_t flags); +void *flex_array_get(struct flex_array *fa, int element_nr); + +#endif /* _FLEX_ARRAY_H */ diff --git a/lib/Makefile b/lib/Makefile index b6d1857bbf08..2e78277eff9d 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -12,7 +12,7 @@ lib-y := ctype.o string.o vsprintf.o cmdline.o \ idr.o int_sqrt.o extable.o prio_tree.o \ sha1.o irq_regs.o reciprocal_div.o argv_split.o \ proportions.o prio_heap.o ratelimit.o show_mem.o \ - is_single_threaded.o plist.o decompress.o + is_single_threaded.o plist.o decompress.o flex_array.o lib-$(CONFIG_MMU) += ioremap.o lib-$(CONFIG_SMP) += cpumask.o diff --git a/lib/flex_array.c b/lib/flex_array.c new file mode 100644 index 000000000000..0e7894ce8882 --- /dev/null +++ b/lib/flex_array.c @@ -0,0 +1,269 @@ +/* + * Flexible array managed in PAGE_SIZE parts + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * Copyright IBM Corporation, 2009 + * + * Author: Dave Hansen + */ + +#include +#include +#include + +struct flex_array_part { + char elements[FLEX_ARRAY_PART_SIZE]; +}; + +static inline int __elements_per_part(int element_size) +{ + return FLEX_ARRAY_PART_SIZE / element_size; +} + +static inline int bytes_left_in_base(void) +{ + int element_offset = offsetof(struct flex_array, parts); + int bytes_left = FLEX_ARRAY_BASE_SIZE - element_offset; + return bytes_left; +} + +static inline int nr_base_part_ptrs(void) +{ + return bytes_left_in_base() / sizeof(struct flex_array_part *); +} + +/* + * If a user requests an allocation which is small + * enough, we may simply use the space in the + * flex_array->parts[] array to store the user + * data. + */ +static inline int elements_fit_in_base(struct flex_array *fa) +{ + int data_size = fa->element_size * fa->total_nr_elements; + if (data_size <= bytes_left_in_base()) + return 1; + return 0; +} + +/** + * flex_array_alloc - allocate a new flexible array + * @element_size: the size of individual elements in the array + * @total: total number of elements that this should hold + * + * Note: all locking must be provided by the caller. + * + * @total is used to size internal structures. If the user ever + * accesses any array indexes >=@total, it will produce errors. + * + * The maximum number of elements is defined as: the number of + * elements that can be stored in a page times the number of + * page pointers that we can fit in the base structure or (using + * integer math): + * + * (PAGE_SIZE/element_size) * (PAGE_SIZE-8)/sizeof(void *) + * + * Here's a table showing example capacities. Note that the maximum + * index that the get/put() functions is just nr_objects-1. This + * basically means that you get 4MB of storage on 32-bit and 2MB on + * 64-bit. + * + * + * Element size | Objects | Objects | + * PAGE_SIZE=4k | 32-bit | 64-bit | + * ---------------------------------| + * 1 bytes | 4186112 | 2093056 | + * 2 bytes | 2093056 | 1046528 | + * 3 bytes | 1395030 | 697515 | + * 4 bytes | 1046528 | 523264 | + * 32 bytes | 130816 | 65408 | + * 33 bytes | 126728 | 63364 | + * 2048 bytes | 2044 | 1022 | + * 2049 bytes | 1022 | 511 | + * void * | 1046528 | 261632 | + * + * Since 64-bit pointers are twice the size, we lose half the + * capacity in the base structure. Also note that no effort is made + * to efficiently pack objects across page boundaries. + */ +struct flex_array *flex_array_alloc(int element_size, int total, gfp_t flags) +{ + struct flex_array *ret; + int max_size = nr_base_part_ptrs() * __elements_per_part(element_size); + + /* max_size will end up 0 if element_size > PAGE_SIZE */ + if (total > max_size) + return NULL; + ret = kzalloc(sizeof(struct flex_array), flags); + if (!ret) + return NULL; + ret->element_size = element_size; + ret->total_nr_elements = total; + return ret; +} + +static int fa_element_to_part_nr(struct flex_array *fa, int element_nr) +{ + return element_nr / __elements_per_part(fa->element_size); +} + +/** + * flex_array_free_parts - just free the second-level pages + * @src: address of data to copy into the array + * @element_nr: index of the position in which to insert + * the new element. + * + * This is to be used in cases where the base 'struct flex_array' + * has been statically allocated and should not be free. + */ +void flex_array_free_parts(struct flex_array *fa) +{ + int part_nr; + int max_part = nr_base_part_ptrs(); + + if (elements_fit_in_base(fa)) + return; + for (part_nr = 0; part_nr < max_part; part_nr++) + kfree(fa->parts[part_nr]); +} + +void flex_array_free(struct flex_array *fa) +{ + flex_array_free_parts(fa); + kfree(fa); +} + +static int fa_index_inside_part(struct flex_array *fa, int element_nr) +{ + return element_nr % __elements_per_part(fa->element_size); +} + +static int index_inside_part(struct flex_array *fa, int element_nr) +{ + int part_offset = fa_index_inside_part(fa, element_nr); + return part_offset * fa->element_size; +} + +static struct flex_array_part * +__fa_get_part(struct flex_array *fa, int part_nr, gfp_t flags) +{ + struct flex_array_part *part = fa->parts[part_nr]; + if (!part) { + /* + * This leaves the part pages uninitialized + * and with potentially random data, just + * as if the user had kmalloc()'d the whole. + * __GFP_ZERO can be used to zero it. + */ + part = kmalloc(FLEX_ARRAY_PART_SIZE, flags); + if (!part) + return NULL; + fa->parts[part_nr] = part; + } + return part; +} + +/** + * flex_array_put - copy data into the array at @element_nr + * @src: address of data to copy into the array + * @element_nr: index of the position in which to insert + * the new element. + * + * Note that this *copies* the contents of @src into + * the array. If you are trying to store an array of + * pointers, make sure to pass in &ptr instead of ptr. + * + * Locking must be provided by the caller. + */ +int flex_array_put(struct flex_array *fa, int element_nr, void *src, gfp_t flags) +{ + int part_nr = fa_element_to_part_nr(fa, element_nr); + struct flex_array_part *part; + void *dst; + + if (element_nr >= fa->total_nr_elements) + return -ENOSPC; + if (elements_fit_in_base(fa)) + part = (struct flex_array_part *)&fa->parts[0]; + else + part = __fa_get_part(fa, part_nr, flags); + if (!part) + return -ENOMEM; + dst = &part->elements[index_inside_part(fa, element_nr)]; + memcpy(dst, src, fa->element_size); + return 0; +} + +/** + * flex_array_prealloc - guarantee that array space exists + * @start: index of first array element for which space is allocated + * @end: index of last (inclusive) element for which space is allocated + * + * This will guarantee that no future calls to flex_array_put() + * will allocate memory. It can be used if you are expecting to + * be holding a lock or in some atomic context while writing + * data into the array. + * + * Locking must be provided by the caller. + */ +int flex_array_prealloc(struct flex_array *fa, int start, int end, gfp_t flags) +{ + int start_part; + int end_part; + int part_nr; + struct flex_array_part *part; + + if (start >= fa->total_nr_elements || end >= fa->total_nr_elements) + return -ENOSPC; + if (elements_fit_in_base(fa)) + return 0; + start_part = fa_element_to_part_nr(fa, start); + end_part = fa_element_to_part_nr(fa, end); + for (part_nr = start_part; part_nr <= end_part; part_nr++) { + part = __fa_get_part(fa, part_nr, flags); + if (!part) + return -ENOMEM; + } + return 0; +} + +/** + * flex_array_get - pull data back out of the array + * @element_nr: index of the element to fetch from the array + * + * Returns a pointer to the data at index @element_nr. Note + * that this is a copy of the data that was passed in. If you + * are using this to store pointers, you'll get back &ptr. + * + * Locking must be provided by the caller. + */ +void *flex_array_get(struct flex_array *fa, int element_nr) +{ + int part_nr = fa_element_to_part_nr(fa, element_nr); + struct flex_array_part *part; + int index; + + if (element_nr >= fa->total_nr_elements) + return NULL; + if (!fa->parts[part_nr]) + return NULL; + if (elements_fit_in_base(fa)) + part = (struct flex_array_part *)&fa->parts[0]; + else + part = fa->parts[part_nr]; + index = index_inside_part(fa, element_nr); + return &part->elements[index_inside_part(fa, element_nr)]; +} -- cgit v1.2.3 From 8da14b5fc32368f582df09fe9c0bec2507868583 Mon Sep 17 00:00:00 2001 From: Albin Tonnerre Date: Wed, 29 Jul 2009 15:04:18 -0700 Subject: drivers/serial/atmel_serial.c: fix compile when CONFIG_SERIAL_ATMEL=Y and CONFIG_SERIAL_ATMEL_CONSOLE=N When SERIAL_ATMEL_CONSOLE is disabled, ATMEL_CONSOLE_DEVICE is set to NULL, and trying to access ATMEL_CONSOLE_DEVICE->flags in atmel_serial_probe makes the compile fail. This fixes the issue by only accessing it if CONFIG_SERIAL_ATMEL_CONSOLE is defined Signed-off-by: Albin Tonnerre Signed-off-by: Haavard Skinnemoen Cc: Nicolas Ferre Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/serial/atmel_serial.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/serial/atmel_serial.c b/drivers/serial/atmel_serial.c index 338b15c0a548..607d43a31048 100644 --- a/drivers/serial/atmel_serial.c +++ b/drivers/serial/atmel_serial.c @@ -1551,6 +1551,7 @@ static int __devinit atmel_serial_probe(struct platform_device *pdev) if (ret) goto err_add_port; +#ifdef CONFIG_SERIAL_ATMEL_CONSOLE if (atmel_is_console_port(&port->uart) && ATMEL_CONSOLE_DEVICE->flags & CON_ENABLED) { /* @@ -1559,6 +1560,7 @@ static int __devinit atmel_serial_probe(struct platform_device *pdev) */ clk_disable(port->clk); } +#endif device_init_wakeup(&pdev->dev, 1); platform_set_drvdata(pdev, port); -- cgit v1.2.3 From 812ed032cdc8138b7546eecc996879756b92d801 Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Wed, 29 Jul 2009 15:04:19 -0700 Subject: uio: mark uio.h functions __KERNEL__ only To avoid userspace build failures such as: .../linux/uio.h:37: error: expected `=', `,', `;', `asm' or `__attribute__' before `iov_length' .../linux/uio.h:47: error: expected declaration specifiers or `...' before `size_t' move uio functions inside a __KERNEL__ block. Signed-off-by: Jiri Slaby Acked-by: Sam Ravnborg Cc: Alexander Viro Cc: Christoph Hellwig Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/linux/uio.h | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/include/linux/uio.h b/include/linux/uio.h index b7fe13883bdb..98c114323a8b 100644 --- a/include/linux/uio.h +++ b/include/linux/uio.h @@ -19,15 +19,6 @@ struct iovec __kernel_size_t iov_len; /* Must be size_t (1003.1g) */ }; -#ifdef __KERNEL__ - -struct kvec { - void *iov_base; /* and that should *never* hold a userland pointer */ - size_t iov_len; -}; - -#endif - /* * UIO_MAXIOV shall be at least 16 1003.1g (5.4.1.1) */ @@ -35,6 +26,13 @@ struct kvec { #define UIO_FASTIOV 8 #define UIO_MAXIOV 1024 +#ifdef __KERNEL__ + +struct kvec { + void *iov_base; /* and that should *never* hold a userland pointer */ + size_t iov_len; +}; + /* * Total number of bytes covered by an iovec. * @@ -53,5 +51,6 @@ static inline size_t iov_length(const struct iovec *iov, unsigned long nr_segs) } unsigned long iov_shorten(struct iovec *iov, unsigned long nr_segs, size_t to); +#endif #endif -- cgit v1.2.3 From 56d44f05177e69b757a01987827db8ef79fb759c Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Wed, 29 Jul 2009 15:04:20 -0700 Subject: MAINTAINERS: IA64 - pair P:/M: entries properly Signed-off-by: Joe Perches Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- MAINTAINERS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MAINTAINERS b/MAINTAINERS index ebc269152faf..5fe36a33ca63 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -2858,8 +2858,8 @@ S: Maintained IA64 (Itanium) PLATFORM P: Tony Luck -P: Fenghua Yu M: tony.luck@intel.com +P: Fenghua Yu M: fenghua.yu@intel.com L: linux-ia64@vger.kernel.org W: http://www.ia64-linux.org/ -- cgit v1.2.3 From 30e10993512c94daf0ab5cb4b512979aa1c85daf Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Wed, 29 Jul 2009 15:04:21 -0700 Subject: MAINTAINERS: Remove ivtv-user lists, add CX18 url Signed-off-by: Joe Perches Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- MAINTAINERS | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/MAINTAINERS b/MAINTAINERS index 5fe36a33ca63..104850879f2e 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1728,10 +1728,10 @@ M: hverkuil@xs4all.nl P: Andy Walls M: awalls@radix.net L: ivtv-devel@ivtvdriver.org -L: ivtv-users@ivtvdriver.org L: linux-media@vger.kernel.org T: git git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-2.6.git W: http://linuxtv.org +W: http://www.ivtvdriver.org/index.php/Cx18 S: Maintained F: Documentation/video4linux/cx18.txt F: drivers/media/video/cx18/ @@ -3283,7 +3283,6 @@ IVTV VIDEO4LINUX DRIVER P: Hans Verkuil M: hverkuil@xs4all.nl L: ivtv-devel@ivtvdriver.org -L: ivtv-users@ivtvdriver.org L: linux-media@vger.kernel.org T: git git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-2.6.git W: http://www.ivtvdriver.org -- cgit v1.2.3 From 4cbfbe256dc0b0491351bc5bea89f229cfae2284 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Wed, 29 Jul 2009 15:04:21 -0700 Subject: MAINTAINERS: QLGE 10Gb ETHERNET - pair P:/M: entries properly Signed-off-by: Joe Perches Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- MAINTAINERS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MAINTAINERS b/MAINTAINERS index 104850879f2e..a6d6420d5b1c 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -4821,8 +4821,8 @@ F: drivers/net/qla3xxx.* QLOGIC QLGE 10Gb ETHERNET DRIVER P: Ron Mercer -M: linux-driver@qlogic.com M: ron.mercer@qlogic.com +M: linux-driver@qlogic.com L: netdev@vger.kernel.org S: Supported F: drivers/net/qlge/ -- cgit v1.2.3 From 4fc26e36acce714ca26b576e3e6862887fa130d3 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Wed, 29 Jul 2009 15:04:22 -0700 Subject: MAINTAINERS: Use tabs in ACER ASPIRE ONE Signed-off-by: Joe Perches Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- MAINTAINERS | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/MAINTAINERS b/MAINTAINERS index a6d6420d5b1c..6504fb916a15 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -231,11 +231,11 @@ S: Maintained F: drivers/net/acenic* ACER ASPIRE ONE TEMPERATURE AND FAN DRIVER -P: Peter Feuerer -M: peter@piie.net -W: http://piie.net/?section=acerhdf -S: Maintained -F: drivers/platform/x86/acerhdf.c +P: Peter Feuerer +M: peter@piie.net +W: http://piie.net/?section=acerhdf +S: Maintained +F: drivers/platform/x86/acerhdf.c ACER WMI LAPTOP EXTRAS P: Carlos Corbacho -- cgit v1.2.3 From 5daa2963f8bd51c161d5b244e439e0c9fdec358b Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Wed, 29 Jul 2009 15:04:23 -0700 Subject: MAINTAINERS: Remove L: linux-kernel@vger.kernel.org from sections that should not have them. Signed-off-by: Joe Perches Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- MAINTAINERS | 5 ----- 1 file changed, 5 deletions(-) diff --git a/MAINTAINERS b/MAINTAINERS index 6504fb916a15..7d10f06d0889 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -2204,7 +2204,6 @@ F: drivers/scsi/lpfc/ ENE CB710 FLASH CARD READER DRIVER P: Michał Mirosław M: mirq-linux@rere.qmqm.pl -L: linux-kernel@vger.kernel.org S: Maintained F: drivers/misc/cb710/ F: drivers/mmc/host/cb710-mmc.* @@ -3480,13 +3479,11 @@ P: Vegard Nossum M: vegardno@ifi.uio.no P Pekka Enberg M: penberg@cs.helsinki.fi -L: linux-kernel@vger.kernel.org S: Maintained KMEMLEAK P: Catalin Marinas M: catalin.marinas@arm.com -L: linux-kernel@vger.kernel.org S: Maintained F: Documentation/kmemleak.txt F: include/linux/kmemleak.h @@ -4306,7 +4303,6 @@ F: drivers/video/omap/ OMAP MMC SUPPORT P: Jarkko Lavinen M: jarkko.lavinen@nokia.com -L: linux-kernel@vger.kernel.org L: linux-omap@vger.kernel.org S: Maintained F: drivers/mmc/host/*omap* @@ -4588,7 +4584,6 @@ P: Paul Mackerras M: paulus@samba.org P: Ingo Molnar M: mingo@elte.hu -L: linux-kernel@vger.kernel.org S: Supported PERSONALITY HANDLING -- cgit v1.2.3 From eb51b0349df8efccc37fc06aa25aecbd4d39551b Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Wed, 29 Jul 2009 15:04:23 -0700 Subject: MAINTAINERS: Move ARPD to CREDITS Jonathan Layes is hard to find. Signed-off-by: Joe Perches Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- CREDITS | 3 +++ MAINTAINERS | 6 ------ 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/CREDITS b/CREDITS index e76d300e9fe4..44c13d19e7ea 100644 --- a/CREDITS +++ b/CREDITS @@ -2006,6 +2006,9 @@ E: paul@laufernet.com D: Soundblaster driver fixes, ISAPnP quirk S: California, USA +N: Jonathan Layes +D: ARPD support + N: Tom Lees E: tom@lpsg.demon.co.uk W: http://www.lpsg.demon.co.uk/ diff --git a/MAINTAINERS b/MAINTAINERS index 7d10f06d0889..b42f1b11fa09 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -951,12 +951,6 @@ W: http://www.arm.linux.org.uk/ S: Maintained F: arch/arm/vfp/ -ARPD SUPPORT -P: Jonathan Layes -L: netdev@vger.kernel.org -S: Maintained -F: net/ipv4/arp.c - ASUS ACPI EXTRAS DRIVER P: Corentin Chary M: corentincj@iksaif.net -- cgit v1.2.3 From 24725d1ecf26ba05d74c1cc3ae7467b61a900421 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Wed, 29 Jul 2009 15:04:24 -0700 Subject: MAINTAINERS: Update KERNEL JANITORS Signed-off-by: Joe Perches Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- MAINTAINERS | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/MAINTAINERS b/MAINTAINERS index b42f1b11fa09..7a22e7068527 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -3373,10 +3373,9 @@ F: Makefile F: scripts/Makefile.* KERNEL JANITORS -P: Several L: kernel-janitors@vger.kernel.org W: http://www.kerneljanitors.org/ -S: Maintained +S: Odd fixes KERNEL NFSD, SUNRPC, AND LOCKD SERVERS P: J. Bruce Fields -- cgit v1.2.3 From cabaaf415cc9820cfbf2bc86308b94b78e31fe3e Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Wed, 29 Jul 2009 15:04:24 -0700 Subject: MAINTAINERS: Add PPS patterns Signed-off-by: Joe Perches Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- MAINTAINERS | 3 +++ 1 file changed, 3 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index 7a22e7068527..b1859597fa2a 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -4667,6 +4667,9 @@ M: giometti@enneenne.com W: http://wiki.enneenne.com/index.php/LinuxPPS_support L: linuxpps@ml.enneenne.com (subscribers-only) S: Maintained +F: Documentation/pps/ +F: drivers/pps/ +F: include/linux/pps*.h PREEMPTIBLE KERNEL P: Robert Love -- cgit v1.2.3 From a72f8024f4c9b06ff35d0bf6df479ea7fae4e2f8 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Wed, 29 Jul 2009 15:04:25 -0700 Subject: MAINTAINERS: USB Serial Digi Acceleport: use separate P: for Al Borchers Signed-off-by: Joe Perches Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- MAINTAINERS | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/MAINTAINERS b/MAINTAINERS index b1859597fa2a..b8d6bd355639 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -6105,8 +6105,9 @@ S: Maintained F: drivers/usb/serial/cyberjack.c USB SERIAL DIGI ACCELEPORT DRIVER -P: Peter Berger and Al Borchers +P: Peter Berger M: pberger@brimson.com +P: Al Borchers M: alborchers@steinerpoint.com L: linux-usb@vger.kernel.org S: Maintained -- cgit v1.2.3 From 5bee73ff71e17f5a807376e29653998755211ceb Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Wed, 29 Jul 2009 15:04:25 -0700 Subject: MAINTAINERS: INPUT: Add Dmitry's name to his email address Signed-off-by: Joe Perches Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- MAINTAINERS | 1 + 1 file changed, 1 insertion(+) diff --git a/MAINTAINERS b/MAINTAINERS index b8d6bd355639..6ef63194996a 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -2979,6 +2979,7 @@ F: include/linux/inotify.h INPUT (KEYBOARD, MOUSE, JOYSTICK, TOUCHSCREEN) DRIVERS P: Dmitry Torokhov M: dmitry.torokhov@gmail.com +P: Dmitry Torokhov M: dtor@mail.ru L: linux-input@vger.kernel.org T: git git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input.git -- cgit v1.2.3 From 9ae9a7f119a8def8e68d7f5ab0d96b3aba80accb Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Wed, 29 Jul 2009 15:04:26 -0700 Subject: MAINTAINERS: Remove CS461x sound card section Thomas Woller's email address bounces Nils Faerber isn't active Added Thomas Woller to CREDITS, Nils already has an entry Signed-off-by: Joe Perches Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- CREDITS | 3 +++ MAINTAINERS | 9 --------- 2 files changed, 3 insertions(+), 9 deletions(-) diff --git a/CREDITS b/CREDITS index 44c13d19e7ea..1a41bf4addd0 100644 --- a/CREDITS +++ b/CREDITS @@ -3805,6 +3805,9 @@ S: van Bronckhorststraat 12 S: 2612 XV Delft S: The Netherlands +N: Thomas Woller +D: CS461x Cirrus Logic sound driver + N: David Woodhouse E: dwmw2@infradead.org D: JFFS2 file system, Memory Technology Device subsystem, diff --git a/MAINTAINERS b/MAINTAINERS index 6ef63194996a..1b02be36d960 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1508,15 +1508,6 @@ L: alsa-devel@alsa-project.org (moderated for non-subscribers) S: Supported F: sound/soc/codecs/cs4270* -CIRRUS LOGIC CS4280/CS461x SOUNDDRIVER -P: Cirrus Logic Corporation (kernel 2.2 driver) -M: Cirrus Logic Corporation, Thomas Woller -P: Nils Faerber (port to kernel 2.4) -M: Nils Faerber -S: Maintained -F: Documentation/input/cs461x.txt -F: sound/pci/cs46xx/ - CLK API P: Russell King M: linux@arm.linux.org.uk -- cgit v1.2.3 From edf4b0a980bf481bbcef0977e2c7369f13f3428f Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Wed, 29 Jul 2009 15:04:26 -0700 Subject: MAINTAINERS: QLOGIC QLA2XXX - add Andrew Vasquez email address Signed-off-by: Joe Perches Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- MAINTAINERS | 1 + 1 file changed, 1 insertion(+) diff --git a/MAINTAINERS b/MAINTAINERS index 1b02be36d960..8ca15f6a4602 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -4788,6 +4788,7 @@ S: Maintained QLOGIC QLA2XXX FC-SCSI DRIVER P: Andrew Vasquez +M: andrew.vasquez@qlogic.com M: linux-driver@qlogic.com L: linux-scsi@vger.kernel.org S: Supported -- cgit v1.2.3 From 2bd1944899354b6f1328fe84886fa8f4d5918aef Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Wed, 29 Jul 2009 15:04:27 -0700 Subject: MAINTAINERS: QLOGIC QLA3XXX - Add Ron Mercer email address Signed-off-by: Joe Perches Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- MAINTAINERS | 1 + 1 file changed, 1 insertion(+) diff --git a/MAINTAINERS b/MAINTAINERS index 8ca15f6a4602..4daf259782ec 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -4797,6 +4797,7 @@ F: drivers/scsi/qla2xxx/ QLOGIC QLA3XXX NETWORK DRIVER P: Ron Mercer +M: ron.mercer@qlogic.com M: linux-driver@qlogic.com L: netdev@vger.kernel.org S: Supported -- cgit v1.2.3 From 82c4dfc76200055bd2ae600a08404c10df5f4ff6 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Wed, 29 Jul 2009 15:04:27 -0700 Subject: MAINTAINERS: Scott Murray is no longer with SomaNetworks Signed-off-by: Joe Perches Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- MAINTAINERS | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/MAINTAINERS b/MAINTAINERS index 4daf259782ec..e4e3471cd0ed 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1546,26 +1546,23 @@ F: fs/cifs/ COMPACTPCI HOTPLUG CORE P: Scott Murray -M: scottm@somanetworks.com M: scott@spiteful.org L: linux-pci@vger.kernel.org -S: Supported +S: Maintained F: drivers/pci/hotplug/cpci_hotplug* COMPACTPCI HOTPLUG ZIATECH ZT5550 DRIVER P: Scott Murray -M: scottm@somanetworks.com M: scott@spiteful.org L: linux-pci@vger.kernel.org -S: Supported +S: Maintained F: drivers/pci/hotplug/cpcihp_zt5550.* COMPACTPCI HOTPLUG GENERIC DRIVER P: Scott Murray -M: scottm@somanetworks.com M: scott@spiteful.org L: linux-pci@vger.kernel.org -S: Supported +S: Maintained F: drivers/pci/hotplug/cpcihp_generic.c COMPAL LAPTOP SUPPORT -- cgit v1.2.3 From 870020f93af2323a81f179091a0780dc1d5b916b Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Wed, 29 Jul 2009 15:04:28 -0700 Subject: scripts/get_maintainer.pl: Add -f directory use Don't require a specific file in a directory to be tested. Also Arnd Bergmann pointed out that the MAINTAINERS pattern requirement that directory patterns have a trailing slash was unnecessary and was likely to be error prone. Removed that requirement. Signed-off-by: Joe Perches Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- scripts/get_maintainer.pl | 23 +++++++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/scripts/get_maintainer.pl b/scripts/get_maintainer.pl index 3e733146cd51..7fc09fc91e8b 100755 --- a/scripts/get_maintainer.pl +++ b/scripts/get_maintainer.pl @@ -13,7 +13,7 @@ use strict; my $P = $0; -my $V = '0.16'; +my $V = '0.17'; use Getopt::Long qw(:config no_auto_abbrev); @@ -132,6 +132,10 @@ while () { $value =~ s@\.@\\\.@g; ##Convert . to \. $value =~ s/\*/\.\*/g; ##Convert * to .* $value =~ s/\?/\./g; ##Convert ? to . + ##if pattern is a directory and it lacks a trailing slash, add one + if ((-d $value)) { + $value =~ s@([^/])$@$1/@; + } } push(@typevalue, "$type:$value"); } elsif (!/^(\s)*$/) { @@ -146,8 +150,10 @@ close(MAINT); my @files = (); foreach my $file (@ARGV) { - next if ((-d $file)); - if (!(-f $file)) { + ##if $file is a directory and it lacks a trailing slash, add one + if ((-d $file)) { + $file =~ s@([^/])$@$1/@; + } elsif (!(-f $file)) { die "$P: file '${file}' not found\n"; } if ($from_filename) { @@ -292,7 +298,7 @@ sub file_match_pattern { sub usage { print < show version --help => show this help information +Notes: + Using "-f directory" may give unexpected results: + + Used with "--git", git signators for _all_ files in and below + directory are examined as git recurses directories. + Any specified X: (exclude) pattern matches are _not_ ignored. + Used with "--nogit", directory is used as a pattern match, + no individual file within the directory or subdirectory + is matched. EOT } -- cgit v1.2.3 From afa81ee13033de791c41c1d9333853504653939b Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Wed, 29 Jul 2009 15:04:28 -0700 Subject: get_maintainer.pl: Add git-min-percent option Allow an option to control the minimum percentage of sign-offs required before being considered a maintainer. git-min-percent has a default value of 5 Signed-off-by: Joe Perches Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- scripts/get_maintainer.pl | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/scripts/get_maintainer.pl b/scripts/get_maintainer.pl index 7fc09fc91e8b..61ef27564ed6 100755 --- a/scripts/get_maintainer.pl +++ b/scripts/get_maintainer.pl @@ -27,6 +27,7 @@ my $email_git = 1; my $email_git_penguin_chiefs = 0; my $email_git_min_signatures = 1; my $email_git_max_maintainers = 5; +my $email_git_min_percent = 5; my $email_git_since = "1-year-ago"; my $output_multiline = 1; my $output_separator = ", "; @@ -65,6 +66,7 @@ if (!GetOptions( 'git-chief-penguins!' => \$email_git_penguin_chiefs, 'git-min-signatures=i' => \$email_git_min_signatures, 'git-max-maintainers=i' => \$email_git_max_maintainers, + 'git-min-percent=i' => \$email_git_min_percent, 'git-since=s' => \$email_git_since, 'm!' => \$email_maintainer, 'n!' => \$email_usename, @@ -307,6 +309,7 @@ MAINTAINER field selection options: --git-chief-penguins => include ${penguin_chiefs} --git-min-signatures => number of signatures required (default: 1) --git-max-maintainers => maximum maintainers to add (default: 5) + --git-min-percent => minimum percentage of commits required (default: 0) --git-since => git history to use (default: 1-year-ago) --m => include maintainer(s) if any --n => include name 'Full Name ' @@ -497,6 +500,7 @@ sub recent_git_signoffs { my $output = ""; my $count = 0; my @lines = (); + my $total_sign_offs; if (which("git") eq "") { warn("$P: git not found. Add --nogit to options?\n"); @@ -520,17 +524,26 @@ sub recent_git_signoffs { $output =~ s/^\s*//gm; @lines = split("\n", $output); + + $total_sign_offs = 0; + foreach my $line (@lines) { + if ($line =~ m/([0-9]+)\s+(.*)/) { + $total_sign_offs += $1; + } else { + die("$P: Unexpected git output: ${line}\n"); + } + } + foreach my $line (@lines) { if ($line =~ m/([0-9]+)\s+(.*)/) { my $sign_offs = $1; $line = $2; $count++; if ($sign_offs < $email_git_min_signatures || - $count > $email_git_max_maintainers) { + $count > $email_git_max_maintainers || + $sign_offs * 100 / $total_sign_offs < $email_git_min_percent) { last; } - } else { - die("$P: Unexpected git output: ${line}\n"); } if ($line =~ m/(.+)<(.+)>/) { my $git_name = $1; -- cgit v1.2.3 From 3d202aeb7b7b33d5a5b2040ee5af5b309782941c Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Wed, 29 Jul 2009 15:04:29 -0700 Subject: get_maintainerpl-add-git-min-percent-option-fix Allow an option to control the minimum percentage of sign-offs required before being considered a maintainer. git-min-percent has a default value of 5 Signed-off-by: Joe Perches Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- scripts/get_maintainer.pl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/get_maintainer.pl b/scripts/get_maintainer.pl index 61ef27564ed6..278a45bd45a5 100755 --- a/scripts/get_maintainer.pl +++ b/scripts/get_maintainer.pl @@ -309,7 +309,7 @@ MAINTAINER field selection options: --git-chief-penguins => include ${penguin_chiefs} --git-min-signatures => number of signatures required (default: 1) --git-max-maintainers => maximum maintainers to add (default: 5) - --git-min-percent => minimum percentage of commits required (default: 0) + --git-min-percent => minimum percentage of commits required (default: 5) --git-since => git history to use (default: 1-year-ago) --m => include maintainer(s) if any --n => include name 'Full Name ' -- cgit v1.2.3 From 8b58be884a9fd650abb7f7adf3f885fb9cecd79d Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Wed, 29 Jul 2009 15:04:30 -0700 Subject: MAINTAINERS: coalesce name and email address lines Switch the MAINTAINERS email address format from P: Linus Torvalds M: torvalds@linux-foundation.org to M: Linus Torvalds Mainly to ease the copy-n-pasting of maitnainer addresses into email clients. The script to perform this operation: #! /bin/sh # # Change MAINTAINERS from # P: name # M: address # to: # M: name
# # Integrate P: and M: lines # perl -i -e 'local $/; while(<>) { s@P: ([^\n]+)\nM: ([^\n]+)\n@M: \1 <\2>\n@g; print; }' MAINTAINERS # # Quote names with periods, commas and parentheses # sed -r -i -e "s/^M: (.+)([\.,'\(])(.*) Acked-by: Pavel Machek Acked-by: Randy Dunlap Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- MAINTAINERS | 2721 ++++++++++++++++++++--------------------------------------- 1 file changed, 907 insertions(+), 1814 deletions(-) diff --git a/MAINTAINERS b/MAINTAINERS index e4e3471cd0ed..a013e963fc07 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -104,67 +104,58 @@ X: Files and directories that are NOT maintained, same rules as F: matches all files in and below net excluding net/ipv6/ 3C505 NETWORK DRIVER -P: Philip Blundell -M: philb@gnu.org +M: Philip Blundell L: netdev@vger.kernel.org S: Maintained F: drivers/net/3c505* 3C59X NETWORK DRIVER -P: Steffen Klassert -M: klassert@mathematik.tu-chemnitz.de +M: Steffen Klassert L: netdev@vger.kernel.org S: Maintained F: Documentation/networking/vortex.txt F: drivers/net/3c59x.c 3CR990 NETWORK DRIVER -P: David Dillow -M: dave@thedillows.org +M: David Dillow L: netdev@vger.kernel.org S: Maintained F: drivers/net/typhoon* 3W-9XXX SATA-RAID CONTROLLER DRIVER -P: Adam Radford -M: linuxraid@amcc.com +M: Adam Radford L: linux-scsi@vger.kernel.org W: http://www.amcc.com S: Supported F: drivers/scsi/3w-9xxx* 3W-XXXX ATA-RAID CONTROLLER DRIVER -P: Adam Radford -M: linuxraid@amcc.com +M: Adam Radford L: linux-scsi@vger.kernel.org W: http://www.amcc.com S: Supported F: drivers/scsi/3w-xxxx* 53C700 AND 53C700-66 SCSI DRIVER -P: James E.J. Bottomley -M: James.Bottomley@HansenPartnership.com +M: "James E.J. Bottomley" L: linux-scsi@vger.kernel.org S: Maintained F: drivers/scsi/53c700* 6PACK NETWORK DRIVER FOR AX.25 -P: Andreas Koensgen -M: ajk@comnets.uni-bremen.de +M: Andreas Koensgen L: linux-hams@vger.kernel.org S: Maintained F: drivers/net/hamradio/6pack.c 8169 10/100/1000 GIGABIT ETHERNET DRIVER -P: Francois Romieu -M: romieu@fr.zoreil.com +M: Francois Romieu L: netdev@vger.kernel.org S: Maintained F: drivers/net/r8169.c 8250/16?50 (AND CLONE UARTS) SERIAL DRIVER -P: Alan Cox -M: alan@lxorguk.ukuu.org.uk +M: Alan Cox L: linux-serial@vger.kernel.org W: http://serial.sourceforge.net S: Odd Fixes @@ -172,20 +163,16 @@ F: drivers/serial/8250* F: include/linux/serial_8250.h 8390 NETWORK DRIVERS [WD80x3/SMC-ELITE, SMC-ULTRA, NE2000, 3C503, etc.] -P: Paul Gortmaker -M: p_gortmaker@yahoo.com +M: Paul Gortmaker L: netdev@vger.kernel.org S: Maintained F: drivers/net/*8390* F: drivers/net/ax88796.c 9P FILE SYSTEM -P: Eric Van Hensbergen -M: ericvh@gmail.com -P: Ron Minnich -M: rminnich@sandia.gov -P: Latchesar Ionkov -M: lucho@ionkov.net +M: Eric Van Hensbergen +M: Ron Minnich +M: Latchesar Ionkov L: v9fs-developer@lists.sourceforge.net W: http://swik.net/v9fs T: git git://git.kernel.org/pub/scm/linux/kernel/ericvh/v9fs.git @@ -194,15 +181,13 @@ F: Documentation/filesystems/9p.txt F: fs/9p/ A2232 SERIAL BOARD DRIVER -P: Enver Haase -M: A2232@gmx.net +M: Enver Haase L: linux-m68k@lists.linux-m68k.org S: Maintained F: drivers/char/ser_a2232* AACRAID SCSI RAID DRIVER -P: Adaptec OEM Raid Solutions -M: aacraid@adaptec.com +M: Adaptec OEM Raid Solutions L: linux-scsi@vger.kernel.org W: http://www.adaptec.com/ S: Supported @@ -210,44 +195,38 @@ F: Documentation/scsi/aacraid.txt F: drivers/scsi/aacraid/ ABIT UGURU 1,2 HARDWARE MONITOR DRIVER -P: Hans de Goede -M: j.w.r.degoede@hhs.nl +M: Hans de Goede L: lm-sensors@lm-sensors.org S: Maintained F: drivers/hwmon/abituguru.c ABIT UGURU 3 HARDWARE MONITOR DRIVER -P: Alistair John Strachan -M: alistair@devzero.co.uk +M: Alistair John Strachan L: lm-sensors@lm-sensors.org S: Maintained F: drivers/hwmon/abituguru3.c ACENIC DRIVER -P: Jes Sorensen -M: jes@trained-monkey.org +M: Jes Sorensen L: linux-acenic@sunsite.dk S: Maintained F: drivers/net/acenic* ACER ASPIRE ONE TEMPERATURE AND FAN DRIVER -P: Peter Feuerer -M: peter@piie.net +M: Peter Feuerer W: http://piie.net/?section=acerhdf S: Maintained F: drivers/platform/x86/acerhdf.c ACER WMI LAPTOP EXTRAS -P: Carlos Corbacho -M: carlos@strangeworlds.co.uk +M: Carlos Corbacho L: aceracpi@googlegroups.com (subscribers-only) W: http://code.google.com/p/aceracpi S: Maintained F: drivers/platform/x86/acer-wmi.c ACPI -P: Len Brown -M: lenb@kernel.org +M: Len Brown L: linux-acpi@vger.kernel.org W: http://www.lesswatts.org/projects/acpi/ T: git git://git.kernel.org/pub/scm/linux/kernel/git/lenb/linux-acpi-2.6.git @@ -257,8 +236,7 @@ F: drivers/pnp/pnpacpi/ F: include/linux/acpi.h ACPI BATTERY DRIVERS -P: Alexey Starikovskiy -M: astarikovskiy@suse.de +M: Alexey Starikovskiy L: linux-acpi@vger.kernel.org W: http://www.lesswatts.org/projects/acpi/ S: Supported @@ -266,80 +244,69 @@ F: drivers/acpi/battery.c F: drivers/acpi/*sbs* ACPI EC DRIVER -P: Alexey Starikovskiy -M: astarikovskiy@suse.de +M: Alexey Starikovskiy L: linux-acpi@vger.kernel.org W: http://www.lesswatts.org/projects/acpi/ S: Supported F: drivers/acpi/ec.c ACPI FAN DRIVER -P: Zhang Rui -M: rui.zhang@intel.com +M: Zhang Rui L: linux-acpi@vger.kernel.org W: http://www.lesswatts.org/projects/acpi/ S: Supported F: drivers/acpi/fan.c ACPI PCI HOTPLUG DRIVER -P: Kristen Carlson Accardi -M: kristen.c.accardi@intel.com +M: Kristen Carlson Accardi L: linux-pci@vger.kernel.org S: Supported F: drivers/pci/hotplug/acpi* ACPI THERMAL DRIVER -P: Zhang Rui -M: rui.zhang@intel.com +M: Zhang Rui L: linux-acpi@vger.kernel.org W: http://www.lesswatts.org/projects/acpi/ S: Supported F: drivers/acpi/*thermal* ACPI VIDEO DRIVER -P: Zhang Rui -M: rui.zhang@intel.com +M: Zhang Rui L: linux-acpi@vger.kernel.org W: http://www.lesswatts.org/projects/acpi/ S: Supported F: drivers/acpi/video.c ACPI WMI DRIVER -P: Carlos Corbacho -M: carlos@strangeworlds.co.uk +M: Carlos Corbacho L: linux-acpi@vger.kernel.org W: http://www.lesswatts.org/projects/acpi/ S: Maintained F: drivers/platform/x86/wmi.c AD1889 ALSA SOUND DRIVER -P: Kyle McMartin -M: kyle@mcmartin.ca -P: Thibaut Varene -M: T-Bone@parisc-linux.org +M: Kyle McMartin +M: Thibaut Varene W: http://wiki.parisc-linux.org/AD1889 L: linux-parisc@vger.kernel.org S: Maintained F: sound/pci/ad1889.* ADM1025 HARDWARE MONITOR DRIVER -P: Jean Delvare -M: khali@linux-fr.org +M: Jean Delvare L: lm-sensors@lm-sensors.org S: Maintained F: Documentation/hwmon/adm1025 F: drivers/hwmon/adm1025.c ADM1029 HARDWARE MONITOR DRIVER -P: Corentin Labbe -M: corentin.labbe@geomatys.fr +M: Corentin Labbe L: lm-sensors@lm-sensors.org S: Maintained F: drivers/hwmon/adm1029.c ADM8211 WIRELESS DRIVER -P: Michael Wu -M: flamingice@sourmilk.net +M: Michael Wu L: linux-wireless@vger.kernel.org W: http://linuxwireless.org/ T: git git://git.kernel.org/pub/scm/linux/kernel/git/mwu/mac80211-drivers.git @@ -347,35 +314,30 @@ S: Maintained F: drivers/net/wireless/adm8211.* ADT746X FAN DRIVER -P: Colin Leroy -M: colin@colino.net +M: Colin Leroy S: Maintained F: drivers/macintosh/therm_adt746x.c ADVANSYS SCSI DRIVER -P: Matthew Wilcox -M: matthew@wil.cx +M: Matthew Wilcox L: linux-scsi@vger.kernel.org S: Maintained F: Documentation/scsi/advansys.txt F: drivers/scsi/advansys.c AEDSP16 DRIVER -P: Riccardo Facchetti -M: fizban@tin.it +M: Riccardo Facchetti S: Maintained F: sound/oss/aedsp16.c AFFS FILE SYSTEM -P: Roman Zippel -M: zippel@linux-m68k.org +M: Roman Zippel S: Maintained F: Documentation/filesystems/affs.txt F: fs/affs/ AFS FILESYSTEM & AF_RXRPC SOCKET DOMAIN -P: David Howells -M: dhowells@redhat.com +M: David Howells L: linux-afs@lists.infradead.org S: Supported F: fs/afs/ @@ -383,40 +345,35 @@ F: include/net/af_rxrpc.h F: net/rxrpc/af_rxrpc.c AGPGART DRIVER -P: David Airlie -M: airlied@linux.ie +M: David Airlie T: git git://git.kernel.org/pub/scm/linux/kernel/git/airlied/drm-2.6.git S: Maintained F: drivers/char/agp/ F: include/linux/agp* AHA152X SCSI DRIVER -P: Juergen E. Fischer -M: fischer@norbit.de +M: "Juergen E. Fischer" L: linux-scsi@vger.kernel.org S: Maintained F: drivers/scsi/aha152x* F: drivers/scsi/pcmcia/aha152x* AIC7XXX / AIC79XX SCSI DRIVER -P: Hannes Reinecke -M: hare@suse.de +M: Hannes Reinecke L: linux-scsi@vger.kernel.org S: Maintained F: drivers/scsi/aic7xxx/ F: drivers/scsi/aic7xxx_old/ AIO -P: Benjamin LaHaise -M: bcrl@kvack.org +M: Benjamin LaHaise L: linux-aio@kvack.org S: Supported F: fs/aio.c F: include/linux/*aio*.h ALCATEL SPEEDTOUCH USB DRIVER -P: Duncan Sands -M: duncan.sands@free.fr +M: Duncan Sands L: linux-usb@vger.kernel.org W: http://www.linux-usb.org/SpeedTouch/ S: Maintained @@ -424,32 +381,27 @@ F: drivers/usb/atm/speedtch.c F: drivers/usb/atm/usbatm.c ALCHEMY AU1XX0 MMC DRIVER -P: Manuel Lauss -M: manuel.lauss@gmail.com +M: Manuel Lauss S: Maintained F: drivers/mmc/host/au1xmmc.c ALI1563 I2C DRIVER -P: Rudolf Marek -M: r.marek@assembler.cz +M: Rudolf Marek L: linux-i2c@vger.kernel.org S: Maintained F: Documentation/i2c/busses/i2c-ali1563 F: drivers/i2c/busses/i2c-ali1563.c ALPHA PORT -P: Richard Henderson -M: rth@twiddle.net +M: Richard Henderson S: Odd Fixes for 2.4; Maintained for 2.6. -P: Ivan Kokshaysky -M: ink@jurassic.park.msu.ru +M: Ivan Kokshaysky S: Maintained for 2.4; PCI support for 2.6. L: linux-alpha@vger.kernel.org F: arch/alpha/ AMD GEODE CS5536 USB DEVICE CONTROLLER DRIVER -P: Thomas Dahlmann -M: dahlmann.thomas@arcor.de +M: Thomas Dahlmann L: linux-geode@lists.infradead.org (moderated for non-subscribers) S: Supported F: drivers/usb/gadget/amd5536udc.* @@ -466,8 +418,7 @@ F: drivers/video/geode/ F: arch/x86/include/asm/geode.h AMD IOMMU (AMD-VI) -P: Joerg Roedel -M: joerg.roedel@amd.com +M: Joerg Roedel L: iommu@lists.linux-foundation.org T: git git://git.kernel.org/pub/scm/linux/kernel/git/joro/linux-2.6-iommu.git S: Supported @@ -475,40 +426,33 @@ F: arch/x86/kernel/amd_iommu*.c F: arch/x86/include/asm/amd_iommu*.h AMD MICROCODE UPDATE SUPPORT -P: Andreas Herrmann -M: andreas.herrmann3@amd.com +M: Andreas Herrmann L: amd64-microcode@amd64.org S: Supported F: arch/x86/kernel/microcode_amd.c AMS (Apple Motion Sensor) DRIVER -P: Stelian Pop -M: stelian@popies.net -P: Michael Hanselmann -M: linux-kernel@hansmi.ch +M: Stelian Pop +M: Michael Hanselmann S: Supported F: drivers/hwmon/ams/ AMSO1100 RNIC DRIVER -P: Tom Tucker -M: tom@opengridcomputing.com -P: Steve Wise -M: swise@opengridcomputing.com +M: Tom Tucker +M: Steve Wise L: general@lists.openfabrics.org S: Maintained F: drivers/infiniband/hw/amso1100/ AOA (Apple Onboard Audio) ALSA DRIVER -P: Johannes Berg -M: johannes@sipsolutions.net +M: Johannes Berg L: linuxppc-dev@ozlabs.org L: alsa-devel@alsa-project.org (moderated for non-subscribers) S: Maintained F: sound/aoa/ APM DRIVER -P: Stephen Rothwell -M: sfr@canb.auug.org.au +M: Stephen Rothwell L: linux-laptop@vger.kernel.org W: http://www.canb.auug.org.au/~sfr/ S: Supported @@ -516,51 +460,44 @@ F: arch/x86/kernel/apm_32.c F: include/linux/apm_bios.h APPLE BCM5974 MULTITOUCH DRIVER -P: Henrik Rydberg -M: rydberg@euromail.se +M: Henrik Rydberg L: linux-input@vger.kernel.org S: Maintained F: drivers/input/mouse/bcm5974.c APPLE SMC DRIVER -P: Nicolas Boichat -M: nicolas@boichat.ch +M: Nicolas Boichat L: mactel-linux-devel@lists.sourceforge.net S: Maintained F: drivers/hwmon/applesmc.c APPLETALK NETWORK LAYER -P: Arnaldo Carvalho de Melo -M: acme@ghostprotocols.net +M: Arnaldo Carvalho de Melo S: Maintained F: drivers/net/appletalk/ F: net/appletalk/ APPLETOUCH TOUCHPAD DRIVER -P: Johannes Berg -M: johannes@sipsolutions.net +M: Johannes Berg L: linux-input@vger.kernel.org S: Maintained F: Documentation/input/appletouch.txt F: drivers/input/mouse/appletouch.c ARC FRAMEBUFFER DRIVER -P: Jaya Kumar -M: jayalk@intworks.biz +M: Jaya Kumar S: Maintained F: drivers/video/arcfb.c F: drivers/video/fb_defio.c ARM MFM AND FLOPPY DRIVERS -P: Ian Molton -M: spyro@f2s.com +M: Ian Molton S: Maintained F: arch/arm/lib/floppydma.S F: arch/arm/include/asm/floppy.h ARM PORT -P: Russell King -M: linux@arm.linux.org.uk +M: Russell King L: linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only) W: http://www.arm.linux.org.uk/ S: Maintained @@ -571,79 +508,67 @@ S: Orphan F: drivers/mmc/host/mmci.* ARM/ADI ROADRUNNER MACHINE SUPPORT -P: Lennert Buytenhek -M: kernel@wantstofly.org +M: Lennert Buytenhek L: linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only) S: Maintained F: arch/arm/mach-ixp23xx/ F: arch/arm/mach-ixp23xx/include/mach/ ARM/ADS SPHERE MACHINE SUPPORT -P: Lennert Buytenhek -M: kernel@wantstofly.org +M: Lennert Buytenhek L: linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only) S: Maintained ARM/AFEB9260 MACHINE SUPPORT -P: Sergey Lapin -M: slapin@ossfans.org +M: Sergey Lapin L: linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only) S: Maintained ARM/AJECO 1ARM MACHINE SUPPORT -P: Lennert Buytenhek -M: kernel@wantstofly.org +M: Lennert Buytenhek L: linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only) S: Maintained ARM/ATMEL AT91RM9200 ARM ARCHITECTURE -P: Andrew Victor -M: linux@maxim.org.za +M: Andrew Victor L: linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only) W: http://maxim.org.za/at91_26.html S: Maintained ARM/CIRRUS LOGIC EP93XX ARM ARCHITECTURE -P: Lennert Buytenhek -M: kernel@wantstofly.org +M: Lennert Buytenhek L: linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only) S: Maintained ARM/CIRRUS LOGIC EDB9315A MACHINE SUPPORT -P: Lennert Buytenhek -M: kernel@wantstofly.org +M: Lennert Buytenhek L: linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only) S: Maintained ARM/CLKDEV SUPPORT -P: Russell King -M: linux@arm.linux.org.uk +M: Russell King L: linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only) F: arch/arm/common/clkdev.c F: arch/arm/include/asm/clkdev.h ARM/COMPULAB CM-X270/EM-X270 and CM-X300 MACHINE SUPPORT -P: Mike Rapoport -M: mike@compulab.co.il +M: Mike Rapoport L: linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only) S: Maintained ARM/CORGI MACHINE SUPPORT -P: Richard Purdie -M: rpurdie@rpsys.net +M: Richard Purdie S: Maintained ARM/CORTINA SYSTEMS GEMINI ARM ARCHITECTURE -P: Paulius Zaleckas -M: paulius.zaleckas@teltonika.lt +M: Paulius Zaleckas L: linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only) T: git git://gitorious.org/linux-gemini/mainline.git S: Maintained F: arch/arm/mach-gemini/ ARM/EBSA110 MACHINE SUPPORT -P: Russell King -M: linux@arm.linux.org.uk +M: Russell King L: linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only) W: http://www.arm.linux.org.uk/ S: Maintained @@ -651,12 +576,9 @@ F: arch/arm/mach-ebsa110/ F: drivers/net/arm/am79c961a.* ARM/EZX SMARTPHONES (A780, A910, A1200, E680, ROKR E2 and ROKR E6) -P: Daniel Ribeiro -M: drwyrm@gmail.com -P: Stefan Schmidt -M: stefan@openezx.org -P: Harald Welte -M: laforge@openezx.org +M: Daniel Ribeiro +M: Stefan Schmidt +M: Harald Welte L: openezx-devel@lists.openezx.org (subscribers-only) W: http://www.openezx.org/ S: Maintained @@ -664,15 +586,13 @@ T: topgit git://git.openezx.org/openezx.git F: arch/arm/mach-pxa/ezx.c ARM/FARADAY FA526 PORT -P: Paulius Zaleckas -M: paulius.zaleckas@teltonika.lt +M: Paulius Zaleckas L: linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only) S: Maintained F: arch/arm/mm/*-fa* ARM/FOOTBRIDGE ARCHITECTURE -P: Russell King -M: linux@arm.linux.org.uk +M: Russell King L: linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only) W: http://www.arm.linux.org.uk/ S: Maintained @@ -680,175 +600,143 @@ F: arch/arm/include/asm/hardware/dec21285.h F: arch/arm/mach-footbridge/ ARM/FREESCALE IMX / MXC ARM ARCHITECTURE -P: Sascha Hauer -M: kernel@pengutronix.de +M: Sascha Hauer L: linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only) S: Maintained ARM/GLOMATION GESBC9312SX MACHINE SUPPORT -P: Lennert Buytenhek -M: kernel@wantstofly.org +M: Lennert Buytenhek L: linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only) S: Maintained ARM/GUMSTIX MACHINE SUPPORT -P: Steve Sakoman -M: sakoman@gmail.com +M: Steve Sakoman L: linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only) S: Maintained ARM/H4700 (HP IPAQ HX4700) MACHINE SUPPORT -P: Philipp Zabel -M: philipp.zabel@gmail.com +M: Philipp Zabel S: Maintained F: arch/arm/mach-pxa/hx4700.c F: arch/arm/mach-pxa/include/mach/hx4700.h ARM/HP JORNADA 7XX MACHINE SUPPORT -P: Kristoffer Ericson -M: kristoffer.ericson@gmail.com +M: Kristoffer Ericson W: www.jlime.com S: Maintained ARM/INTEL IOP32X ARM ARCHITECTURE -P: Lennert Buytenhek -M: kernel@wantstofly.org -P: Dan Williams -M: dan.j.williams@intel.com +M: Lennert Buytenhek +M: Dan Williams L: linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only) S: Supported ARM/INTEL IOP33X ARM ARCHITECTURE -P: Dan Williams -M: dan.j.williams@intel.com +M: Dan Williams L: linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only) S: Supported ARM/INTEL IOP13XX ARM ARCHITECTURE -P: Lennert Buytenhek -M: kernel@wantstofly.org -P: Dan Williams -M: dan.j.williams@intel.com +M: Lennert Buytenhek +M: Dan Williams L: linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only) S: Supported ARM/INTEL IQ81342EX MACHINE SUPPORT -P: Lennert Buytenhek -M: kernel@wantstofly.org -P: Dan Williams -M: dan.j.williams@intel.com +M: Lennert Buytenhek +M: Dan Williams L: linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only) S: Supported ARM/INTEL IXP2000 ARM ARCHITECTURE -P: Lennert Buytenhek -M: kernel@wantstofly.org +M: Lennert Buytenhek L: linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only) S: Maintained ARM/INTEL IXDP2850 MACHINE SUPPORT -P: Lennert Buytenhek -M: kernel@wantstofly.org +M: Lennert Buytenhek L: linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only) S: Maintained ARM/INTEL IXP23XX ARM ARCHITECTURE -P: Lennert Buytenhek -M: kernel@wantstofly.org +M: Lennert Buytenhek L: linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only) S: Maintained ARM/INTEL XSC3 (MANZANO) ARM CORE -P: Lennert Buytenhek -M: kernel@wantstofly.org -P: Dan Williams -M: dan.j.williams@intel.com +M: Lennert Buytenhek +M: Dan Williams L: linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only) S: Supported ARM/IP FABRICS DOUBLE ESPRESSO MACHINE SUPPORT -P: Lennert Buytenhek -M: kernel@wantstofly.org +M: Lennert Buytenhek L: linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only) S: Maintained ARM/LOGICPD PXA270 MACHINE SUPPORT -P: Lennert Buytenhek -M: kernel@wantstofly.org +M: Lennert Buytenhek L: linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only) S: Maintained ARM/MAGICIAN MACHINE SUPPORT -P: Philipp Zabel -M: philipp.zabel@gmail.com +M: Philipp Zabel S: Maintained ARM/MIOA701 MACHINE SUPPORT -P: Robert Jarzmik -M: robert.jarzmik@free.fr +M: Robert Jarzmik L: linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only) F: arch/arm/mach-pxa/mioa701.c S: Maintained ARM/NEC MOBILEPRO 900/c MACHINE SUPPORT -P: Michael Petchkovsky -M: mkpetch@internode.on.net +M: Michael Petchkovsky S: Maintained ARM/OPENMOKO NEO FREERUNNER (GTA02) MACHINE SUPPORT -P: Nelson Castillo -M: arhuaco@freaks-unidos.net +M: Nelson Castillo L: openmoko-kernel@lists.openmoko.org (subscribers-only) W: http://wiki.openmoko.org/wiki/Neo_FreeRunner S: Supported ARM/TOSA MACHINE SUPPORT -P: Dmitry Eremin-Solenikov -M: dbaryshkov@gmail.com -P: Dirk Opfer -M: dirk@opfer-online.de +M: Dmitry Eremin-Solenikov +M: Dirk Opfer S: Maintained ARM/PALMTX,PALMT5,PALMLD,PALMTE2 SUPPORT -P: Marek Vasut -M: marek.vasut@gmail.com +M: Marek Vasut W: http://hackndev.com S: Maintained ARM/PALM TREO 680 SUPPORT -P: Tomas Cech -M: sleep_walker@suse.cz +M: Tomas Cech W: http://hackndev.com S: Maintained ARM/PALMZ72 SUPPORT -P: Sergey Lapin -M: slapin@ossfans.org +M: Sergey Lapin W: http://hackndev.com S: Maintained ARM/PLEB SUPPORT -P: Peter Chubb -M: pleb@gelato.unsw.edu.au +M: Peter Chubb W: http://www.disy.cse.unsw.edu.au/Hardware/PLEB S: Maintained ARM/PT DIGITAL BOARD PORT -P: Stefan Eletzhofer -M: stefan.eletzhofer@eletztrick.de +M: Stefan Eletzhofer L: linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only) W: http://www.arm.linux.org.uk/ S: Maintained ARM/RADISYS ENP2611 MACHINE SUPPORT -P: Lennert Buytenhek -M: kernel@wantstofly.org +M: Lennert Buytenhek L: linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only) S: Maintained ARM/RISCPC ARCHITECTURE -P: Russell King -M: linux@arm.linux.org.uk +M: Russell King L: linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only) W: http://www.arm.linux.org.uk/ S: Maintained @@ -862,14 +750,12 @@ F: drivers/net/arm/ether* F: drivers/scsi/arm/ ARM/SHARK MACHINE SUPPORT -P: Alexander Schulz -M: alex@shark-linux.de +M: Alexander Schulz W: http://www.shark-linux.de/shark.html S: Maintained ARM/SAMSUNG ARM ARCHITECTURES -P: Ben Dooks -M: ben-linux@fluff.org +M: Ben Dooks L: linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only) W: http://www.fluff.org/ben/linux/ S: Maintained @@ -877,85 +763,73 @@ F: arch/arm/plat-s3c/ F: arch/arm/plat-s3c24xx/ ARM/S3C2410 ARM ARCHITECTURE -P: Ben Dooks -M: ben-linux@fluff.org +M: Ben Dooks L: linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only) W: http://www.fluff.org/ben/linux/ S: Maintained F: arch/arm/mach-s3c2410/ ARM/S3C2440 ARM ARCHITECTURE -P: Ben Dooks -M: ben-linux@fluff.org +M: Ben Dooks L: linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only) W: http://www.fluff.org/ben/linux/ S: Maintained F: arch/arm/mach-s3c2440/ ARM/S3C2442 ARM ARCHITECTURE -P: Ben Dooks -M: ben-linux@fluff.org +M: Ben Dooks L: linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only) W: http://www.fluff.org/ben/linux/ S: Maintained F: arch/arm/mach-s3c2442/ ARM/S3C2443 ARM ARCHITECTURE -P: Ben Dooks -M: ben-linux@fluff.org +M: Ben Dooks L: linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only) W: http://www.fluff.org/ben/linux/ S: Maintained F: arch/arm/mach-s3c2443/ ARM/S3C6400 ARM ARCHITECTURE -P: Ben Dooks -M: ben-linux@fluff.org +M: Ben Dooks L: linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only) W: http://www.fluff.org/ben/linux/ S: Maintained F: arch/arm/mach-s3c6400/ ARM/S3C6410 ARM ARCHITECTURE -P: Ben Dooks -M: ben-linux@fluff.org +M: Ben Dooks L: linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only) W: http://www.fluff.org/ben/linux/ S: Maintained F: arch/arm/mach-s3c6410/ ARM/TECHNOLOGIC SYSTEMS TS7250 MACHINE SUPPORT -P: Lennert Buytenhek -M: kernel@wantstofly.org +M: Lennert Buytenhek L: linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only) S: Maintained ARM/THECUS N2100 MACHINE SUPPORT -P: Lennert Buytenhek -M: kernel@wantstofly.org +M: Lennert Buytenhek L: linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only) S: Maintained ARM/NUVOTON W90X900 ARM ARCHITECTURE -P: Wan ZongShun -M: mcuos.com@gmail.com +M: Wan ZongShun L: linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only) W: http://www.mcuos.com S: Maintained ARM/VFP SUPPORT -P: Russell King -M: linux@arm.linux.org.uk +M: Russell King L: linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only) W: http://www.arm.linux.org.uk/ S: Maintained F: arch/arm/vfp/ ASUS ACPI EXTRAS DRIVER -P: Corentin Chary -M: corentincj@iksaif.net -P: Karol Kozimor -M: sziwan@users.sourceforge.net +M: Corentin Chary +M: Karol Kozimor L: acpi4asus-user@lists.sourceforge.net W: http://acpi4asus.sf.net S: Maintained @@ -963,25 +837,21 @@ F: arch/x86/kernel/acpi/boot.c F: drivers/platform/x86/asus_acpi.c ASUS ASB100 HARDWARE MONITOR DRIVER -P: Mark M. Hoffman -M: mhoffman@lightlink.com +M: "Mark M. Hoffman" L: lm-sensors@lm-sensors.org S: Maintained F: drivers/hwmon/asb100.c ASUS LAPTOP EXTRAS DRIVER -P: Corentin Chary -M: corentincj@iksaif.net +M: Corentin Chary L: acpi4asus-user@lists.sourceforge.net W: http://acpi4asus.sf.net S: Maintained F: drivers/platform/x86/asus-laptop.c ASYNCHRONOUS TRANSFERS/TRANSFORMS (IOAT) API -P: Dan Williams -M: dan.j.williams@intel.com -P: Maciej Sosnowski -M: maciej.sosnowski@intel.com +M: Dan Williams +M: Maciej Sosnowski W: http://sourceforge.net/projects/xscaleiop S: Supported F: Documentation/crypto/async-tx-api.txt @@ -991,64 +861,49 @@ F: include/linux/dmaengine.h F: include/linux/async_tx.h ATA OVER ETHERNET (AOE) DRIVER -P: Ed L. Cashin -M: ecashin@coraid.com +M: "Ed L. Cashin" W: http://www.coraid.com/support/linux S: Supported F: Documentation/aoe/ F: drivers/block/aoe/ ATHEROS ATH5K WIRELESS DRIVER -P: Jiri Slaby -M: jirislaby@gmail.com -P: Nick Kossifidis -M: mickflemm@gmail.com -P: Luis R. Rodriguez -M: lrodriguez@atheros.com -P: Bob Copeland -M: me@bobcopeland.com +M: Jiri Slaby +M: Nick Kossifidis +M: "Luis R. Rodriguez" +M: Bob Copeland L: linux-wireless@vger.kernel.org L: ath5k-devel@lists.ath5k.org S: Maintained F: drivers/net/wireless/ath/ath5k/ ATHEROS ATH9K WIRELESS DRIVER -P: Luis R. Rodriguez -M: lrodriguez@atheros.com -P: Jouni Malinen -M: jmalinen@atheros.com -P: Sujith Manoharan -M: Sujith.Manoharan@atheros.com -P: Vasanthakumar Thiagarajan -M: vasanth@atheros.com -P: Senthil Balasubramanian -M: senthilkumar@atheros.com +M: "Luis R. Rodriguez" +M: Jouni Malinen +M: Sujith Manoharan +M: Vasanthakumar Thiagarajan +M: Senthil Balasubramanian L: linux-wireless@vger.kernel.org L: ath9k-devel@lists.ath9k.org S: Supported F: drivers/net/wireless/ath/ath9k/ ATHEROS AR9170 WIRELESS DRIVER -P: Christian Lamparter -M: chunkeey@web.de +M: Christian Lamparter L: linux-wireless@vger.kernel.org W: http://wireless.kernel.org/en/users/Drivers/ar9170 S: Maintained F: drivers/net/wireless/ath/ar9170/ ATI_REMOTE2 DRIVER -P: Ville Syrjala -M: syrjala@sci.fi +M: Ville Syrjala S: Maintained F: drivers/input/misc/ati_remote2.c ATLX ETHERNET DRIVERS -P: Jay Cliburn -M: jcliburn@gmail.com -P: Chris Snook -M: csnook@redhat.com -P: Jie Yang -M: jie.yang@atheros.com +M: Jay Cliburn +M: Chris Snook +M: Jie Yang L: atl1-devel@lists.sourceforge.net W: http://sourceforge.net/projects/atl1 W: http://atl1.sourceforge.net @@ -1056,8 +911,7 @@ S: Maintained F: drivers/net/atlx/ ATM -P: Chas Williams -M: chas@cmf.nrl.navy.mil +M: Chas Williams L: linux-atm-general@lists.sourceforge.net (subscribers-only) L: netdev@vger.kernel.org W: http://linux-atm.sourceforge.net @@ -1066,8 +920,7 @@ F: drivers/atm/ F: include/linux/atm* ATMEL AT91 MCI DRIVER -P: Nicolas Ferre -M: nicolas.ferre@atmel.com +M: Nicolas Ferre L: linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only) W: http://www.atmel.com/products/AT91/ W: http://www.at91.com/ @@ -1075,49 +928,42 @@ S: Maintained F: drivers/mmc/host/at91_mci.c ATMEL AT91 / AT32 MCI DRIVER -P: Nicolas Ferre -M: nicolas.ferre@atmel.com +M: Nicolas Ferre S: Maintained F: drivers/mmc/host/atmel-mci.c F: drivers/mmc/host/atmel-mci-regs.h ATMEL AT91 / AT32 SERIAL DRIVER -P: Haavard Skinnemoen -M: hskinnemoen@atmel.com +M: Haavard Skinnemoen S: Supported F: drivers/serial/atmel_serial.c ATMEL LCDFB DRIVER -P: Nicolas Ferre -M: nicolas.ferre@atmel.com +M: Nicolas Ferre L: linux-fbdev-devel@lists.sourceforge.net (moderated for non-subscribers) S: Maintained F: drivers/video/atmel_lcdfb.c F: include/video/atmel_lcdc.h ATMEL MACB ETHERNET DRIVER -P: Haavard Skinnemoen -M: hskinnemoen@atmel.com +M: Haavard Skinnemoen S: Supported F: drivers/net/macb.* ATMEL SPI DRIVER -P: Haavard Skinnemoen -M: hskinnemoen@atmel.com +M: Haavard Skinnemoen S: Supported F: drivers/spi/atmel_spi.* ATMEL USBA UDC DRIVER -P: Haavard Skinnemoen -M: hskinnemoen@atmel.com +M: Haavard Skinnemoen L: kernel@avr32linux.org W: http://avr32linux.org/twiki/bin/view/Main/AtmelUsbDeviceDriver S: Supported F: drivers/usb/gadget/atmel_usba_udc.* ATMEL WIRELESS DRIVER -P: Simon Kelley -M: simon@thekelleys.org.uk +M: Simon Kelley L: linux-wireless@vger.kernel.org W: http://www.thekelleys.org.uk/atmel W: http://atmelwlandriver.sourceforge.net/ @@ -1125,10 +971,8 @@ S: Maintained F: drivers/net/wireless/atmel* AUDIT SUBSYSTEM -P: Al Viro -M: viro@zeniv.linux.org.uk -P: Eric Paris -M: eparis@redhat.com +M: Al Viro +M: Eric Paris L: linux-audit@redhat.com (subscribers-only) W: http://people.redhat.com/sgrubb/audit/ T: git git://git.kernel.org/pub/scm/linux/kernel/git/viro/audit-current.git @@ -1137,8 +981,7 @@ F: include/linux/audit.h F: kernel/audit* AUXILIARY DISPLAY DRIVERS -P: Miguel Ojeda Sandonis -M: miguel.ojeda.sandonis@gmail.com +M: Miguel Ojeda Sandonis W: http://miguelojeda.es/auxdisplay.htm W: http://jair.lab.fi.uva.es/~migojed/auxdisplay.htm S: Maintained @@ -1146,8 +989,7 @@ F: drivers/auxdisplay/ F: include/linux/cfag12864b.h AVR32 ARCHITECTURE -P: Haavard Skinnemoen -M: hskinnemoen@atmel.com +M: Haavard Skinnemoen W: http://www.atmel.com/products/AVR32/ W: http://avr32linux.org/ W: http://avrfreaks.net/ @@ -1155,14 +997,12 @@ S: Supported F: arch/avr32/ AVR32/AT32AP MACHINE SUPPORT -P: Haavard Skinnemoen -M: hskinnemoen@atmel.com +M: Haavard Skinnemoen S: Supported F: arch/avr32/mach-at32ap/ AX.25 NETWORK LAYER -P: Ralf Baechle -M: ralf@linux-mips.org +M: Ralf Baechle L: linux-hams@vger.kernel.org W: http://www.linux-ax25.org/ S: Maintained @@ -1171,128 +1011,110 @@ F: include/net/ax25.h F: net/ax25/ B43 WIRELESS DRIVER -P: Michael Buesch -M: mb@bu3sch.de -P: Stefano Brivio -M: stefano.brivio@polimi.it +M: Michael Buesch +M: Stefano Brivio L: linux-wireless@vger.kernel.org W: http://linuxwireless.org/en/users/Drivers/b43 S: Maintained F: drivers/net/wireless/b43/ B43LEGACY WIRELESS DRIVER -P: Larry Finger -M: Larry.Finger@lwfinger.net -P: Stefano Brivio -M: stefano.brivio@polimi.it +M: Larry Finger +M: Stefano Brivio L: linux-wireless@vger.kernel.org W: http://linuxwireless.org/en/users/Drivers/b43 S: Maintained F: drivers/net/wireless/b43legacy/ BACKLIGHT CLASS/SUBSYSTEM -P: Richard Purdie -M: rpurdie@rpsys.net +M: Richard Purdie S: Maintained F: drivers/video/backlight/ F: include/linux/backlight.h BAYCOM/HDLCDRV DRIVERS FOR AX.25 -P: Thomas Sailer -M: t.sailer@alumni.ethz.ch +M: Thomas Sailer L: linux-hams@vger.kernel.org W: http://www.baycom.org/~tom/ham/ham.html S: Maintained F: drivers/net/hamradio/baycom* BEFS FILE SYSTEM -P: Sergey S. Kostyliov -M: rathamahata@php4.ru +M: "Sergey S. Kostyliov" S: Maintained F: Documentation/filesystems/befs.txt F: fs/befs/ BFS FILE SYSTEM -P: Tigran A. Aivazian -M: tigran@aivazian.fsnet.co.uk +M: "Tigran A. Aivazian" S: Maintained F: Documentation/filesystems/bfs.txt F: fs/bfs/ F: include/linux/bfs_fs.h BLACKFIN ARCHITECTURE -P: Mike Frysinger -M: vapier@gentoo.org +M: Mike Frysinger L: uclinux-dist-devel@blackfin.uclinux.org W: http://blackfin.uclinux.org S: Supported F: arch/blackfin/ BLACKFIN EMAC DRIVER -P: Michael Hennerich -M: michael.hennerich@analog.com +M: Michael Hennerich L: uclinux-dist-devel@blackfin.uclinux.org W: http://blackfin.uclinux.org S: Supported F: drivers/net/bfin_mac.* BLACKFIN RTC DRIVER -P: Mike Frysinger -M: vapier.adi@gmail.com +M: Mike Frysinger L: uclinux-dist-devel@blackfin.uclinux.org W: http://blackfin.uclinux.org S: Supported F: drivers/rtc/rtc-bfin.c BLACKFIN SERIAL DRIVER -P: Sonic Zhang -M: sonic.zhang@analog.com +M: Sonic Zhang L: uclinux-dist-devel@blackfin.uclinux.org W: http://blackfin.uclinux.org S: Supported F: drivers/serial/bfin_5xx.c BLACKFIN WATCHDOG DRIVER -P: Mike Frysinger -M: vapier.adi@gmail.com +M: Mike Frysinger L: uclinux-dist-devel@blackfin.uclinux.org W: http://blackfin.uclinux.org S: Supported F: drivers/watchdog/bfin_wdt.c BLACKFIN I2C TWI DRIVER -P: Sonic Zhang -M: sonic.zhang@analog.com +M: Sonic Zhang L: uclinux-dist-devel@blackfin.uclinux.org W: http://blackfin.uclinux.org/ S: Supported F: drivers/i2c/busses/i2c-bfin-twi.c BLOCK LAYER -P: Jens Axboe -M: axboe@kernel.dk +M: Jens Axboe T: git git://git.kernel.org/pub/scm/linux/kernel/git/axboe/linux-2.6-block.git S: Maintained F: block/ BLOCK2MTD DRIVER -P: Joern Engel -M: joern@lazybastard.org +M: Joern Engel L: linux-mtd@lists.infradead.org S: Maintained F: drivers/mtd/devices/block2mtd.c BLUETOOTH DRIVERS -P: Marcel Holtmann -M: marcel@holtmann.org +M: Marcel Holtmann L: linux-bluetooth@vger.kernel.org W: http://www.bluez.org/ S: Maintained F: drivers/bluetooth/ BLUETOOTH SUBSYSTEM -P: Marcel Holtmann -M: marcel@holtmann.org +M: Marcel Holtmann L: linux-bluetooth@vger.kernel.org W: http://www.bluez.org/ T: git git://git.kernel.org/pub/scm/linux/kernel/git/holtmann/bluetooth-2.6.git @@ -1301,8 +1123,7 @@ F: net/bluetooth/ F: include/net/bluetooth/ BONDING DRIVER -P: Jay Vosburgh -M: fubar@us.ibm.com +M: Jay Vosburgh L: bonding-devel@lists.sourceforge.net W: http://sourceforge.net/projects/bonding/ S: Supported @@ -1310,54 +1131,46 @@ F: drivers/net/bonding/ F: include/linux/if_bonding.h BROADCOM B44 10/100 ETHERNET DRIVER -P: Gary Zambrano -M: zambrano@broadcom.com +M: Gary Zambrano L: netdev@vger.kernel.org S: Supported F: drivers/net/b44.* BROADCOM BNX2 GIGABIT ETHERNET DRIVER -P: Michael Chan -M: mchan@broadcom.com +M: Michael Chan L: netdev@vger.kernel.org S: Supported F: drivers/net/bnx2.* F: drivers/net/bnx2_* BROADCOM BNX2X 10 GIGABIT ETHERNET DRIVER -P: Eilon Greenstein -M: eilong@broadcom.com +M: Eilon Greenstein L: netdev@vger.kernel.org S: Supported F: drivers/net/bnx2x* BROADCOM TG3 GIGABIT ETHERNET DRIVER -P: Matt Carlson -M: mcarlson@broadcom.com -P: Michael Chan -M: mchan@broadcom.com +M: Matt Carlson +M: Michael Chan L: netdev@vger.kernel.org S: Supported F: drivers/net/tg3.* BSG (block layer generic sg v4 driver) -P: FUJITA Tomonori -M: fujita.tomonori@lab.ntt.co.jp +M: FUJITA Tomonori L: linux-scsi@vger.kernel.org S: Supported F: block/bsg.c F: include/linux/bsg.h BT8XXGPIO DRIVER -P: Michael Buesch -M: mb@bu3sch.de +M: Michael Buesch W: http://bu3sch.de/btgpio.php S: Maintained F: drivers/gpio/bt8xxgpio.c BTRFS FILE SYSTEM -P: Chris Mason -M: chris.mason@oracle.com +M: Chris Mason L: linux-btrfs@vger.kernel.org W: http://btrfs.wiki.kernel.org/ T: git git://git.kernel.org/pub/scm/linux/kernel/git/mason/btrfs-unstable.git @@ -1366,8 +1179,7 @@ F: Documentation/filesystems/btrfs.txt F: fs/btrfs/ BTTV VIDEO4LINUX DRIVER -P: Mauro Carvalho Chehab -M: mchehab@infradead.org +M: Mauro Carvalho Chehab L: linux-media@vger.kernel.org W: http://linuxtv.org T: git git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-2.6.git @@ -1376,16 +1188,14 @@ F: Documentation/video4linux/bttv/ F: drivers/media/video/bt8xx/bttv* CACHEFILES: FS-CACHE BACKEND FOR CACHING ON MOUNTED FILESYSTEMS -P: David Howells -M: dhowells@redhat.com +M: David Howells L: linux-cachefs@redhat.com S: Supported F: Documentation/filesystems/caching/cachefiles.txt F: fs/cachefiles/ CAFE CMOS INTEGRATED CAMERA CONTROLLER DRIVER -P: Jonathan Corbet -M: corbet@lwn.net +M: Jonathan Corbet L: linux-media@vger.kernel.org T: git git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-2.6.git S: Maintained @@ -1393,10 +1203,8 @@ F: Documentation/video4linux/cafe_ccic F: drivers/media/video/cafe_ccic* CALGARY x86-64 IOMMU -P: Muli Ben-Yehuda -M: muli@il.ibm.com -P: Jon D. Mason -M: jdmason@kudzu.us +M: Muli Ben-Yehuda +M: "Jon D. Mason" L: discuss@x86-64.org S: Maintained F: arch/x86/kernel/pci-calgary_64.c @@ -1405,10 +1213,8 @@ F: arch/x86/include/asm/calgary.h F: arch/x86/include/asm/tce.h CAN NETWORK LAYER -P: Urs Thuermann -M: urs.thuermann@volkswagen.de -P: Oliver Hartkopp -M: oliver.hartkopp@volkswagen.de +M: Urs Thuermann +M: Oliver Hartkopp L: socketcan-core@lists.berlios.de (subscribers-only) W: http://developer.berlios.de/projects/socketcan/ S: Maintained @@ -1417,15 +1223,13 @@ F: include/linux/can/ F: include/linux/can.h CAN NETWORK DRIVERS -P: Wolfgang Grandegger -M: wg@grandegger.com +M: Wolfgang Grandegger L: socketcan-core@lists.berlios.de (subscribers-only) W: http://developer.berlios.de/projects/socketcan/ S: Maintained CELL BROADBAND ENGINE ARCHITECTURE -P: Arnd Bergmann -M: arnd@arndb.de +M: Arnd Bergmann L: linuxppc-dev@ozlabs.org L: cbe-oss-dev@ozlabs.org W: http://www.ibm.com/developerworks/power/cell/ @@ -1436,8 +1240,7 @@ F: arch/powerpc/oprofile/*cell* F: arch/powerpc/platforms/cell/ CERTIFIED WIRELESS USB (WUSB) SUBSYSTEM: -P: David Vrabel -M: david.vrabel@csr.com +M: David Vrabel L: linux-usb@vger.kernel.org S: Supported F: Documentation/usb/WUSB-Design-overview.txt @@ -1446,8 +1249,7 @@ F: drivers/usb/wusbcore/ F: include/linux/usb/wusb* CFAG12864B LCD DRIVER -P: Miguel Ojeda Sandonis -M: miguel.ojeda.sandonis@gmail.com +M: Miguel Ojeda Sandonis W: http://miguelojeda.es/auxdisplay.htm W: http://jair.lab.fi.uva.es/~migojed/auxdisplay.htm S: Maintained @@ -1455,8 +1257,7 @@ F: drivers/auxdisplay/cfag12864b.c F: include/linux/cfag12864b.h CFAG12864BFB LCD FRAMEBUFFER DRIVER -P: Miguel Ojeda Sandonis -M: miguel.ojeda.sandonis@gmail.com +M: Miguel Ojeda Sandonis W: http://miguelojeda.es/auxdisplay.htm W: http://jair.lab.fi.uva.es/~migojed/auxdisplay.htm S: Maintained @@ -1464,8 +1265,7 @@ F: drivers/auxdisplay/cfag12864bfb.c F: include/linux/cfag12864b.h CFG80211 and NL80211 -P: Johannes Berg -M: johannes@sipsolutions.net +M: Johannes Berg L: linux-wireless@vger.kernel.org S: Maintained F: include/linux/nl80211.h @@ -1474,57 +1274,47 @@ F: net/wireless/* X: net/wireless/wext* CHECKPATCH -P: Andy Whitcroft -M: apw@canonical.com +M: Andy Whitcroft S: Supported F: scripts/checkpatch.pl CISCO 10G ETHERNET DRIVER -P: Scott Feldman -M: scofeldm@cisco.com -P: Joe Eykholt -M: jeykholt@cisco.com +M: Scott Feldman +M: Joe Eykholt S: Supported F: drivers/net/enic/ CIRRUS LOGIC EP93XX ETHERNET DRIVER -P: Lennert Buytenhek -M: kernel@wantstofly.org +M: Lennert Buytenhek L: netdev@vger.kernel.org S: Maintained F: drivers/net/arm/ep93xx_eth.c CIRRUS LOGIC EP93XX OHCI USB HOST DRIVER -P: Lennert Buytenhek -M: kernel@wantstofly.org +M: Lennert Buytenhek L: linux-usb@vger.kernel.org S: Maintained F: drivers/usb/host/ohci-ep93xx.c CIRRUS LOGIC CS4270 SOUND DRIVER -P: Timur Tabi -M: timur@freescale.com +M: Timur Tabi L: alsa-devel@alsa-project.org (moderated for non-subscribers) S: Supported F: sound/soc/codecs/cs4270* CLK API -P: Russell King -M: linux@arm.linux.org.uk +M: Russell King F: include/linux/clk.h CISCO FCOE HBA DRIVER -P: Abhijeet Joglekar -M: abjoglek@cisco.com -P: Joe Eykholt -M: jeykholt@cisco.com +M: Abhijeet Joglekar +M: Joe Eykholt L: linux-scsi@vger.kernel.org S: Supported F: drivers/scsi/fnic/ CODA FILE SYSTEM -P: Jan Harkes -M: jaharkes@cs.cmu.edu +M: Jan Harkes M: coda@cs.cmu.edu L: codalist@coda.cs.cmu.edu W: http://www.coda.cs.cmu.edu/ @@ -1534,8 +1324,7 @@ F: fs/coda/ F: include/linux/coda*.h COMMON INTERNET FILE SYSTEM (CIFS) -P: Steve French -M: sfrench@samba.org +M: Steve French L: linux-cifs-client@lists.samba.org L: samba-technical@lists.samba.org W: http://linux-cifs.samba.org/ @@ -1545,67 +1334,57 @@ F: Documentation/filesystems/cifs.txt F: fs/cifs/ COMPACTPCI HOTPLUG CORE -P: Scott Murray -M: scott@spiteful.org +M: Scott Murray L: linux-pci@vger.kernel.org S: Maintained F: drivers/pci/hotplug/cpci_hotplug* COMPACTPCI HOTPLUG ZIATECH ZT5550 DRIVER -P: Scott Murray -M: scott@spiteful.org +M: Scott Murray L: linux-pci@vger.kernel.org S: Maintained F: drivers/pci/hotplug/cpcihp_zt5550.* COMPACTPCI HOTPLUG GENERIC DRIVER -P: Scott Murray -M: scott@spiteful.org +M: Scott Murray L: linux-pci@vger.kernel.org S: Maintained F: drivers/pci/hotplug/cpcihp_generic.c COMPAL LAPTOP SUPPORT -P: Cezary Jackiewicz -M: cezary.jackiewicz@gmail.com +M: Cezary Jackiewicz S: Maintained F: drivers/platform/x86/compal-laptop.c COMPUTONE INTELLIPORT MULTIPORT CARD -P: Michael H. Warfield -M: mhw@wittsend.com +M: "Michael H. Warfield" W: http://www.wittsend.com/computone.html S: Maintained F: Documentation/serial/computone.txt F: drivers/char/ip2/ CONEXANT ACCESSRUNNER USB DRIVER -P: Simon Arlott -M: cxacru@fire.lp0.eu +M: Simon Arlott L: accessrunner-general@lists.sourceforge.net W: http://accessrunner.sourceforge.net/ S: Maintained F: drivers/usb/atm/cxacru.c CONFIGFS -P: Joel Becker -M: joel.becker@oracle.com +M: Joel Becker S: Supported F: fs/configfs/ F: include/linux/configfs.h CONNECTOR -P: Evgeniy Polyakov -M: zbr@ioremap.net +M: Evgeniy Polyakov L: netdev@vger.kernel.org S: Maintained F: drivers/connector/ CONTROL GROUPS (CGROUPS) -P: Paul Menage -M: menage@google.com -P: Li Zefan -M: lizf@cn.fujitsu.com +M: Paul Menage +M: Li Zefan L: containers@lists.linux-foundation.org S: Maintained F: include/linux/cgroup* @@ -1613,30 +1392,26 @@ F: kernel/cgroup* F: mm/*cgroup* CORETEMP HARDWARE MONITORING DRIVER -P: Rudolf Marek -M: r.marek@assembler.cz +M: Rudolf Marek L: lm-sensors@lm-sensors.org S: Maintained F: Documentation/hwmon/coretemp F: drivers/hwmon/coretemp.c COSA/SRP SYNC SERIAL DRIVER -P: Jan "Yenya" Kasprzak -M: kas@fi.muni.cz +M: Jan "Yenya" Kasprzak W: http://www.fi.muni.cz/~kas/cosa/ S: Maintained F: drivers/net/wan/cosa* CPMAC ETHERNET DRIVER -P: Florian Fainelli -M: florian@openwrt.org +M: Florian Fainelli L: netdev@vger.kernel.org S: Maintained F: drivers/net/cpmac.c CPU FREQUENCY DRIVERS -P: Dave Jones -M: davej@redhat.com +M: Dave Jones L: cpufreq@vger.kernel.org W: http://www.codemonkey.org.uk/projects/cpufreq/ T: git git://git.kernel.org/pub/scm/linux/kernel/git/davej/cpufreq.git @@ -1646,15 +1421,13 @@ F: drivers/cpufreq/ F: include/linux/cpufreq.h CPUID/MSR DRIVER -P: H. Peter Anvin -M: hpa@zytor.com +M: "H. Peter Anvin" S: Maintained F: arch/x86/kernel/cpuid.c F: arch/x86/kernel/msr.c CPUSETS -P: Paul Menage -M: menage@google.com +M: Paul Menage W: http://www.bullopensource.org/cpuset/ W: http://oss.sgi.com/projects/cpusets/ S: Supported @@ -1669,20 +1442,16 @@ F: Documentation/filesystems/cramfs.txt F: fs/cramfs/ CRIS PORT -P: Mikael Starvik -M: starvik@axis.com -P: Jesper Nilsson -M: jesper.nilsson@axis.com +M: Mikael Starvik +M: Jesper Nilsson L: linux-cris-kernel@axis.com W: http://developer.axis.com S: Maintained F: arch/cris/ CRYPTO API -P: Herbert Xu -M: herbert@gondor.apana.org.au -P: David S. Miller -M: davem@davemloft.net +M: Herbert Xu +M: "David S. Miller" L: linux-crypto@vger.kernel.org T: git git://git.kernel.org/pub/scm/linux/kernel/git/herbert/crypto-2.6.git S: Maintained @@ -1693,22 +1462,18 @@ F: drivers/crypto/ F: include/crypto/ CRYPTOGRAPHIC RANDOM NUMBER GENERATOR -P: Neil Horman -M: nhorman@tuxdriver.com +M: Neil Horman L: linux-crypto@vger.kernel.org S: Maintained CS5535 Audio ALSA driver -P: Jaya Kumar -M: jayakumar.alsa@gmail.com +M: Jaya Kumar S: Maintained F: sound/pci/cs5535audio/ CX18 VIDEO4LINUX DRIVER -P: Hans Verkuil -M: hverkuil@xs4all.nl -P: Andy Walls -M: awalls@radix.net +M: Hans Verkuil +M: Andy Walls L: ivtv-devel@ivtvdriver.org L: linux-media@vger.kernel.org T: git git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-2.6.git @@ -1719,32 +1484,28 @@ F: Documentation/video4linux/cx18.txt F: drivers/media/video/cx18/ CXGB3 ETHERNET DRIVER (CXGB3) -P: Divy Le Ray -M: divy@chelsio.com +M: Divy Le Ray L: netdev@vger.kernel.org W: http://www.chelsio.com S: Supported F: drivers/net/cxgb3/ CXGB3 IWARP RNIC DRIVER (IW_CXGB3) -P: Steve Wise -M: swise@chelsio.com +M: Steve Wise L: general@lists.openfabrics.org W: http://www.openfabrics.org S: Supported F: drivers/infiniband/hw/cxgb3/ CYBERPRO FB DRIVER -P: Russell King -M: linux@arm.linux.org.uk +M: Russell King L: linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only) W: http://www.arm.linux.org.uk/ S: Maintained F: drivers/video/cyber2000fb.* CYCLADES 2X SYNC CARD DRIVER -P: Arnaldo Carvalho de Melo -M: acme@ghostprotocols.net +M: Arnaldo Carvalho de Melo W: http://oops.ghostprotocols.net:81/blog S: Maintained F: drivers/net/wan/cycx* @@ -1761,8 +1522,7 @@ S: Orphan F: drivers/net/wan/pc300* DAMA SLAVE for AX.25 -P: Joerg Reuter -M: jreuter@yaina.de +M: Joerg Reuter W: http://yaina.de/jreuter/ W: http://www.qsl.net/dl1bke/ L: linux-hams@vger.kernel.org @@ -1776,29 +1536,23 @@ F: net/ax25/ax25_timer.c F: net/ax25/sysctl_net_ax25.c DAVICOM FAST ETHERNET (DMFE) NETWORK DRIVER -P: Tobias Ringstrom -M: tori@unhappy.mine.nu +M: Tobias Ringstrom L: netdev@vger.kernel.org S: Maintained F: Documentation/networking/dmfe.txt F: drivers/net/tulip/dmfe.c DC390/AM53C974 SCSI driver -P: Kurt Garloff -M: garloff@suse.de +M: Kurt Garloff W: http://www.garloff.de/kurt/linux/dc390/ -P: Guennadi Liakhovetski -M: g.liakhovetski@gmx.de +M: Guennadi Liakhovetski S: Maintained F: drivers/scsi/tmscsim.* DC395x SCSI driver -P: Oliver Neukum -M: oliver@neukum.name -P: Ali Akcaagac -M: aliakc@web.de -P: Jamie Lenehan -M: lenehan@twibble.org +M: Oliver Neukum +M: Ali Akcaagac +M: Jamie Lenehan W: http://twibble.org/dist/dc395x/ L: dc395x@twibble.org L: http://lists.twibble.org/mailman/listinfo/dc395x/ @@ -1807,8 +1561,7 @@ F: Documentation/scsi/dc395x.txt F: drivers/scsi/dc395x.* DCCP PROTOCOL -P: Arnaldo Carvalho de Melo -M: acme@ghostprotocols.net +M: Arnaldo Carvalho de Melo L: dccp@vger.kernel.org W: http://linux-net.osdl.org/index.php/DCCP S: Maintained @@ -1817,8 +1570,7 @@ F: include/linux/tfrc.h F: net/dccp/ DECnet NETWORK LAYER -P: Christine Caulfield -M: christine.caulfield@googlemail.com +M: Christine Caulfield W: http://linux-decnet.sourceforge.net L: linux-decnet-user@lists.sourceforge.net S: Maintained @@ -1826,40 +1578,34 @@ F: Documentation/networking/decnet.txt F: net/decnet/ DEFXX FDDI NETWORK DRIVER -P: Maciej W. Rozycki -M: macro@linux-mips.org +M: "Maciej W. Rozycki" S: Maintained F: drivers/net/defxx.* DELL LAPTOP DRIVER -P: Matthew Garrett -M: mjg59@srcf.ucam.org +M: Matthew Garrett S: Maintained F: drivers/platform/x86/dell-laptop.c DELL LAPTOP SMM DRIVER -P: Massimo Dal Zotto -M: dz@debian.org +M: Massimo Dal Zotto W: http://www.debian.org/~dz/i8k/ S: Maintained F: drivers/char/i8k.c F: include/linux/i8k.h DELL SYSTEMS MANAGEMENT BASE DRIVER (dcdbas) -P: Doug Warzecha -M: Douglas_Warzecha@dell.com +M: Doug Warzecha S: Maintained F: Documentation/dcdbas.txt F: drivers/firmware/dcdbas.* DELL WMI EXTRAS DRIVER -P: Matthew Garrett -M: mjg59@srcf.ucam.org +M: Matthew Garrett S: Maintained DEVICE NUMBER REGISTRY -P: Torben Mathiasen -M: device@lanana.org +M: Torben Mathiasen W: http://lanana.org/docs/device-list/index.html S: Maintained @@ -1874,8 +1620,7 @@ F: include/linux/device-mapper.h F: include/linux/dm-*.h DIGI INTL. EPCA DRIVER -P: Digi International, Inc -M: Eng.Linux@digi.com +M: "Digi International, Inc" L: Eng.Linux@digi.com W: http://www.digi.com S: Orphan @@ -1884,34 +1629,29 @@ F: drivers/char/epca* F: drivers/char/digi* DIRECTORY NOTIFICATION (DNOTIFY) -P: Eric Paris -M: eparis@parisplace.org +M: Eric Paris S: Maintained F: Documentation/filesystems/dnotify.txt F: fs/notify/dnotify/ F: include/linux/dnotify.h DISK GEOMETRY AND PARTITION HANDLING -P: Andries Brouwer -M: aeb@cwi.nl +M: Andries Brouwer W: http://www.win.tue.nl/~aeb/linux/Large-Disk.html W: http://www.win.tue.nl/~aeb/linux/zip/zip-1.html W: http://www.win.tue.nl/~aeb/partitions/partition_types-1.html S: Maintained DISKQUOTA -P: Jan Kara -M: jack@suse.cz +M: Jan Kara S: Maintained F: Documentation/filesystems/quota.txt F: fs/quota/ F: include/linux/quota*.h DISTRIBUTED LOCK MANAGER (DLM) -P: Christine Caulfield -M: ccaulfie@redhat.com -P: David Teigland -M: teigland@redhat.com +M: Christine Caulfield +M: David Teigland L: cluster-devel@redhat.com W: http://sources.redhat.com/cluster/ T: git git://git.kernel.org/pub/scm/linux/kernel/git/teigland/dlm.git @@ -1919,52 +1659,44 @@ S: Supported F: fs/dlm/ DMA GENERIC OFFLOAD ENGINE SUBSYSTEM -P: Maciej Sosnowski -M: maciej.sosnowski@intel.com -P: Dan Williams -M: dan.j.williams@intel.com +M: Maciej Sosnowski +M: Dan Williams S: Supported F: drivers/dma/ F: include/linux/dma* DME1737 HARDWARE MONITOR DRIVER -P: Juerg Haefliger -M: juergh@gmail.com +M: Juerg Haefliger L: lm-sensors@lm-sensors.org S: Maintained F: Documentation/hwmon/dme1737 F: drivers/hwmon/dme1737.c DOCBOOK FOR DOCUMENTATION -P: Randy Dunlap -M: rdunlap@xenotime.net +M: Randy Dunlap S: Maintained DOCKING STATION DRIVER -P: Shaohua Li -M: shaohua.li@intel.com +M: Shaohua Li L: linux-acpi@vger.kernel.org S: Supported F: drivers/acpi/dock.c DOCUMENTATION -P: Randy Dunlap -M: rdunlap@xenotime.net +M: Randy Dunlap L: linux-doc@vger.kernel.org S: Maintained F: Documentation/ DOUBLETALK DRIVER -P: James R. Van Zandt -M: jrv@vanzandt.mv.com +M: "James R. Van Zandt" L: blinux-list@redhat.com S: Maintained F: drivers/char/dtlk.c F: include/linux/dtlk.h DPT_I2O SCSI RAID DRIVER -P: Adaptec OEM Raid Solutions -M: aacraid@adaptec.com +M: Adaptec OEM Raid Solutions L: linux-scsi@vger.kernel.org W: http://www.adaptec.com/ S: Maintained @@ -1972,8 +1704,7 @@ F: drivers/scsi/dpt* F: drivers/scsi/dpt/ DRIVER CORE, KOBJECTS, AND SYSFS -P: Greg Kroah-Hartman -M: gregkh@suse.de +M: Greg Kroah-Hartman T: quilt kernel.org/pub/linux/kernel/people/gregkh/gregkh-2.6/ S: Supported F: Documentation/kobject.txt @@ -1983,52 +1714,45 @@ F: include/linux/kobj* F: lib/kobj* DRM DRIVERS -P: David Airlie -M: airlied@linux.ie +M: David Airlie L: dri-devel@lists.sourceforge.net T: git git://git.kernel.org/pub/scm/linux/kernel/git/airlied/drm-2.6.git S: Maintained F: drivers/gpu/drm/ DSCC4 DRIVER -P: Francois Romieu -M: romieu@fr.zoreil.com +M: Francois Romieu L: netdev@vger.kernel.org S: Maintained F: drivers/net/wan/dscc4.c DZ DECSTATION DZ11 SERIAL DRIVER -P: Maciej W. Rozycki -M: macro@linux-mips.org +M: "Maciej W. Rozycki" S: Maintained F: drivers/serial/dz.* EATA-DMA SCSI DRIVER -P: Michael Neuffer -M: mike@i-Connect.Net +M: Michael Neuffer L: linux-eata@i-connect.net L: linux-scsi@vger.kernel.org S: Maintained F: drivers/scsi/eata* EATA ISA/EISA/PCI SCSI DRIVER -P: Dario Ballabio -M: ballabio_dario@emc.com +M: Dario Ballabio L: linux-scsi@vger.kernel.org S: Maintained F: drivers/scsi/eata.c EATA-PIO SCSI DRIVER -P: Michael Neuffer -M: mike@i-Connect.Net +M: Michael Neuffer L: linux-eata@i-connect.net L: linux-scsi@vger.kernel.org S: Maintained F: drivers/scsi/eata_pio.* EBTABLES -P: Bart De Schuymer -M: bart.de.schuymer@pandora.be +M: Bart De Schuymer L: ebtables-user@lists.sourceforge.net L: ebtables-devel@lists.sourceforge.net W: http://ebtables.sourceforge.net/ @@ -2037,10 +1761,8 @@ F: include/linux/netfilter_bridge/ebt_*.h F: net/bridge/netfilter/ebt*.c ECRYPT FILE SYSTEM -P: Tyler Hicks -M: tyhicks@linux.vnet.ibm.com -P: Dustin Kirkland -M: kirkland@canonical.com +M: Tyler Hicks +M: Dustin Kirkland L: ecryptfs-devel@lists.launchpad.net W: https://launchpad.net/ecryptfs S: Supported @@ -2048,8 +1770,7 @@ F: Documentation/filesystems/ecryptfs.txt F: fs/ecryptfs/ EDAC-CORE -P: Doug Thompson -M: dougthompson@xmission.com +M: Doug Thompson L: bluesmoke-devel@lists.sourceforge.net (moderated for non-subscribers) W: bluesmoke.sourceforge.net S: Supported @@ -2058,94 +1779,80 @@ F: drivers/edac/edac_* F: include/linux/edac.h EDAC-AMD64 -P: Doug Thompson -M: dougthompson@xmission.com -P: Borislav Petkov -M: borislav.petkov@amd.com +M: Doug Thompson +M: Borislav Petkov L: bluesmoke-devel@lists.sourceforge.net (moderated for non-subscribers) W: bluesmoke.sourceforge.net S: Supported F: drivers/edac/amd64_edac* EDAC-E752X -P: Mark Gross -M: mark.gross@intel.com -P: Doug Thompson -M: dougthompson@xmission.com +M: Mark Gross +M: Doug Thompson L: bluesmoke-devel@lists.sourceforge.net (moderated for non-subscribers) W: bluesmoke.sourceforge.net S: Maintained F: drivers/edac/e752x_edac.c EDAC-E7XXX -P: Doug Thompson -M: dougthompson@xmission.com +M: Doug Thompson L: bluesmoke-devel@lists.sourceforge.net (moderated for non-subscribers) W: bluesmoke.sourceforge.net S: Maintained F: drivers/edac/e7xxx_edac.c EDAC-I82443BXGX -P: Tim Small -M: tim@buttersideup.com +M: Tim Small L: bluesmoke-devel@lists.sourceforge.net (moderated for non-subscribers) W: bluesmoke.sourceforge.net S: Maintained F: drivers/edac/i82443bxgx_edac.c EDAC-I3000 -P: Jason Uhlenkott -M: juhlenko@akamai.com +M: Jason Uhlenkott L: bluesmoke-devel@lists.sourceforge.net (moderated for non-subscribers) W: bluesmoke.sourceforge.net S: Maintained F: drivers/edac/i3000_edac.c EDAC-I5000 -P: Doug Thompson -M: dougthompson@xmission.com +M: Doug Thompson L: bluesmoke-devel@lists.sourceforge.net (moderated for non-subscribers) W: bluesmoke.sourceforge.net S: Maintained F: drivers/edac/i5000_edac.c EDAC-I5400 -P: Mauro Carvalho Chehab -M: mchehab@redhat.com +M: Mauro Carvalho Chehab L: bluesmoke-devel@lists.sourceforge.net (moderated for non-subscribers) W: bluesmoke.sourceforge.net S: Maintained F: drivers/edac/i5400_edac.c EDAC-I82975X -P: Ranganathan Desikan -M: ravi@jetztechnologies.com -P: Arvind R. -M: arvind@jetztechnologies.com +M: Ranganathan Desikan +M: "Arvind R." L: bluesmoke-devel@lists.sourceforge.net (moderated for non-subscribers) W: bluesmoke.sourceforge.net S: Maintained F: drivers/edac/i82975x_edac.c EDAC-PASEMI -P: Egor Martovetsky -M: egor@pasemi.com +M: Egor Martovetsky L: bluesmoke-devel@lists.sourceforge.net (moderated for non-subscribers) W: bluesmoke.sourceforge.net S: Maintained F: drivers/edac/pasemi_edac.c EDAC-R82600 -P: Tim Small -M: tim@buttersideup.com +M: Tim Small L: bluesmoke-devel@lists.sourceforge.net (moderated for non-subscribers) W: bluesmoke.sourceforge.net S: Maintained F: drivers/edac/r82600_edac.c EEEPC LAPTOP EXTRAS DRIVER -P: Corentin Chary -M: corentincj@iksaif.net +M: Corentin Chary L: acpi4asus-user@lists.sourceforge.net W: http://acpi4asus.sf.net S: Maintained @@ -2157,65 +1864,53 @@ S: Orphan F: fs/efs/ EHCA (IBM GX bus InfiniBand adapter) DRIVER -P: Hoang-Nam Nguyen -M: hnguyen@de.ibm.com -P: Christoph Raisch -M: raisch@de.ibm.com +M: Hoang-Nam Nguyen +M: Christoph Raisch L: general@lists.openfabrics.org S: Supported F: drivers/infiniband/hw/ehca/ EMBEDDED LINUX -P: Paul Gortmaker -M: paul.gortmaker@windriver.com -P: Matt Mackall -M: mpm@selenic.com -P: David Woodhouse -M: dwmw2@infradead.org +M: Paul Gortmaker +M: Matt Mackall +M: David Woodhouse L: linux-embedded@vger.kernel.org S: Maintained EMULEX LPFC FC SCSI DRIVER -P: James Smart -M: james.smart@emulex.com +M: James Smart L: linux-scsi@vger.kernel.org W: http://sourceforge.net/projects/lpfcxxxx S: Supported F: drivers/scsi/lpfc/ ENE CB710 FLASH CARD READER DRIVER -P: Michał Mirosław -M: mirq-linux@rere.qmqm.pl +M: Michał Mirosław S: Maintained F: drivers/misc/cb710/ F: drivers/mmc/host/cb710-mmc.* F: include/linux/cb710.h EPSON 1355 FRAMEBUFFER DRIVER -P: Christopher Hoover -M: ch@murgatroid.com -P: Christopher Hoover -M: ch@hpl.hp.com +M: Christopher Hoover +M: Christopher Hoover S: Maintained F: drivers/video/epson1355fb.c EPSON S1D13XXX FRAMEBUFFER DRIVER -P: Kristoffer Ericson -M: kristoffer.ericson@gmail.com +M: Kristoffer Ericson S: Maintained F: drivers/video/s1d13xxxfb.c F: include/video/s1d13xxxfb.h ETHEREXPRESS-16 NETWORK DRIVER -P: Philip Blundell -M: philb@gnu.org +M: Philip Blundell L: netdev@vger.kernel.org S: Maintained F: drivers/net/eexpress.* ETHERNET BRIDGE -P: Stephen Hemminger -M: shemminger@linux-foundation.org +M: Stephen Hemminger L: bridge@lists.linux-foundation.org W: http://www.linux-foundation.org/en/Net:Bridge S: Maintained @@ -2223,8 +1918,7 @@ F: include/linux/netfilter_bridge/ F: net/bridge/ ETHERTEAM 16I DRIVER -P: Mika Kuoppala -M: miku@iki.fi +M: Mika Kuoppala S: Maintained F: drivers/net/eth16i.c @@ -2236,12 +1930,9 @@ F: fs/ext2/ F: include/linux/ext2* EXT3 FILE SYSTEM -P: Stephen Tweedie -M: sct@redhat.com -P: Andrew Morton -M: akpm@linux-foundation.org -P: Andreas Dilger -M: adilger@sun.com +M: Stephen Tweedie +M: Andrew Morton +M: Andreas Dilger L: linux-ext4@vger.kernel.org S: Maintained F: Documentation/filesystems/ext3.txt @@ -2249,10 +1940,8 @@ F: fs/ext3/ F: include/linux/ext3* EXT4 FILE SYSTEM -P: Theodore Ts'o -M: tytso@mit.edu -P: Andreas Dilger -M: adilger@sun.com +M: "Theodore Ts'o" +M: Andreas Dilger L: linux-ext4@vger.kernel.org W: http://ext4.wiki.kernel.org S: Maintained @@ -2260,30 +1949,26 @@ F: Documentation/filesystems/ext4.txt F: fs/ext4/ F71805F HARDWARE MONITORING DRIVER -P: Jean Delvare -M: khali@linux-fr.org +M: Jean Delvare L: lm-sensors@lm-sensors.org S: Maintained F: Documentation/hwmon/f71805f F: drivers/hwmon/f71805f.c FARSYNC SYNCHRONOUS DRIVER -P: Kevin Curtis -M: kevin.curtis@farsite.co.uk +M: Kevin Curtis W: http://www.farsite.co.uk/ S: Supported F: drivers/net/wan/farsync.* FAULT INJECTION SUPPORT -P: Akinobu Mita -M: akinobu.mita@gmail.com +M: Akinobu Mita S: Supported F: Documentation/fault-injection/ F: lib/fault-inject.c FILE LOCKING (flock() and fcntl()/lockf()) -P: Matthew Wilcox -M: matthew@wil.cx +M: Matthew Wilcox L: linux-fsdevel@vger.kernel.org S: Maintained F: include/linux/fcntl.h @@ -2292,25 +1977,21 @@ F: fs/fcntl.c F: fs/locks.c FILESYSTEMS (VFS and infrastructure) -P: Alexander Viro -M: viro@zeniv.linux.org.uk +M: Alexander Viro L: linux-fsdevel@vger.kernel.org S: Maintained F: fs/* FINTEK F75375S HARDWARE MONITOR AND FAN CONTROLLER DRIVER -P: Riku Voipio -M: riku.vipio@iki.fi +M: Riku Voipio L: lm-sensors@lm-sensors.org S: Maintained F: drivers/hwmon/f75375s.c F: include/linux/f75375s.h FIREWIRE SUBSYSTEM -P: Kristian Hoegsberg -M: krh@redhat.com -P: Stefan Richter -M: stefanr@s5r6.in-berlin.de +M: Kristian Hoegsberg +M: Stefan Richter L: linux1394-devel@lists.sourceforge.net W: http://www.linux1394.org/ T: git git://git.kernel.org/pub/scm/linux/kernel/git/ieee1394/linux1394-2.6.git @@ -2325,15 +2006,13 @@ F: drivers/base/firmware*.c F: include/linux/firmware.h FPU EMULATOR -P: Bill Metzenthen -M: billm@melbpc.org.au +M: Bill Metzenthen W: http://floatingpoint.sourceforge.net/emulator/index.html S: Maintained F: arch/x86/math-emu/ FRAME RELAY DLCI/FRAD (Sangoma drivers too) -P: Mike McLagan -M: mike.mclagan@linux.org +M: Mike McLagan L: netdev@vger.kernel.org S: Maintained F: drivers/net/wan/dlci.c @@ -2348,25 +2027,21 @@ F: drivers/video/fb* F: include/linux/fb.h FREESCALE DMA DRIVER -P: Li Yang -M: leoli@freescale.com -P: Zhang Wei -M: zw@zh-kernel.org +M: Li Yang +M: Zhang Wei L: linuxppc-dev@ozlabs.org S: Maintained F: drivers/dma/fsldma.* FREESCALE I2C CPM DRIVER -P: Jochen Friedrich -M: jochen@scram.de +M: Jochen Friedrich L: linuxppc-dev@ozlabs.org L: linux-i2c@vger.kernel.org S: Maintained F: drivers/i2c/busses/i2c-cpm.c FREESCALE IMX / MXC FRAMEBUFFER DRIVER -P: Sascha Hauer -M: kernel@pengutronix.de +M: Sascha Hauer L: linux-fbdev-devel@lists.sourceforge.net (moderated for non-subscribers) L: linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only) S: Maintained @@ -2374,10 +2049,8 @@ F: arch/arm/plat-mxc/include/mach/imxfb.h F: drivers/video/imxfb.c FREESCALE SOC FS_ENET DRIVER -P: Pantelis Antoniou -M: pantelis.antoniou@gmail.com -P: Vitaly Bordug -M: vbordug@ru.mvista.com +M: Pantelis Antoniou +M: Vitaly Bordug L: linuxppc-dev@ozlabs.org L: netdev@vger.kernel.org S: Maintained @@ -2385,39 +2058,34 @@ F: drivers/net/fs_enet/ F: include/linux/fs_enet_pd.h FREESCALE QUICC ENGINE LIBRARY -P: Timur Tabi -M: timur@freescale.com +M: Timur Tabi L: linuxppc-dev@ozlabs.org S: Supported F: arch/powerpc/sysdev/qe_lib/ F: arch/powerpc/include/asm/*qe.h FREESCALE HIGHSPEED USB DEVICE DRIVER -P: Li Yang -M: leoli@freescale.com +M: Li Yang L: linux-usb@vger.kernel.org L: linuxppc-dev@ozlabs.org S: Maintained F: drivers/usb/gadget/fsl_usb2_udc.c FREESCALE QUICC ENGINE UCC ETHERNET DRIVER -P: Li Yang -M: leoli@freescale.com +M: Li Yang L: netdev@vger.kernel.org L: linuxppc-dev@ozlabs.org S: Maintained F: drivers/net/ucc_geth* FREESCALE QUICC ENGINE UCC UART DRIVER -P: Timur Tabi -M: timur@freescale.com +M: Timur Tabi L: linuxppc-dev@ozlabs.org S: Supported F: drivers/serial/ucc_uart.c FREESCALE SOC SOUND DRIVERS -P: Timur Tabi -M: timur@freescale.com +M: Timur Tabi L: alsa-devel@alsa-project.org (moderated for non-subscribers) L: linuxppc-dev@ozlabs.org S: Supported @@ -2425,17 +2093,14 @@ F: sound/soc/fsl/fsl* F: sound/soc/fsl/mpc8610_hpcd.c FREEVXFS FILESYSTEM -P: Christoph Hellwig -M: hch@infradead.org +M: Christoph Hellwig W: ftp://ftp.openlinux.org/pub/people/hch/vxfs S: Maintained F: fs/freevxfs/ FREEZER -P: Pavel Machek -M: pavel@ucw.cz -P: Rafael J. Wysocki -M: rjw@sisk.pl +M: Pavel Machek +M: "Rafael J. Wysocki" L: linux-pm@lists.linux-foundation.org S: Supported F: Documentation/power/freezing-of-tasks.txt @@ -2443,8 +2108,7 @@ F: include/linux/freezer.h F: kernel/freezer.c FS-CACHE: LOCAL CACHING FOR NETWORK FILESYSTEMS -P: David Howells -M: dhowells@redhat.com +M: David Howells L: linux-cachefs@redhat.com S: Supported F: Documentation/filesystems/caching/ @@ -2452,8 +2116,7 @@ F: fs/fscache/ F: include/linux/fscache*.h FTRACE -P: Steven Rostedt -M: rostedt@goodmis.org +M: Steven Rostedt S: Maintained F: Documentation/trace/ftrace.txt F: arch/*/*/*/ftrace.h @@ -2462,21 +2125,18 @@ F: include/*/ftrace.h F: kernel/trace/ FUJITSU FR-V (FRV) PORT -P: David Howells -M: dhowells@redhat.com +M: David Howells S: Maintained F: arch/frv/ FUJITSU LAPTOP EXTRAS -P: Jonathan Woithe -M: jwoithe@physics.adelaide.edu.au +M: Jonathan Woithe L: linux-acpi@vger.kernel.org S: Maintained F: drivers/platform/x86/fujitsu-laptop.c FUSE: FILESYSTEM IN USERSPACE -P: Miklos Szeredi -M: miklos@szeredi.hu +M: Miklos Szeredi L: fuse-devel@lists.sourceforge.net W: http://fuse.sourceforge.net/ S: Maintained @@ -2484,30 +2144,26 @@ F: fs/fuse/ F: include/linux/fuse.h FUTURE DOMAIN TMC-16x0 SCSI DRIVER (16-bit) -P: Rik Faith -M: faith@cs.unc.edu +M: Rik Faith L: linux-scsi@vger.kernel.org S: Odd Fixes (e.g., new signatures) F: drivers/scsi/fdomain.* GDT SCSI DISK ARRAY CONTROLLER DRIVER -P: Achim Leubner -M: achim_leubner@adaptec.com +M: Achim Leubner L: linux-scsi@vger.kernel.org W: http://www.icp-vortex.com/ S: Supported F: drivers/scsi/gdt* GENERIC GPIO I2C DRIVER -P: Haavard Skinnemoen -M: hskinnemoen@atmel.com +M: Haavard Skinnemoen S: Supported F: drivers/i2c/busses/i2c-gpio.c F: include/linux/i2c-gpio.h GENERIC HDLC (WAN) DRIVERS -P: Krzysztof Halasa -M: khc@pm.waw.pl +M: Krzysztof Halasa W: http://www.kernel.org/pub/linux/utils/net/hdlc/ S: Maintained F: drivers/net/wan/c101.c @@ -2519,16 +2175,14 @@ F: drivers/net/wan/pci200syn.c F: drivers/net/wan/wanxl* GENERIC INCLUDE/ASM HEADER FILES -P: Arnd Bergmann -M: arnd@arndb.de +M: Arnd Bergmann L: linux-arch@vger.kernel.org T: git git://git.kernel.org/pub/scm/linux/kernel/git/arnd/asm-generic.git S: Maintained F: include/asm-generic GFS2 FILE SYSTEM -P: Steven Whitehouse -M: swhiteho@redhat.com +M: Steven Whitehouse L: cluster-devel@redhat.com W: http://sources.redhat.com/cluster/ T: git git://git.kernel.org/pub/scm/linux/kernel/git/steve/gfs2-2.6-fixes.git @@ -2539,10 +2193,8 @@ F: fs/gfs2/ F: include/linux/gfs2_ondisk.h GIGASET ISDN DRIVERS -P: Hansjoerg Lipp -M: hjlipp@web.de -P: Tilman Schmidt -M: tilman@imap.cc +M: Hansjoerg Lipp +M: Tilman Schmidt L: gigaset307x-common@lists.sourceforge.net W: http://gigaset307x.sourceforge.net/ S: Maintained @@ -2551,8 +2203,7 @@ F: drivers/isdn/gigaset/ F: include/linux/gigaset_dev.h HARD DRIVE ACTIVE PROTECTION SYSTEM (HDAPS) DRIVER -P: Frank Seidel -M: frank@f-seidel.de +M: Frank Seidel L: lm-sensors@lm-sensors.org W: http://www.kernel.org/pub/linux/kernel/people/fseidel/hdaps/ S: Maintained @@ -2564,40 +2215,35 @@ S: Odd Fixes F: drivers/char/hvc_* GSPCA FINEPIX SUBDRIVER -P: Frank Zago -M: frank@zago.net +M: Frank Zago L: linux-media@vger.kernel.org T: git git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-2.6.git S: Maintained F: drivers/media/video/gspca/finepix.c GSPCA M5602 SUBDRIVER -P: Erik Andren -M: erik.andren@gmail.com +M: Erik Andren L: linux-media@vger.kernel.org T: git git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-2.6.git S: Maintained F: drivers/media/video/gspca/m5602/ GSPCA PAC207 SONIXB SUBDRIVER -P: Hans de Goede -M: hdegoede@redhat.com +M: Hans de Goede L: linux-media@vger.kernel.org T: git git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-2.6.git S: Maintained F: drivers/media/video/gspca/pac207.c GSPCA T613 SUBDRIVER -P: Leandro Costantino -M: lcostantino@gmail.com +M: Leandro Costantino L: linux-media@vger.kernel.org T: git git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-2.6.git S: Maintained F: drivers/media/video/gspca/t613.c GSPCA USB WEBCAM DRIVER -P: Jean-Francois Moine -M: moinejf@free.fr +M: Jean-Francois Moine W: http://moinejf.free.fr L: linux-media@vger.kernel.org T: git git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-2.6.git @@ -2617,31 +2263,27 @@ F: drivers/char/hw_random/ F: include/linux/hw_random.h HARMONY SOUND DRIVER -P: Kyle McMartin -M: kyle@mcmartin.ca +M: Kyle McMartin L: linux-parisc@vger.kernel.org S: Maintained F: sound/parisc/harmony.* HAYES ESP SERIAL DRIVER -P: Andrew J. Robinson -M: arobinso@nyx.net +M: "Andrew J. Robinson" W: http://www.nyx.net/~arobinso S: Maintained F: Documentation/serial/hayes-esp.txt F: drivers/char/esp.c HEWLETT-PACKARD SMART2 RAID DRIVER -P: Chirag Kantharia -M: chirag.kantharia@hp.com +M: Chirag Kantharia L: iss_storagedev@hp.com S: Maintained F: Documentation/blockdev/cpqarray.txt F: drivers/block/cpqarray.* HEWLETT-PACKARD SMART CISS RAID DRIVER (cciss) -P: Mike Miller -M: mike.miller@hp.com +M: Mike Miller L: iss_storagedev@hp.com S: Supported F: Documentation/blockdev/cciss.txt @@ -2649,25 +2291,21 @@ F: drivers/block/cciss* F: include/linux/cciss_ioctl.h HFS FILESYSTEM -P: Roman Zippel -M: zippel@linux-m68k.org +M: Roman Zippel S: Maintained F: Documentation/filesystems/hfs.txt F: fs/hfs/ HGA FRAMEBUFFER DRIVER -P: Ferenc Bakonyi -M: fero@drama.obuda.kando.hu +M: Ferenc Bakonyi L: linux-nvidia@lists.surfsouth.com W: http://drama.obuda.kando.hu/~fero/cgi-bin/hgafb.shtml S: Maintained F: drivers/video/hgafb.c HIBERNATION (aka Software Suspend, aka swsusp) -P: Pavel Machek -M: pavel@ucw.cz -P: Rafael J. Wysocki -M: rjw@sisk.pl +M: Pavel Machek +M: "Rafael J. Wysocki" L: linux-pm@lists.linux-foundation.org S: Supported F: arch/x86/power/ @@ -2679,8 +2317,7 @@ F: include/linux/pm.h F: arch/*/include/asm/suspend*.h HID CORE LAYER -P: Jiri Kosina -M: jkosina@suse.cz +M: Jiri Kosina L: linux-input@vger.kernel.org T: git git://git.kernel.org/pub/scm/linux/kernel/git/jikos/hid.git S: Maintained @@ -2688,16 +2325,14 @@ F: drivers/hid/ F: include/linux/hid* HIGH-RESOLUTION TIMERS, CLOCKEVENTS, DYNTICKS -P: Thomas Gleixner -M: tglx@linutronix.de +M: Thomas Gleixner S: Maintained F: Documentation/timers/ F: kernel/hrtimer.c F: include/linux/hrtimer.h HIGH-SPEED SCC DRIVER FOR AX.25 -P: Klaus Kudielka -M: klaus.kudielka@ieee.org +M: Klaus Kudielka L: linux-hams@vger.kernel.org W: http://www.nt.tuwien.ac.at/~kkudielk/Linux/ S: Maintained @@ -2705,16 +2340,14 @@ F: drivers/net/hamradio/dmascc.c F: drivers/net/hamradio/scc.c HIGHPOINT ROCKETRAID 3xxx RAID DRIVER -P: HighPoint Linux Team -M: linux@highpoint-tech.com +M: HighPoint Linux Team W: http://www.highpoint-tech.com S: Supported F: Documentation/scsi/hptiop.txt F: drivers/scsi/hptiop.c HIPPI -P: Jes Sorensen -M: jes@trained-monkey.org +M: Jes Sorensen L: linux-hippi@sunsite.dk S: Maintained F: include/linux/hippidevice.h @@ -2722,8 +2355,7 @@ F: include/linux/if_hippi.h F: net/802/hippi.c HOST AP DRIVER -P: Jouni Malinen -M: j@w1.fi +M: Jouni Malinen L: hostap@shmoo.com (subscribers-only) L: linux-wireless@vger.kernel.org W: http://hostap.epitest.fi/ @@ -2731,82 +2363,69 @@ S: Maintained F: drivers/net/wireless/hostap/ HP COMPAQ TC1100 TABLET WMI EXTRAS DRIVER -P: Carlos Corbacho -M: carlos@strangeworlds.co.uk +M: Carlos Corbacho S: Odd Fixes F: drivers/platform/x86/tc1100-wmi.c HP100: Driver for HP 10/100 Mbit/s Voice Grade Network Adapter Series -P: Jaroslav Kysela -M: perex@perex.cz +M: Jaroslav Kysela S: Maintained F: drivers/net/hp100.* HPET: High Precision Event Timers driver -P: Clemens Ladisch -M: clemens@ladisch.de +M: Clemens Ladisch S: Maintained F: Documentation/timers/hpet.txt F: drivers/char/hpet.c F: include/linux/hpet.h HPET: i386 -P: Venkatesh Pallipadi (Venki) -M: venkatesh.pallipadi@intel.com +M: "Venkatesh Pallipadi (Venki)" S: Maintained F: arch/x86/kernel/hpet.c F: arch/x86/include/asm/hpet.h HPET: x86_64 -P: Vojtech Pavlik -M: vojtech@suse.cz +M: Vojtech Pavlik S: Maintained HPET: ACPI -P: Bob Picco -M: bob.picco@hp.com +M: Bob Picco S: Maintained F: drivers/char/hpet.c HPFS FILESYSTEM -P: Mikulas Patocka -M: mikulas@artax.karlin.mff.cuni.cz +M: Mikulas Patocka W: http://artax.karlin.mff.cuni.cz/~mikulas/vyplody/hpfs/index-e.cgi S: Maintained F: fs/hpfs/ HSO 3G MODEM DRIVER -P: Jan Dumon -M: j.dumon@option.com +M: Jan Dumon W: http://www.pharscape.org S: Maintained F: drivers/net/usb/hso.c HTCPEN TOUCHSCREEN DRIVER -P: Pau Oliva Fora -M: pof@eslack.org +M: Pau Oliva Fora L: linux-input@vger.kernel.org S: Maintained F: drivers/input/touchscreen/htcpen.c HUGETLB FILESYSTEM -P: William Irwin -M: wli@holomorphy.com +M: William Irwin S: Maintained F: fs/hugetlbfs/ I2C/SMBUS STUB DRIVER -P: Mark M. Hoffman -M: mhoffman@lightlink.com +M: "Mark M. Hoffman" L: linux-i2c@vger.kernel.org S: Maintained F: drivers/i2c/busses/i2c-stub.c I2C SUBSYSTEM -P: Jean Delvare (PC drivers, core) -M: khali@linux-fr.org -P: Ben Dooks (embedded platforms) -M: ben-linux@fluff.org +M: "Jean Delvare (PC drivers, core)" +M: "Ben Dooks (embedded platforms)" L: linux-i2c@vger.kernel.org W: http://i2c.wiki.kernel.org/ T: quilt kernel.org/pub/linux/kernel/people/jdelvare/linux-2.6/jdelvare-i2c/ @@ -2818,30 +2437,25 @@ F: include/linux/i2c-dev.h F: include/linux/i2c-id.h I2C-TINY-USB DRIVER -P: Till Harbaum -M: till@harbaum.org +M: Till Harbaum L: linux-i2c@vger.kernel.org W: http://www.harbaum.org/till/i2c_tiny_usb S: Maintained F: drivers/i2c/busses/i2c-tiny-usb.c i386 BOOT CODE -P: H. Peter Anvin -M: hpa@zytor.com +M: "H. Peter Anvin" S: Maintained F: arch/x86/boot/ i386 SETUP CODE / CPU ERRATA WORKAROUNDS -P: H. Peter Anvin -M: hpa@zytor.com +M: "H. Peter Anvin" T: git git://git.kernel.org/pub/scm/linux/kernel/git/hpa/linux-2.6-x86setup.git S: Maintained IA64 (Itanium) PLATFORM -P: Tony Luck -M: tony.luck@intel.com -P: Fenghua Yu -M: fenghua.yu@intel.com +M: Tony Luck +M: Fenghua Yu L: linux-ia64@vger.kernel.org W: http://www.ia64-linux.org/ T: git git://git.kernel.org/pub/scm/linux/kernel/git/aegl/linux-2.6.git @@ -2849,29 +2463,25 @@ S: Maintained F: arch/ia64/ IBM MCA SCSI SUBSYSTEM DRIVER -P: Michael Lang -M: langa2@kph.uni-mainz.de +M: Michael Lang W: http://www.uni-mainz.de/~langm000/linux.html S: Maintained F: drivers/scsi/ibmmca.c IBM Power Linux RAID adapter -P: Brian King -M: brking@us.ibm.com +M: Brian King S: Supported F: drivers/scsi/ipr.* IBM ServeRAID RAID DRIVER P: Jack Hammer -P: Dave Jeffery -M: ipslinux@adaptec.com +M: Dave Jeffery W: http://www.developer.ibm.com/welcome/netfinity/serveraid.html S: Supported F: drivers/scsi/ips.* IDE SUBSYSTEM -P: David S. Miller -M: davem@davemloft.net +M: "David S. Miller" L: linux-ide@vger.kernel.org T: git git://git.kernel.org/pub/scm/linux/kernel/git/davem/ide-2.6.git S: Maintained @@ -2880,25 +2490,21 @@ F: drivers/ide/ F: include/linux/ide.h IDE/ATAPI DRIVERS -P: Borislav Petkov -M: petkovbb@gmail.com +M: Borislav Petkov L: linux-ide@vger.kernel.org S: Maintained F: Documentation/cdrom/ide-cd F: drivers/ide/ide-cd* IDLE-I7300 -P: Andy Henroid -M: andrew.d.henroid@intel.com +M: Andy Henroid L: linux-pm@lists.linux-foundation.org S: Supported F: drivers/idle/i7300_idle.c IEEE 1394 SUBSYSTEM -P: Ben Collins -M: ben.collins@ubuntu.com -P: Stefan Richter -M: stefanr@s5r6.in-berlin.de +M: Ben Collins +M: Stefan Richter L: linux1394-devel@lists.sourceforge.net W: http://www.linux1394.org/ T: git git://git.kernel.org/pub/scm/linux/kernel/git/ieee1394/linux1394-2.6.git @@ -2906,19 +2512,15 @@ S: Maintained F: drivers/ieee1394/ IEEE 1394 RAW I/O DRIVER -P: Dan Dennedy -M: dan@dennedy.org -P: Stefan Richter -M: stefanr@s5r6.in-berlin.de +M: Dan Dennedy +M: Stefan Richter L: linux1394-devel@lists.sourceforge.net S: Maintained F: drivers/ieee1394/raw1394* IEEE 802.15.4 SUBSYSTEM -P: Dmitry Eremin-Solenikov -M: dbaryshkov@gmail.com -P: Sergey Lapin -M: slapin@ossfans.org +M: Dmitry Eremin-Solenikov +M: Sergey Lapin L: linux-zigbee-devel@lists.sourceforge.net (moderated for non-subscribers) W: http://apps.sourceforge.net/trac/linux-zigbee T: git git://git.kernel.org/pub/scm/linux/kernel/git/lowpan/lowpan.git @@ -2927,8 +2529,7 @@ F: net/ieee802154/ F: drivers/ieee802154/ INTEGRITY MEASUREMENT ARCHITECTURE (IMA) -P: Mimi Zohar -M: zohar@us.ibm.com +M: Mimi Zohar S: Supported F: security/integrity/ima/ @@ -2938,12 +2539,9 @@ S: Orphan F: drivers/video/imsttfb.c INFINIBAND SUBSYSTEM -P: Roland Dreier -M: rolandd@cisco.com -P: Sean Hefty -M: sean.hefty@intel.com -P: Hal Rosenstock -M: hal.rosenstock@gmail.com +M: Roland Dreier +M: Sean Hefty +M: Hal Rosenstock L: general@lists.openfabrics.org (moderated for non-subscribers) W: http://www.openib.org/ T: git git://git.kernel.org/pub/scm/linux/kernel/git/roland/infiniband.git @@ -2953,66 +2551,55 @@ F: drivers/infiniband/ F: include/linux/if_infiniband.h INOTIFY -P: John McCutchan -M: john@johnmccutchan.com -P: Robert Love -M: rlove@rlove.org -P: Eric Paris -M: eparis@parisplace.org +M: John McCutchan +M: Robert Love +M: Eric Paris S: Maintained F: Documentation/filesystems/inotify.txt F: fs/notify/inotify/ F: include/linux/inotify.h INPUT (KEYBOARD, MOUSE, JOYSTICK, TOUCHSCREEN) DRIVERS -P: Dmitry Torokhov -M: dmitry.torokhov@gmail.com -P: Dmitry Torokhov -M: dtor@mail.ru +M: Dmitry Torokhov +M: Dmitry Torokhov L: linux-input@vger.kernel.org T: git git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input.git S: Maintained F: drivers/input/ INTEL FRAMEBUFFER DRIVER (excluding 810 and 815) -P: Sylvain Meyer -M: sylvain.meyer@worldonline.fr +M: Sylvain Meyer L: linux-fbdev-devel@lists.sourceforge.net (moderated for non-subscribers) S: Maintained F: Documentation/fb/intelfb.txt F: drivers/video/intelfb/ INTEL 810/815 FRAMEBUFFER DRIVER -P: Antonino Daplas -M: adaplas@gmail.com +M: Antonino Daplas L: linux-fbdev-devel@lists.sourceforge.net (moderated for non-subscribers) S: Maintained F: drivers/video/i810/ INTEL MENLOW THERMAL DRIVER -P: Sujith Thomas -M: sujith.thomas@intel.com +M: Sujith Thomas L: linux-acpi@vger.kernel.org W: http://www.lesswatts.org/projects/acpi/ S: Supported F: drivers/platform/x86/intel_menlow.c INTEL IA32 MICROCODE UPDATE SUPPORT -P: Tigran Aivazian -M: tigran@aivazian.fsnet.co.uk +M: Tigran Aivazian S: Maintained F: arch/x86/kernel/microcode_core.c F: arch/x86/kernel/microcode_intel.c INTEL I/OAT DMA DRIVER -P: Maciej Sosnowski -M: maciej.sosnowski@intel.com +M: Maciej Sosnowski S: Supported F: drivers/dma/ioat* INTEL IOMMU (VT-d) -P: David Woodhouse -M: dwmw2@infradead.org +M: David Woodhouse L: iommu@lists.linux-foundation.org T: git git://git.infradead.org/iommu-2.6.git S: Supported @@ -3020,14 +2607,12 @@ F: drivers/pci/intel-iommu.c F: include/linux/intel-iommu.h INTEL IOP-ADMA DMA DRIVER -P: Dan Williams -M: dan.j.williams@intel.com +M: Dan Williams S: Supported F: drivers/dma/iop-adma.c INTEL IXP4XX QMGR, NPE, ETHERNET and HSS SUPPORT -P: Krzysztof Halasa -M: khc@pm.waw.pl +M: Krzysztof Halasa S: Maintained F: arch/arm/mach-ixp4xx/include/mach/qmgr.h F: arch/arm/mach-ixp4xx/include/mach/npe.h @@ -3037,29 +2622,22 @@ F: drivers/net/arm/ixp4xx_eth.c F: drivers/net/wan/ixp4xx_hss.c INTEL IXP4XX RANDOM NUMBER GENERATOR SUPPORT -P: Deepak Saxena -M: dsaxena@plexity.net +M: Deepak Saxena S: Maintained F: drivers/char/hw_random/ixp4xx-rng.c INTEL IXP2000 ETHERNET DRIVER -P: Lennert Buytenhek -M: kernel@wantstofly.org +M: Lennert Buytenhek L: netdev@vger.kernel.org S: Maintained F: drivers/net/ixp2000/ INTEL ETHERNET DRIVERS (e100/e1000/e1000e/igb/ixgb/ixgbe) -P: Jeff Kirsher -M: jeffrey.t.kirsher@intel.com -P: Jesse Brandeburg -M: jesse.brandeburg@intel.com -P: Bruce Allan -M: bruce.w.allan@intel.com -P: PJ Waskiewicz -M: peter.p.waskiewicz.jr@intel.com -P: John Ronciak -M: john.ronciak@intel.com +M: Jeff Kirsher +M: Jesse Brandeburg +M: Bruce Allan +M: PJ Waskiewicz +M: John Ronciak L: e1000-devel@lists.sourceforge.net W: http://e1000.sourceforge.net/ S: Supported @@ -3071,12 +2649,9 @@ F: drivers/net/ixgb/ F: drivers/net/ixgbe/ INTEL PRO/WIRELESS 2100 NETWORK CONNECTION SUPPORT -P: Zhu Yi -M: yi.zhu@intel.com -P: James Ketrenos -M: jketreno@linux.intel.com -P: Reinette Chatre -M: reinette.chatre@intel.com +M: Zhu Yi +M: James Ketrenos +M: Reinette Chatre L: linux-wireless@vger.kernel.org L: ipw2100-devel@lists.sourceforge.net W: http://lists.sourceforge.net/mailman/listinfo/ipw2100-devel @@ -3086,12 +2661,9 @@ F: Documentation/networking/README.ipw2100 F: drivers/net/wireless/ipw2x00/ipw2100.* INTEL PRO/WIRELESS 2915ABG NETWORK CONNECTION SUPPORT -P: Zhu Yi -M: yi.zhu@intel.com -P: James Ketrenos -M: jketreno@linux.intel.com -P: Reinette Chatre -M: reinette.chatre@intel.com +M: Zhu Yi +M: James Ketrenos +M: Reinette Chatre L: linux-wireless@vger.kernel.org L: ipw2100-devel@lists.sourceforge.net W: http://lists.sourceforge.net/mailman/listinfo/ipw2100-devel @@ -3101,8 +2673,7 @@ F: Documentation/networking/README.ipw2200 F: drivers/net/wireless/ipw2x00/ipw2200.* INTEL WIRELESS WIMAX CONNECTION 2400 -P: Inaky Perez-Gonzalez -M: inaky.perez-gonzalez@intel.com +M: Inaky Perez-Gonzalez M: linux-wimax@intel.com L: wimax@linuxwimax.org S: Supported @@ -3112,10 +2683,8 @@ F: drivers/net/wimax/i2400m/ F: include/linux/wimax/i2400m.h INTEL WIRELESS WIFI LINK (iwlwifi) -P: Zhu Yi -M: yi.zhu@intel.com -P: Reinette Chatre -M: reinette.chatre@intel.com +M: Zhu Yi +M: Reinette Chatre L: linux-wireless@vger.kernel.org L: ipw3945-devel@lists.sourceforge.net W: http://intellinuxwireless.org @@ -3124,47 +2693,39 @@ S: Supported F: drivers/net/wireless/iwlwifi/ IOC3 ETHERNET DRIVER -P: Ralf Baechle -M: ralf@linux-mips.org +M: Ralf Baechle L: linux-mips@linux-mips.org S: Maintained F: drivers/net/ioc3-eth.c IOC3 SERIAL DRIVER -P: Pat Gefre -M: pfg@sgi.com +M: Pat Gefre L: linux-mips@linux-mips.org S: Maintained F: drivers/serial/ioc3_serial.c IP MASQUERADING -P: Juanjo Ciarlante -M: jjciarla@raiz.uncu.edu.ar +M: Juanjo Ciarlante S: Maintained F: net/ipv4/netfilter/ipt_MASQUERADE.c IP1000A 10/100/1000 GIGABIT ETHERNET DRIVER -P: Francois Romieu -M: romieu@fr.zoreil.com -P: Sorbica Shieh -M: sorbica@icplus.com.tw -P: Jesse Huang -M: jesse@icplus.com.tw +M: Francois Romieu +M: Sorbica Shieh +M: Jesse Huang L: netdev@vger.kernel.org S: Maintained F: drivers/net/ipg.c IPATH DRIVER -P: Ralph Campbell -M: infinipath@qlogic.com +M: Ralph Campbell L: general@lists.openfabrics.org T: git git://git.qlogic.com/ipath-linux-2.6 S: Supported F: drivers/infiniband/hw/ipath/ IPMI SUBSYSTEM -P: Corey Minyard -M: minyard@acm.org +M: Corey Minyard L: openipmi-developer@lists.sourceforge.net W: http://openipmi.sourceforge.net/ S: Supported @@ -3173,20 +2734,16 @@ F: drivers/char/ipmi/ F: include/linux/ipmi* IPS SCSI RAID DRIVER -P: Adaptec OEM Raid Solutions -M: aacraid@adaptec.com +M: Adaptec OEM Raid Solutions L: linux-scsi@vger.kernel.org W: http://www.adaptec.com/ S: Maintained F: drivers/scsi/ips* IPVS -P: Wensong Zhang -M: wensong@linux-vs.org -P: Simon Horman -M: horms@verge.net.au -P: Julian Anastasov -M: ja@ssi.bg +M: Wensong Zhang +M: Simon Horman +M: Julian Anastasov L: netdev@vger.kernel.org L: lvs-devel@vger.kernel.org S: Maintained @@ -3194,17 +2751,14 @@ F: Documentation/networking/ipvs-sysctl.txt F: net/netfilter/ipvs/ IPWIRELESS DRIVER -P: Jiri Kosina -M: jkosina@suse.cz -P: David Sterba -M: dsterba@suse.cz +M: Jiri Kosina +M: David Sterba S: Maintained T: git git://git.kernel.org/pub/scm/linux/kernel/git/jikos/ipwireless_cs.git F: drivers/char/pcmcia/ipwireless/ IPX NETWORK LAYER -P: Arnaldo Carvalho de Melo -M: acme@ghostprotocols.net +M: Arnaldo Carvalho de Melo L: netdev@vger.kernel.org S: Maintained F: include/linux/ipx.h @@ -3212,8 +2766,7 @@ F: include/net/ipx.h F: net/ipx/ IRDA SUBSYSTEM -P: Samuel Ortiz -M: samuel@sortiz.org +M: Samuel Ortiz L: irda-users@lists.sourceforge.net (subscribers-only) W: http://irda.sourceforge.net/ S: Maintained @@ -3224,16 +2777,14 @@ F: include/net/irda/ F: net/irda/ ISAPNP -P: Jaroslav Kysela -M: perex@perex.cz +M: Jaroslav Kysela S: Maintained F: Documentation/isapnp.txt F: drivers/pnp/isapnp/ F: include/linux/isapnp.h ISCSI -P: Mike Christie -M: michaelc@cs.wisc.edu +M: Mike Christie L: open-iscsi@googlegroups.com W: www.open-iscsi.org T: git git://git.kernel.org/pub/scm/linux/kernel/git/mnc/linux-2.6-iscsi.git @@ -3242,8 +2793,7 @@ F: drivers/scsi/*iscsi* F: include/scsi/*iscsi* ISDN SUBSYSTEM -P: Karsten Keil -M: isdn@linux-pingi.de +M: Karsten Keil L: isdn4linux@listserv.isdn4linux.de (subscribers-only) W: http://www.isdn4linux.de T: git git://git.kernel.org/pub/scm/linux/kernel/git/kkeil/isdn-2.6.git @@ -3254,16 +2804,14 @@ F: include/linux/isdn.h F: include/linux/isdn/ ISDN SUBSYSTEM (Eicon active card driver) -P: Armin Schindler -M: mac@melware.de +M: Armin Schindler L: isdn4linux@listserv.isdn4linux.de (subscribers-only) W: http://www.melware.de S: Maintained F: drivers/isdn/hardware/eicon/ IVTV VIDEO4LINUX DRIVER -P: Hans Verkuil -M: hverkuil@xs4all.nl +M: Hans Verkuil L: ivtv-devel@ivtvdriver.org L: linux-media@vger.kernel.org T: git git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-2.6.git @@ -3274,8 +2822,7 @@ F: drivers/media/video/ivtv/ F: include/linux/ivtv* JFS FILESYSTEM -P: Dave Kleikamp -M: shaggy@linux.vnet.ibm.com +M: Dave Kleikamp L: jfs-discussion@lists.sourceforge.net W: http://jfs.sourceforge.net/ T: git git://git.kernel.org/pub/scm/linux/kernel/git/shaggy/jfs-2.6.git @@ -3284,15 +2831,13 @@ F: Documentation/filesystems/jfs.txt F: fs/jfs/ JME NETWORK DRIVER -P: Guo-Fu Tseng -M: cooldavid@cooldavid.org +M: Guo-Fu Tseng L: netdev@vger.kernel.org S: Maintained F: drivers/net/jme.* JOURNALLING FLASH FILE SYSTEM V2 (JFFS2) -P: David Woodhouse -M: dwmw2@infradead.org +M: David Woodhouse L: linux-mtd@lists.infradead.org W: http://www.linux-mtd.infradead.org/doc/jffs2.html S: Maintained @@ -3300,10 +2845,8 @@ F: fs/jffs2/ F: include/linux/jffs2.h JOURNALLING LAYER FOR BLOCK DEVICES (JBD) -P: Stephen Tweedie -M: sct@redhat.com -P: Andrew Morton -M: akpm@linux-foundation.org +M: Stephen Tweedie +M: Andrew Morton L: linux-ext4@vger.kernel.org S: Maintained F: fs/jbd*/ @@ -3311,48 +2854,41 @@ F: include/linux/ext*jbd*.h F: include/linux/jbd*.h K8TEMP HARDWARE MONITORING DRIVER -P: Rudolf Marek -M: r.marek@assembler.cz +M: Rudolf Marek L: lm-sensors@lm-sensors.org S: Maintained F: Documentation/hwmon/k8temp F: drivers/hwmon/k8temp.c KCONFIG -P: Roman Zippel -M: zippel@linux-m68k.org +M: Roman Zippel L: linux-kbuild@vger.kernel.org S: Maintained F: Documentation/kbuild/kconfig-language.txt F: scripts/kconfig/ KDUMP -P: Vivek Goyal -M: vgoyal@redhat.com -P: Haren Myneni -M: hbabu@us.ibm.com +M: Vivek Goyal +M: Haren Myneni L: kexec@lists.infradead.org W: http://lse.sourceforge.net/kdump/ S: Maintained F: Documentation/kdump/ KERNEL AUTOMOUNTER (AUTOFS) -P: H. Peter Anvin -M: hpa@zytor.com +M: "H. Peter Anvin" L: autofs@linux.kernel.org S: Odd Fixes F: fs/autofs/ KERNEL AUTOMOUNTER v4 (AUTOFS4) -P: Ian Kent -M: raven@themaw.net +M: Ian Kent L: autofs@linux.kernel.org S: Maintained F: fs/autofs4/ KERNEL BUILD -P: Sam Ravnborg -M: sam@ravnborg.org +M: Sam Ravnborg T: git git://git.kernel.org/pub/scm/linux/kernel/git/sam/kbuild-next.git T: git git://git.kernel.org/pub/scm/linux/kernel/git/sam/kbuild-fixes.git L: linux-kbuild@vger.kernel.org @@ -3367,10 +2903,8 @@ W: http://www.kerneljanitors.org/ S: Odd fixes KERNEL NFSD, SUNRPC, AND LOCKD SERVERS -P: J. Bruce Fields -M: bfields@fieldses.org -P: Neil Brown -M: neilb@suse.de +M: "J. Bruce Fields" +M: Neil Brown L: linux-nfs@vger.kernel.org W: http://nfs.sourceforge.net/ S: Supported @@ -3383,8 +2917,7 @@ F: include/linux/lockd/ F: include/linux/sunrpc/ KERNEL VIRTUAL MACHINE (KVM) -P: Avi Kivity -M: avi@redhat.com +M: Avi Kivity L: kvm@vger.kernel.org W: http://kvm.qumranet.com S: Supported @@ -3395,8 +2928,7 @@ F: include/linux/kvm* F: virt/kvm/ KERNEL VIRTUAL MACHINE (KVM) FOR AMD-V -P: Joerg Roedel -M: joerg.roedel@amd.com +M: Joerg Roedel L: kvm@vger.kernel.org W: http://kvm.qumranet.com S: Supported @@ -3405,8 +2937,7 @@ F: arch/x86/kvm/kvm_svm.h F: arch/x86/kvm/svm.c KERNEL VIRTUAL MACHINE (KVM) FOR POWERPC -P: Hollis Blanchard -M: hollisb@us.ibm.com +M: Hollis Blanchard L: kvm-ppc@vger.kernel.org W: http://kvm.qumranet.com S: Supported @@ -3414,8 +2945,7 @@ F: arch/powerpc/include/asm/kvm* F: arch/powerpc/kvm/ KERNEL VIRTUAL MACHINE For Itanium (KVM/IA64) -P: Xiantao Zhang -M: xiantao.zhang@intel.com +M: Xiantao Zhang L: kvm-ia64@vger.kernel.org W: http://kvm.qumranet.com S: Supported @@ -3424,10 +2954,8 @@ F: arch/ia64/include/asm/kvm* F: arch/ia64/kvm/ KERNEL VIRTUAL MACHINE for s390 (KVM/s390) -P: Carsten Otte -M: cotte@de.ibm.com -P: Christian Borntraeger -M: borntraeger@de.ibm.com +M: Carsten Otte +M: Christian Borntraeger M: linux390@de.ibm.com L: linux-s390@vger.kernel.org W: http://www.ibm.com/developerworks/linux/linux390/ @@ -3437,8 +2965,7 @@ F: arch/s390/include/asm/kvm* F: arch/s390/kvm/ KEXEC -P: Eric Biederman -M: ebiederm@xmission.com +M: Eric Biederman W: http://ftp.kernel.org/pub/linux/kernel/people/horms/kexec-tools/ L: kexec@lists.infradead.org S: Maintained @@ -3446,8 +2973,7 @@ F: include/linux/kexec.h F: kernel/kexec.c KGDB -P: Jason Wessel -M: jason.wessel@windriver.com +M: Jason Wessel L: kgdb-bugreport@lists.sourceforge.net S: Maintained F: Documentation/DocBook/kgdb.tmpl @@ -3457,15 +2983,13 @@ F: include/linux/kgdb.h F: kernel/kgdb.c KMEMCHECK -P: Vegard Nossum -M: vegardno@ifi.uio.no +M: Vegard Nossum P Pekka Enberg M: penberg@cs.helsinki.fi S: Maintained KMEMLEAK -P: Catalin Marinas -M: catalin.marinas@arm.com +M: Catalin Marinas S: Maintained F: Documentation/kmemleak.txt F: include/linux/kmemleak.h @@ -3473,30 +2997,24 @@ F: mm/kmemleak.c F: mm/kmemleak-test.c KMEMTRACE -P: Eduard - Gabriel Munteanu -M: eduard.munteanu@linux360.ro +M: Eduard - Gabriel Munteanu S: Maintained F: Documentation/trace/kmemtrace.txt F: include/linux/kmemtrace.h F: kernel/trace/kmemtrace.c KPROBES -P: Ananth N Mavinakayanahalli -M: ananth@in.ibm.com -P: Anil S Keshavamurthy -M: anil.s.keshavamurthy@intel.com -P: David S. Miller -M: davem@davemloft.net -P: Masami Hiramatsu -M: mhiramat@redhat.com +M: Ananth N Mavinakayanahalli +M: Anil S Keshavamurthy +M: "David S. Miller" +M: Masami Hiramatsu S: Maintained F: Documentation/kprobes.txt F: include/linux/kprobes.h F: kernel/kprobes.c KS0108 LCD CONTROLLER DRIVER -P: Miguel Ojeda Sandonis -M: miguel.ojeda.sandonis@gmail.com +M: Miguel Ojeda Sandonis W: http://miguelojeda.es/auxdisplay.htm W: http://jair.lab.fi.uva.es/~migojed/auxdisplay.htm S: Maintained @@ -3512,31 +3030,27 @@ F: include/*/lapb.h F: net/lapb/ LASI 53c700 driver for PARISC -P: James E.J. Bottomley -M: James.Bottomley@HansenPartnership.com +M: "James E.J. Bottomley" L: linux-scsi@vger.kernel.org S: Maintained F: Documentation/scsi/53c700.txt F: drivers/scsi/53c700* LED SUBSYSTEM -P: Richard Purdie -M: rpurdie@rpsys.net +M: Richard Purdie S: Maintained F: drivers/leds/ F: include/linux/leds.h LEGO USB Tower driver -P: Juergen Stuber -M: starblue@users.sourceforge.net +M: Juergen Stuber L: legousb-devel@lists.sourceforge.net W: http://legousb.sourceforge.net/ S: Maintained F: drivers/usb/misc/legousbtower.c LGUEST -P: Rusty Russell -M: rusty@rustcorp.com.au +M: Rusty Russell L: lguest@ozlabs.org W: http://lguest.ozlabs.org/ S: Maintained @@ -3547,119 +3061,100 @@ F: include/linux/lguest*.h F: arch/x86/include/asm/lguest*.h LINUX FOR IBM pSERIES (RS/6000) -P: Paul Mackerras -M: paulus@au.ibm.com +M: Paul Mackerras W: http://www.ibm.com/linux/ltc/projects/ppc S: Supported LINUX FOR POWERPC (32-BIT AND 64-BIT) -P: Benjamin Herrenschmidt -M: benh@kernel.crashing.org -P: Paul Mackerras -M: paulus@samba.org +M: Benjamin Herrenschmidt +M: Paul Mackerras W: http://www.penguinppc.org/ L: linuxppc-dev@ozlabs.org T: git git://git.kernel.org/pub/scm/linux/kernel/git/benh/powerpc.git S: Supported LINUX FOR POWER MACINTOSH -P: Benjamin Herrenschmidt -M: benh@kernel.crashing.org +M: Benjamin Herrenschmidt W: http://www.penguinppc.org/ L: linuxppc-dev@ozlabs.org S: Maintained LINUX FOR POWERPC EMBEDDED MPC5XXX -P: Grant Likely -M: grant.likely@secretlab.ca +M: Grant Likely L: linuxppc-dev@ozlabs.org T: git git://git.secretlab.ca/git/linux-2.6.git S: Maintained LINUX FOR POWERPC EMBEDDED PPC4XX -P: Josh Boyer -M: jwboyer@linux.vnet.ibm.com -P: Matt Porter -M: mporter@kernel.crashing.org +M: Josh Boyer +M: Matt Porter W: http://www.penguinppc.org/ L: linuxppc-dev@ozlabs.org T: git git://git.kernel.org/pub/scm/linux/kernel/git/jwboyer/powerpc-4xx.git S: Maintained LINUX FOR POWERPC EMBEDDED XILINX VIRTEX -P: Grant Likely -M: grant.likely@secretlab.ca +M: Grant Likely W: http://wiki.secretlab.ca/index.php/Linux_on_Xilinx_Virtex L: linuxppc-dev@ozlabs.org T: git git://git.secretlab.ca/git/linux-2.6.git S: Maintained LINUX FOR POWERPC EMBEDDED PPC8XX -P: Vitaly Bordug -M: vitb@kernel.crashing.org -P: Marcelo Tosatti -M: marcelo@kvack.org +M: Vitaly Bordug +M: Marcelo Tosatti W: http://www.penguinppc.org/ L: linuxppc-dev@ozlabs.org S: Maintained LINUX FOR POWERPC EMBEDDED PPC83XX AND PPC85XX -P: Kumar Gala -M: galak@kernel.crashing.org +M: Kumar Gala W: http://www.penguinppc.org/ L: linuxppc-dev@ozlabs.org S: Maintained LINUX FOR POWERPC PA SEMI PWRFICIENT -P: Olof Johansson -M: olof@lixom.net +M: Olof Johansson W: http://www.pasemi.com/ L: linuxppc-dev@ozlabs.org S: Supported LINUX SECURITY MODULE (LSM) FRAMEWORK -P: Chris Wright -M: chrisw@sous-sol.org +M: Chris Wright L: linux-security-module@vger.kernel.org T: git git://git.kernel.org/pub/scm/linux/kernel/git/chrisw/lsm-2.6.git S: Supported LLC (802.2) -P: Arnaldo Carvalho de Melo -M: acme@ghostprotocols.net +M: Arnaldo Carvalho de Melo S: Maintained F: include/linux/llc.h F: include/net/llc* F: net/llc/ LIS3LV02D ACCELEROMETER DRIVER -P: Eric Piel -M: eric.piel@tremplin-utc.net +M: Eric Piel S: Maintained F: Documentation/hwmon/lis3lv02d F: drivers/hwmon/lis3lv02d.* LM83 HARDWARE MONITOR DRIVER -P: Jean Delvare -M: khali@linux-fr.org +M: Jean Delvare L: lm-sensors@lm-sensors.org S: Maintained F: Documentation/hwmon/lm83 F: drivers/hwmon/lm83.c LM90 HARDWARE MONITOR DRIVER -P: Jean Delvare -M: khali@linux-fr.org +M: Jean Delvare L: lm-sensors@lm-sensors.org S: Maintained F: Documentation/hwmon/lm90 F: drivers/hwmon/lm90.c LOCKDEP AND LOCKSTAT -P: Peter Zijlstra -M: peterz@infradead.org -P: Ingo Molnar -M: mingo@redhat.com +M: Peter Zijlstra +M: Ingo Molnar T: git git://git.kernel.org/pub/scm/linux/kernel/git/peterz/linux-2.6-lockdep.git S: Maintained F: Documentation/lockdep*.txt @@ -3668,8 +3163,7 @@ F: include/linux/lockdep.h F: kernel/lockdep* LOGICAL DISK MANAGER SUPPORT (LDM, Windows 2000/XP/Vista Dynamic Disks) -P: Richard Russon (FlatCap) -M: ldm@flatcap.org +M: "Richard Russon (FlatCap)" L: linux-ntfs-dev@lists.sourceforge.net W: http://www.linux-ntfs.org/content/view/19/37/ S: Maintained @@ -3677,8 +3171,7 @@ F: Documentation/ldm.txt F: fs/partitions/ldm.* LSILOGIC MPT FUSION DRIVERS (FC/SAS/SPI) -P: Eric Moore -M: Eric.Moore@lsi.com +M: Eric Moore M: support@lsi.com L: DL-MPTFusionLinux@lsi.com L: linux-scsi@vger.kernel.org @@ -3687,25 +3180,21 @@ S: Supported F: drivers/message/fusion/ LSILOGIC/SYMBIOS/NCR 53C8XX and 53C1010 PCI-SCSI drivers -P: Matthew Wilcox -M: matthew@wil.cx +M: Matthew Wilcox L: linux-scsi@vger.kernel.org S: Maintained F: drivers/scsi/sym53c8xx_2/ LTP (Linux Test Project) -P: Subrata Modak -M: subrata@linux.vnet.ibm.com -P: Mike Frysinger -M: vapier@gentoo.org +M: Subrata Modak +M: Mike Frysinger L: ltp-list@lists.sourceforge.net (subscribers-only) W: http://ltp.sourceforge.net/ T: git git://git.kernel.org/pub/scm/linux/kernel/git/galak/ltp.git S: Maintained M32R ARCHITECTURE -P: Hirokazu Takata -M: takata@linux-m32r.org +M: Hirokazu Takata L: linux-m32r@ml.linux-m32r.org L: linux-m32r-ja@ml.linux-m32r.org (in Japanese) W: http://www.linux-m32r.org/ @@ -3713,10 +3202,8 @@ S: Maintained F: arch/m32r/ M68K ARCHITECTURE -P: Geert Uytterhoeven -M: geert@linux-m68k.org -P: Roman Zippel -M: zippel@linux-m68k.org +M: Geert Uytterhoeven +M: Roman Zippel L: linux-m68k@lists.linux-m68k.org W: http://www.linux-m68k.org/ T: git git://git.kernel.org/pub/scm/linux/kernel/git/geert/linux-m68k.git @@ -3725,23 +3212,20 @@ F: arch/m68k/ F: drivers/zorro/ M68K ON APPLE MACINTOSH -P: Joshua Thompson -M: funaho@jurai.org +M: Joshua Thompson W: http://www.mac.linux-m68k.org/ L: linux-m68k@lists.linux-m68k.org S: Maintained F: arch/m68k/mac/ M68K ON HP9000/300 -P: Philip Blundell -M: philb@gnu.org +M: Philip Blundell W: http://www.tazenda.demon.co.uk/phil/linux-hp S: Maintained F: arch/m68k/hp300/ MAC80211 -P: Johannes Berg -M: johannes@sipsolutions.net +M: Johannes Berg L: linux-wireless@vger.kernel.org W: http://linuxwireless.org/ T: git git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-2.6.git @@ -3751,10 +3235,8 @@ F: include/net/mac80211.h F: net/mac80211/ MAC80211 PID RATE CONTROL -P: Stefano Brivio -M: stefano.brivio@polimi.it -P: Mattias Nissler -M: mattias.nissler@gmx.de +M: Stefano Brivio +M: Mattias Nissler L: linux-wireless@vger.kernel.org W: http://linuxwireless.org/en/developers/Documentation/mac80211/RateControl/PID T: git git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-2.6.git @@ -3762,67 +3244,57 @@ S: Maintained F: net/mac80211/rc80211_pid* MACVLAN DRIVER -P: Patrick McHardy -M: kaber@trash.net +M: Patrick McHardy L: netdev@vger.kernel.org S: Maintained F: drivers/net/macvlan.c F: include/linux/if_macvlan.h MAN-PAGES: MANUAL PAGES FOR LINUX -- Sections 2, 3, 4, 5, and 7 -P: Michael Kerrisk -M: mtk.manpages@gmail.com +M: Michael Kerrisk W: http://www.kernel.org/doc/man-pages L: linux-man@vger.kernel.org S: Maintained MARVELL LIBERTAS WIRELESS DRIVER -P: Dan Williams -M: dcbw@redhat.com +M: Dan Williams L: libertas-dev@lists.infradead.org S: Maintained F: drivers/net/wireless/libertas/ MARVELL MV643XX ETHERNET DRIVER -P: Lennert Buytenhek -M: buytenh@marvell.com +M: Lennert Buytenhek L: netdev@vger.kernel.org S: Supported F: drivers/net/mv643xx_eth.* F: include/linux/mv643xx.h MARVELL SOC MMC/SD/SDIO CONTROLLER DRIVER -P: Nicolas Pitre -M: nico@cam.org +M: Nicolas Pitre S: Maintained MARVELL YUKON / SYSKONNECT DRIVER -P: Mirko Lindner -M: mlindner@syskonnect.de -P: Ralph Roesler -M: rroesler@syskonnect.de +M: Mirko Lindner +M: Ralph Roesler W: http://www.syskonnect.com S: Supported MATROX FRAMEBUFFER DRIVER -P: Petr Vandrovec -M: vandrove@vc.cvut.cz +M: Petr Vandrovec L: linux-fbdev-devel@lists.sourceforge.net (moderated for non-subscribers) S: Maintained F: drivers/video/matrox/matroxfb_* F: include/linux/matroxfb.h MAX6650 HARDWARE MONITOR AND FAN CONTROLLER DRIVER -P: Hans J. Koch -M: hjk@linutronix.de +M: "Hans J. Koch" L: lm-sensors@lm-sensors.org S: Maintained F: Documentation/hwmon/max6650 F: drivers/hwmon/max6650.c MEDIA INPUT INFRASTRUCTURE (V4L/DVB) -P: Mauro Carvalho Chehab -M: mchehab@infradead.org +M: Mauro Carvalho Chehab P: LinuxTV.org Project L: linux-media@vger.kernel.org W: http://linuxtv.org @@ -3836,8 +3308,7 @@ F: include/linux/dvb/ F: include/linux/videodev*.h MEGARAID SCSI DRIVERS -P: Neela Syam Kolli -M: megaraidlinux@lsi.com +M: Neela Syam Kolli L: linux-scsi@vger.kernel.org W: http://megaraid.lsilogic.com S: Maintained @@ -3853,19 +3324,15 @@ F: include/linux/mm.h F: mm/ MEMORY RESOURCE CONTROLLER -P: Balbir Singh -M: balbir@linux.vnet.ibm.com -P: Pavel Emelyanov -M: xemul@openvz.org -P: KAMEZAWA Hiroyuki -M: kamezawa.hiroyu@jp.fujitsu.com +M: Balbir Singh +M: Pavel Emelyanov +M: KAMEZAWA Hiroyuki L: linux-mm@kvack.org S: Maintained F: mm/memcontrol.c MEMORY TECHNOLOGY DEVICES (MTD) -P: David Woodhouse -M: dwmw2@infradead.org +M: David Woodhouse W: http://www.linux-mtd.infradead.org/ L: linux-mtd@lists.infradead.org T: git git://git.infradead.org/mtd-2.6.git @@ -3875,8 +3342,7 @@ F: include/linux/mtd/ F: include/mtd/ MICROBLAZE ARCHITECTURE -P: Michal Simek -M: monstr@monstr.eu +M: Michal Simek L: microblaze-uclinux@itee.uq.edu.au W: http://www.monstr.eu/fdt/ T: git git://git.monstr.eu/linux-2.6-microblaze.git @@ -3884,14 +3350,12 @@ S: Supported F: arch/microblaze/ MICROTEK X6 SCANNER -P: Oliver Neukum -M: oliver@neukum.name +M: Oliver Neukum S: Maintained F: drivers/usb/image/microtek.* MIPS -P: Ralf Baechle -M: ralf@linux-mips.org +M: Ralf Baechle W: http://www.linux-mips.org/ L: linux-mips@linux-mips.org T: git git://git.linux-mips.org/pub/scm/linux.git @@ -3900,8 +3364,7 @@ F: Documentation/mips/ F: arch/mips/ MISCELLANEOUS MCA-SUPPORT -P: James Bottomley -M: James.Bottomley@HansenPartnership.com +M: James Bottomley S: Maintained F: Documentation/ia64/mca.txt F: Documentation/mca.txt @@ -3909,15 +3372,13 @@ F: drivers/mca/ F: include/linux/mca* MODULE SUPPORT -P: Rusty Russell -M: rusty@rustcorp.com.au +M: Rusty Russell S: Maintained F: include/linux/module.h F: kernel/module.c MOTION EYE VAIO PICTUREBOOK CAMERA DRIVER -P: Stelian Pop -M: stelian@popies.net +M: Stelian Pop W: http://popies.net/meye/ S: Maintained F: Documentation/video4linux/meye.txt @@ -3925,135 +3386,112 @@ F: drivers/media/video/meye.* F: include/linux/meye.h MOTOROLA IMX MMC/SD HOST CONTROLLER INTERFACE DRIVER -P: Pavel Pisa -M: ppisa@pikron.com +M: Pavel Pisa L: linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only) S: Maintained F: drivers/mmc/host/imxmmc.* MOUSE AND MISC DEVICES [GENERAL] -P: Alessandro Rubini -M: rubini@ipvvis.unipv.it +M: Alessandro Rubini S: Maintained F: drivers/input/mouse/ F: include/linux/gpio_mouse.h MOXA SMARTIO/INDUSTIO/INTELLIO SERIAL CARD -P: Jiri Slaby -M: jirislaby@gmail.com +M: Jiri Slaby S: Maintained F: Documentation/serial/moxa-smartio F: drivers/char/mxser.* MSI LAPTOP SUPPORT -P: Lennart Poettering -M: mzxreary@0pointer.de +M: Lennart Poettering W: https://tango.0pointer.de/mailman/listinfo/s270-linux W: http://0pointer.de/lennart/tchibo.html S: Maintained F: drivers/platform/x86/msi-laptop.c MULTIFUNCTION DEVICES (MFD) -P: Samuel Ortiz -M: sameo@linux.intel.com +M: Samuel Ortiz T: git git://git.kernel.org/pub/scm/linux/kernel/git/sameo/mfd-2.6.git S: Supported F: drivers/mfd/ MULTIMEDIA CARD (MMC), SECURE DIGITAL (SD) AND SDIO SUBSYSTEM -P: Pierre Ossman -M: pierre@ossman.eu +M: Pierre Ossman S: Maintained F: drivers/mmc/ F: include/linux/mmc/ MULTIMEDIA CARD (MMC) ETC. OVER SPI -P: David Brownell -M: dbrownell@users.sourceforge.net +M: David Brownell S: Odd Fixes F: drivers/mmc/host/mmc_spi.c F: include/linux/spi/mmc_spi.h MULTISOUND SOUND DRIVER -P: Andrew Veliath -M: andrewtv@usa.net +M: Andrew Veliath S: Maintained F: Documentation/sound/oss/MultiSound F: sound/oss/msnd* MULTITECH MULTIPORT CARD (ISICOM) -P: Jiri Slaby -M: jirislaby@gmail.com +M: Jiri Slaby S: Maintained F: drivers/char/isicom.c F: include/linux/isicom.h MUSB MULTIPOINT HIGH SPEED DUAL-ROLE CONTROLLER -P: Felipe Balbi -M: felipe.balbi@nokia.com +M: Felipe Balbi L: linux-usb@vger.kernel.org T: git git://gitorious.org/musb/mainline.git S: Maintained F: drivers/usb/musb/ MYRICOM MYRI-10G 10GbE DRIVER (MYRI10GE) -P: Andrew Gallatin -M: gallatin@myri.com -P: Brice Goglin -M: brice@myri.com +M: Andrew Gallatin +M: Brice Goglin L: netdev@vger.kernel.org W: http://www.myri.com/scs/download-Myri10GE.html S: Supported F: drivers/net/myri10ge/ NATSEMI ETHERNET DRIVER (DP8381x) -P: Tim Hockin -M: thockin@hockin.org +M: Tim Hockin S: Maintained F: drivers/net/natsemi.c NCP FILESYSTEM -P: Petr Vandrovec -M: vandrove@vc.cvut.cz +M: Petr Vandrovec L: linware@sh.cvut.cz S: Maintained F: fs/ncpfs/ NCR DUAL 700 SCSI DRIVER (MICROCHANNEL) -P: James E.J. Bottomley -M: James.Bottomley@HansenPartnership.com +M: "James E.J. Bottomley" L: linux-scsi@vger.kernel.org S: Maintained F: drivers/scsi/NCR_D700.* NETEFFECT IWARP RNIC DRIVER (IW_NES) -P: Faisal Latif -M: faisal.latif@intel.com -P: Chien Tung -M: chien.tin.tung@intel.com +M: Faisal Latif +M: Chien Tung L: general@lists.openfabrics.org W: http://www.neteffect.com S: Supported F: drivers/infiniband/hw/nes/ NETEM NETWORK EMULATOR -P: Stephen Hemminger -M: shemminger@linux-foundation.org +M: Stephen Hemminger L: netem@lists.linux-foundation.org S: Maintained F: net/sched/sch_netem.c NETERION (S2IO) 10GbE DRIVER (xframe/vxge) -P: Ramkrishna Vepa -M: ram.vepa@neterion.com -P: Rastapur Santosh -M: santosh.rastapur@neterion.com -P: Sivakumar Subramani -M: sivakumar.subramani@neterion.com -P: Sreenivasa Honnur -M: sreenivasa.honnur@neterion.com -P: Anil Murthy -M: anil.murthy@neterion.com +M: Ramkrishna Vepa +M: Rastapur Santosh +M: Sivakumar Subramani +M: Sreenivasa Honnur +M: Anil Murthy L: netdev@vger.kernel.org W: http://trac.neterion.com/cgi-bin/trac.cgi/wiki/Linux?Anonymous W: http://trac.neterion.com/cgi-bin/trac.cgi/wiki/X3100Linux?Anonymous @@ -4067,8 +3505,7 @@ P: Marc Boucher P: James Morris P: Harald Welte P: Jozsef Kadlecsik -P: Patrick McHardy -M: kaber@trash.net +M: Patrick McHardy L: netfilter-devel@vger.kernel.org L: netfilter@vger.kernel.org L: coreteam@netfilter.org @@ -4084,8 +3521,7 @@ F: net/*/netfilter/ F: net/netfilter/ NETLABEL -P: Paul Moore -M: paul.moore@hp.com +M: Paul Moore W: http://netlabel.sf.net L: netdev@vger.kernel.org S: Supported @@ -4094,8 +3530,7 @@ F: include/net/netlabel.h F: net/netlabel/ NETROM NETWORK LAYER -P: Ralf Baechle -M: ralf@linux-mips.org +M: Ralf Baechle L: linux-hams@vger.kernel.org W: http://www.linux-ax25.org/ S: Maintained @@ -4104,16 +3539,14 @@ F: include/net/netrom.h F: net/netrom/ NETWORK BLOCK DEVICE (NBD) -P: Paul Clements -M: Paul.Clements@steeleye.com +M: Paul Clements S: Maintained F: Documentation/blockdev/nbd.txt F: drivers/block/nbd.c F: include/linux/nbd.h NETWORKING [GENERAL] -P: David S. Miller -M: davem@davemloft.net +M: "David S. Miller" L: netdev@vger.kernel.org W: http://www.linuxfoundation.org/en/Net T: git git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-2.6.git @@ -4122,18 +3555,12 @@ F: net/ F: include/net/ NETWORKING [IPv4/IPv6] -P: David S. Miller -M: davem@davemloft.net -P: Alexey Kuznetsov -M: kuznet@ms2.inr.ac.ru -P: Pekka Savola (ipv6) -M: pekkas@netcore.fi -P: James Morris -M: jmorris@namei.org -P: Hideaki YOSHIFUJI -M: yoshfuji@linux-ipv6.org -P: Patrick McHardy -M: kaber@trash.net +M: "David S. Miller" +M: Alexey Kuznetsov +M: "Pekka Savola (ipv6)" +M: James Morris +M: Hideaki YOSHIFUJI +M: Patrick McHardy L: netdev@vger.kernel.org T: git git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-2.6.git S: Maintained @@ -4142,14 +3569,12 @@ F: net/ipv6/ F: include/net/ip* NETWORKING [LABELED] (NetLabel, CIPSO, Labeled IPsec, SECMARK) -P: Paul Moore -M: paul.moore@hp.com +M: Paul Moore L: netdev@vger.kernel.org S: Maintained NETWORKING [WIRELESS] -P: John W. Linville -M: linville@tuxdriver.com +M: "John W. Linville" L: linux-wireless@vger.kernel.org T: git git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-2.6.git S: Maintained @@ -4165,16 +3590,14 @@ S: Odd Fixes F: drivers/net/ NETXEN (1/10) GbE SUPPORT -P: Dhananjay Phadke -M: dhananjay@netxen.com +M: Dhananjay Phadke L: netdev@vger.kernel.org W: http://www.netxen.com S: Supported F: drivers/net/netxen/ NFS, SUNRPC, AND LOCKD CLIENTS -P: Trond Myklebust -M: Trond.Myklebust@netapp.com +M: Trond Myklebust L: linux-nfs@vger.kernel.org W: http://client.linux-nfs.org T: git git://git.linux-nfs.org/pub/linux/nfs-2.6.git @@ -4188,17 +3611,14 @@ F: include/linux/nfs* F: include/linux/sunrpc/ NI5010 NETWORK DRIVER -P: Jan-Pascal van Best -M: janpascal@vanbest.org -P: Andreas Mohr -M: andi@lisas.de +M: Jan-Pascal van Best +M: Andreas Mohr L: netdev@vger.kernel.org S: Maintained F: drivers/net/ni5010.* NILFS2 FILESYSTEM -P: KONISHI Ryusuke -M: konishi.ryusuke@lab.ntt.co.jp +M: KONISHI Ryusuke L: users@nilfs.org W: http://www.nilfs.org/en/ S: Supported @@ -4207,26 +3627,22 @@ F: fs/nilfs2/ F: include/linux/nilfs2_fs.h NINJA SCSI-3 / NINJA SCSI-32Bi (16bit/CardBus) PCMCIA SCSI HOST ADAPTER DRIVER -P: YOKOTA Hiroshi -M: yokota@netlab.is.tsukuba.ac.jp +M: YOKOTA Hiroshi W: http://www.netlab.is.tsukuba.ac.jp/~yokota/izumi/ninja/ S: Maintained F: Documentation/scsi/NinjaSCSI.txt F: drivers/scsi/pcmcia/nsp_* NINJA SCSI-32Bi/UDE PCI/CARDBUS SCSI HOST ADAPTER DRIVER -P: GOTO Masanori -M: gotom@debian.or.jp -P: YOKOTA Hiroshi -M: yokota@netlab.is.tsukuba.ac.jp +M: GOTO Masanori +M: YOKOTA Hiroshi W: http://www.netlab.is.tsukuba.ac.jp/~yokota/izumi/ninja/ S: Maintained F: Documentation/scsi/NinjaSCSI.txt F: drivers/scsi/nsp32* NTFS FILESYSTEM -P: Anton Altaparmakov -M: aia21@cantab.net +M: Anton Altaparmakov L: linux-ntfs-dev@lists.sourceforge.net W: http://www.linux-ntfs.org/ T: git git://git.kernel.org/pub/scm/linux/kernel/git/aia21/ntfs-2.6.git @@ -4235,16 +3651,14 @@ F: Documentation/filesystems/ntfs.txt F: fs/ntfs/ NVIDIA (rivafb and nvidiafb) FRAMEBUFFER DRIVER -P: Antonino Daplas -M: adaplas@gmail.com +M: Antonino Daplas L: linux-fbdev-devel@lists.sourceforge.net (moderated for non-subscribers) S: Maintained F: drivers/video/riva/ F: drivers/video/nvidia/ OMAP SUPPORT -P: Tony Lindgren -M: tony@atomide.com +M: "Tony Lindgren " L: linux-omap@vger.kernel.org W: http://www.muru.com/linux/omap/ W: http://linux.omap.com/ @@ -4253,97 +3667,83 @@ S: Maintained F: arch/arm/*omap* OMAP CLOCK FRAMEWORK SUPPORT -P: Paul Walmsley -M: paul@pwsan.com +M: Paul Walmsley L: linux-omap@vger.kernel.org S: Maintained F: arch/arm/*omap*/*clock* OMAP POWER MANAGEMENT SUPPORT -P: Kevin Hilman -M: khilman@deeprootsystems.com +M: Kevin Hilman L: linux-omap@vger.kernel.org S: Maintained F: arch/arm/*omap*/*pm* OMAP AUDIO SUPPORT -P: Jarkko Nikula -M: jhnikula@gmail.com +M: Jarkko Nikula L: alsa-devel@alsa-project.org (subscribers-only) L: linux-omap@vger.kernel.org S: Maintained F: sound/soc/omap/ OMAP FRAMEBUFFER SUPPORT -P: Imre Deak -M: imre.deak@nokia.com +M: Imre Deak L: linux-fbdev-devel@lists.sourceforge.net (moderated for non-subscribers) L: linux-omap@vger.kernel.org S: Maintained F: drivers/video/omap/ OMAP MMC SUPPORT -P: Jarkko Lavinen -M: jarkko.lavinen@nokia.com +M: Jarkko Lavinen L: linux-omap@vger.kernel.org S: Maintained F: drivers/mmc/host/*omap* OMAP RANDOM NUMBER GENERATOR SUPPORT -P: Deepak Saxena -M: dsaxena@plexity.net +M: Deepak Saxena S: Maintained F: drivers/char/hw_random/omap-rng.c OMAP USB SUPPORT -P: Felipe Balbi -M: felipe.balbi@nokia.com -P: David Brownell -M: dbrownell@users.sourceforge.net +M: Felipe Balbi +M: David Brownell L: linux-usb@vger.kernel.org L: linux-omap@vger.kernel.org S: Maintained OMFS FILESYSTEM -P: Bob Copeland -M: me@bobcopeland.com +M: Bob Copeland L: linux-karma-devel@lists.sourceforge.net S: Maintained F: Documentation/filesystems/omfs.txt F: fs/omfs/ OMNIKEY CARDMAN 4000 DRIVER -P: Harald Welte -M: laforge@gnumonks.org +M: Harald Welte S: Maintained F: drivers/char/pcmcia/cm4000_cs.c F: include/linux/cm4000_cs.h OMNIKEY CARDMAN 4040 DRIVER -P: Harald Welte -M: laforge@gnumonks.org +M: Harald Welte S: Maintained F: drivers/char/pcmcia/cm4040_cs.* OMNIVISION OV7670 SENSOR DRIVER -P: Jonathan Corbet -M: corbet@lwn.net +M: Jonathan Corbet L: linux-media@vger.kernel.org T: git git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-2.6.git S: Maintained F: drivers/media/video/ov7670.c ONENAND FLASH DRIVER -P: Kyungmin Park -M: kyungmin.park@samsung.com +M: Kyungmin Park L: linux-mtd@lists.infradead.org S: Maintained F: drivers/mtd/onenand/ F: include/linux/mtd/onenand*.h ONSTREAM SCSI TAPE DRIVER -P: Willem Riede -M: osst@riede.org +M: Willem Riede L: osst-users@lists.sourceforge.net L: linux-scsi@vger.kernel.org S: Maintained @@ -4351,16 +3751,14 @@ F: drivers/scsi/osst* F: drivers/scsi/st* OPENCORES I2C BUS DRIVER -P: Peter Korsgaard -M: jacmet@sunsite.dk +M: Peter Korsgaard L: linux-i2c@vger.kernel.org S: Maintained F: Documentation/i2c/busses/i2c-ocores F: drivers/i2c/busses/i2c-ocores.c OPROFILE -P: Robert Richter -M: robert.richter@amd.com +M: Robert Richter L: oprofile-list@lists.sf.net S: Maintained F: arch/*/oprofile/ @@ -4368,10 +3766,8 @@ F: drivers/oprofile/ F: include/linux/oprofile.h ORACLE CLUSTER FILESYSTEM 2 (OCFS2) -P: Mark Fasheh -M: mfasheh@suse.com -P: Joel Becker -M: joel.becker@oracle.com +M: Mark Fasheh +M: Joel Becker L: ocfs2-devel@oss.oracle.com (moderated for non-subscribers) W: http://oss.oracle.com/projects/ocfs2/ T: git git://git.kernel.org/pub/scm/linux/kernel/git/jlbec/ocfs2.git @@ -4381,10 +3777,8 @@ F: Documentation/filesystems/dlmfs.txt F: fs/ocfs2/ ORINOCO DRIVER -P: Pavel Roskin -M: proski@gnu.org -P: David Gibson -M: hermes@gibson.dropbear.id.au +M: Pavel Roskin +M: David Gibson L: linux-wireless@vger.kernel.org L: orinoco-users@lists.sourceforge.net L: orinoco-devel@lists.sourceforge.net @@ -4393,10 +3787,8 @@ S: Maintained F: drivers/net/wireless/orinoco/ OSD LIBRARY and FILESYSTEM -P: Boaz Harrosh -M: bharrosh@panasas.com -P: Benny Halevy -M: bhalevy@panasas.com +M: Boaz Harrosh +M: Benny Halevy L: osd-dev@open-osd.org W: http://open-osd.org T: git git://git.open-osd.org/open-osd.git @@ -4406,8 +3798,7 @@ F: drivers/include/scsi/osd_* F: fs/exofs/ P54 WIRELESS DRIVER -P: Michael Wu -M: flamingice@sourmilk.net +M: Michael Wu L: linux-wireless@vger.kernel.org W: http://prism54.org T: git git://git.kernel.org/pub/scm/linux/kernel/git/mwu/mac80211-drivers.git @@ -4415,30 +3806,25 @@ S: Maintained F: drivers/net/wireless/p54/ PA SEMI ETHERNET DRIVER -P: Olof Johansson -M: olof@lixom.net +M: Olof Johansson L: netdev@vger.kernel.org S: Maintained F: drivers/net/pasemi_mac.* PA SEMI SMBUS DRIVER -P: Olof Johansson -M: olof@lixom.net +M: Olof Johansson L: linux-i2c@vger.kernel.org S: Maintained F: drivers/i2c/busses/i2c-pasemi.c PANASONIC LAPTOP ACPI EXTRAS DRIVER -P: Harald Welte -M: laforge@gnumonks.org +M: Harald Welte S: Maintained F: drivers/platform/x86/panasonic-laptop.c PANASONIC MN10300/AM33 PORT -P: David Howells -M: dhowells@redhat.com -P: Koichi Yasutake -M: yasutake.koichi@jp.panasonic.com +M: David Howells +M: Koichi Yasutake L: linux-am33-list@redhat.com (moderated for non-subscribers) W: ftp://ftp.redhat.com/pub/redhat/gnupro/AM33/ S: Maintained @@ -4454,14 +3840,10 @@ F: drivers/char/ppdev.c F: include/linux/ppdev.h PARAVIRT_OPS INTERFACE -P: Jeremy Fitzhardinge -M: jeremy@xensource.com -P: Chris Wright -M: chrisw@sous-sol.org -P: Alok Kataria -M: akataria@vmware.com -P: Rusty Russell -M: rusty@rustcorp.com.au +M: Jeremy Fitzhardinge +M: Chris Wright +M: Alok Kataria +M: Rusty Russell L: virtualization@lists.osdl.org S: Supported F: Documentation/ia64/paravirt_ops.txt @@ -4469,8 +3851,7 @@ F: arch/*/kernel/paravirt* F: arch/*/include/asm/paravirt.h PARIDE DRIVERS FOR PARALLEL PORT IDE DEVICES -P: Tim Waugh -M: tim@cyberelk.net +M: Tim Waugh L: linux-parport@lists.infradead.org (subscribers-only) W: http://www.torque.net/linux-pp.html S: Maintained @@ -4478,10 +3859,8 @@ F: Documentation/blockdev/paride.txt F: drivers/block/paride/ PARISC ARCHITECTURE -P: Kyle McMartin -M: kyle@mcmartin.ca -P: Helge Deller -M: deller@gmx.de +M: Kyle McMartin +M: Helge Deller L: linux-parisc@vger.kernel.org W: http://www.parisc-linux.org/ T: git git://git.kernel.org/pub/scm/linux/kernel/git/kyle/parisc-2.6.git @@ -4490,37 +3869,32 @@ F: arch/parisc/ F: drivers/parisc/ PC87360 HARDWARE MONITORING DRIVER -P: Jim Cromie -M: jim.cromie@gmail.com +M: Jim Cromie L: lm-sensors@lm-sensors.org S: Maintained F: Documentation/hwmon/pc87360 F: drivers/hwmon/pc87360.c PC8736x GPIO DRIVER -P: Jim Cromie -M: jim.cromie@gmail.com +M: Jim Cromie S: Maintained F: drivers/char/pc8736x_gpio.c PCA9532 LED DRIVER -P: Riku Voipio -M: riku.voipio@iki.fi +M: Riku Voipio S: Maintained F: drivers/leds/leds-pca9532.c F: include/linux/leds-pca9532.h PCI ERROR RECOVERY -P: Linas Vepstas -M: linas@austin.ibm.com +M: Linas Vepstas L: linux-pci@vger.kernel.org S: Supported F: Documentation/PCI/pci-error-recovery.txt F: Documentation/powerpc/eeh-pci-error-recovery.txt PCI SUBSYSTEM -P: Jesse Barnes -M: jbarnes@virtuousgeek.org +M: Jesse Barnes L: linux-pci@vger.kernel.org T: git git://git.kernel.org/pub/scm/linux/kernel/git/jbarnes/pci-2.6.git S: Supported @@ -4529,8 +3903,7 @@ F: drivers/pci/ F: include/linux/pci* PCIE HOTPLUG DRIVER -P: Kristen Carlson Accardi -M: kristen.c.accardi@intel.com +M: Kristen Carlson Accardi L: linux-pci@vger.kernel.org S: Supported F: drivers/pci/pcie/ @@ -4546,113 +3919,94 @@ F: drivers/pcmcia/ F: include/pcmcia/ PCNET32 NETWORK DRIVER -P: Don Fry -M: pcnet32@verizon.net +M: Don Fry L: netdev@vger.kernel.org S: Maintained F: drivers/net/pcnet32.c PER-TASK DELAY ACCOUNTING -P: Balbir Singh -M: balbir@linux.vnet.ibm.com +M: Balbir Singh S: Maintained F: include/linux/delayacct.h F: kernel/delayacct.c PERFORMANCE COUNTER SUBSYSTEM -P: Peter Zijlstra -M: a.p.zijlstra@chello.nl -P: Paul Mackerras -M: paulus@samba.org -P: Ingo Molnar -M: mingo@elte.hu +M: Peter Zijlstra +M: Paul Mackerras +M: Ingo Molnar S: Supported PERSONALITY HANDLING -P: Christoph Hellwig -M: hch@infradead.org +M: Christoph Hellwig L: linux-abi-devel@lists.sourceforge.net S: Maintained F: include/linux/personality.h PHRAM MTD DRIVER -P: Joern Engel -M: joern@lazybastard.org +M: Joern Engel L: linux-mtd@lists.infradead.org S: Maintained F: drivers/mtd/devices/phram.c PKTCDVD DRIVER -P: Peter Osterlund -M: petero2@telia.com +M: Peter Osterlund S: Maintained F: drivers/block/pktcdvd.c F: include/linux/pktcdvd.h POSIX CLOCKS and TIMERS -P: Thomas Gleixner -M: tglx@linutronix.de +M: Thomas Gleixner S: Supported F: fs/timerfd.c F: include/linux/timer* F: kernel/*timer* POWER SUPPLY CLASS/SUBSYSTEM and DRIVERS -P: Anton Vorontsov -M: cbou@mail.ru -P: David Woodhouse -M: dwmw2@infradead.org +M: Anton Vorontsov +M: David Woodhouse T: git git://git.infradead.org/battery-2.6.git S: Maintained F: include/linux/power_supply.h F: drivers/power/power_supply* PNP SUPPORT -P: Adam Belay -M: abelay@mit.edu -P: Bjorn Helgaas -M: bjorn.helgaas@hp.com +M: Adam Belay +M: Bjorn Helgaas S: Maintained F: drivers/pnp/ PNXxxxx I2C DRIVER -P: Vitaly Wool -M: vitalywool@gmail.com +M: Vitaly Wool L: linux-i2c@vger.kernel.org S: Maintained F: drivers/i2c/busses/i2c-pnx.c PPP PROTOCOL DRIVERS AND COMPRESSORS -P: Paul Mackerras -M: paulus@samba.org +M: Paul Mackerras L: linux-ppp@vger.kernel.org S: Maintained F: drivers/net/ppp_* PPP OVER ATM (RFC 2364) -P: Mitchell Blank Jr -M: mitch@sfgoth.com +M: Mitchell Blank Jr S: Maintained F: net/atm/pppoatm.c F: include/linux/atmppp.h PPP OVER ETHERNET -P: Michal Ostrowski -M: mostrows@earthlink.net +M: Michal Ostrowski S: Maintained F: drivers/net/pppoe.c F: drivers/net/pppox.c PPP OVER L2TP -P: James Chapman -M: jchapman@katalix.com +M: James Chapman S: Maintained F: drivers/net/pppol2tp.c F: include/linux/if_pppol2tp.h PPS SUPPORT -P: Rodolfo Giometti -M: giometti@enneenne.com +M: Rodolfo Giometti W: http://wiki.enneenne.com/index.php/LinuxPPS_support L: linuxpps@ml.enneenne.com (subscribers-only) S: Maintained @@ -4661,8 +4015,7 @@ F: drivers/pps/ F: include/linux/pps*.h PREEMPTIBLE KERNEL -P: Robert Love -M: rml@tech9.net +M: Robert Love L: kpreempt-tech@lists.sourceforge.net W: ftp://ftp.kernel.org/pub/linux/kernel/people/rml/preempt-kernel S: Supported @@ -4670,37 +4023,32 @@ F: Documentation/preempt-locking.txt F: include/linux/preempt.h PRISM54 WIRELESS DRIVER -P: Luis R. Rodriguez -M: mcgrof@gmail.com +M: "Luis R. Rodriguez" L: linux-wireless@vger.kernel.org W: http://prism54.org S: Maintained F: drivers/net/wireless/prism54/ PROMISE DC4030 CACHING DISK CONTROLLER DRIVER -P: Peter Denison -M: promise@pnd-pc.demon.co.uk +M: Peter Denison W: http://www.pnd-pc.demon.co.uk/promise/ S: Maintained PROMISE SATA TX2/TX4 CONTROLLER LIBATA DRIVER -P: Mikael Pettersson -M: mikpe@it.uu.se +M: Mikael Pettersson L: linux-ide@vger.kernel.org S: Maintained F: drivers/ata/sata_promise.* PS3 NETWORK SUPPORT -P: Geoff Levand -M: geoffrey.levand@am.sony.com +M: Geoff Levand L: netdev@vger.kernel.org L: cbe-oss-dev@ozlabs.org S: Supported F: drivers/net/ps3_gelic_net.* PS3 PLATFORM SUPPORT -P: Geoff Levand -M: geoffrey.levand@am.sony.com +M: Geoff Levand L: linuxppc-dev@ozlabs.org L: cbe-oss-dev@ozlabs.org S: Supported @@ -4715,16 +4063,13 @@ F: drivers/usb/host/*ps3.c F: sound/ppc/snd_ps3* PS3VRAM DRIVER -P: Jim Paris -M: jim@jtan.com +M: Jim Paris L: cbe-oss-dev@ozlabs.org S: Maintained PTRACE SUPPORT -P: Roland McGrath -M: roland@redhat.com -P: Oleg Nesterov -M: oleg@redhat.com +M: Roland McGrath +M: Oleg Nesterov S: Maintained F: include/asm-generic/syscall.h F: include/linux/ptrace.h @@ -4733,8 +4078,7 @@ F: include/linux/tracehook.h F: kernel/ptrace.c PVRUSB2 VIDEO4LINUX DRIVER -P: Mike Isely -M: isely@pobox.com +M: Mike Isely L: pvrusb2@isely.net (subscribers-only) L: linux-media@vger.kernel.org W: http://www.isely.net/pvrusb2/ @@ -4744,10 +4088,8 @@ F: Documentation/video4linux/README.pvrusb2 F: drivers/media/video/pvrusb2/ PXA2xx/PXA3xx SUPPORT -P: Eric Miao -M: eric.y.miao@gmail.com -P: Russell King -M: linux@arm.linux.org.uk +M: Eric Miao +M: Russell King L: linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only) S: Maintained F: arch/arm/mach-pxa/ @@ -4759,17 +4101,14 @@ F: sound/arm/pxa* F: sound/soc/pxa PXA168 SUPPORT -P: Eric Miao -M: eric.y.miao@gmail.com -P: Jason Chagas -M: jason.chagas@marvell.com +M: Eric Miao +M: Jason Chagas L: linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only) T: git git://git.kernel.org/pub/scm/linux/kernel/git/ycmiao/pxa-linux-2.6.git S: Maintained PXA910 SUPPORT -P: Eric Miao -M: eric.y.miao@gmail.com +M: Eric Miao L: linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only) T: git git://git.kernel.org/pub/scm/linux/kernel/git/ycmiao/pxa-linux-2.6.git S: Maintained @@ -4778,14 +4117,12 @@ PXA MMCI DRIVER S: Orphan PXA RTC DRIVER -P: Robert Jarzmik -M: robert.jarzmik@free.fr +M: Robert Jarzmik L: rtc-linux@googlegroups.com S: Maintained QLOGIC QLA2XXX FC-SCSI DRIVER -P: Andrew Vasquez -M: andrew.vasquez@qlogic.com +M: Andrew Vasquez M: linux-driver@qlogic.com L: linux-scsi@vger.kernel.org S: Supported @@ -4793,8 +4130,7 @@ F: Documentation/scsi/LICENSE.qla2xxx F: drivers/scsi/qla2xxx/ QLOGIC QLA3XXX NETWORK DRIVER -P: Ron Mercer -M: ron.mercer@qlogic.com +M: Ron Mercer M: linux-driver@qlogic.com L: netdev@vger.kernel.org S: Supported @@ -4802,16 +4138,14 @@ F: Documentation/networking/LICENSE.qla3xxx F: drivers/net/qla3xxx.* QLOGIC QLGE 10Gb ETHERNET DRIVER -P: Ron Mercer -M: ron.mercer@qlogic.com +M: Ron Mercer M: linux-driver@qlogic.com L: netdev@vger.kernel.org S: Supported F: drivers/net/qlge/ QNX4 FILESYSTEM -P: Anders Larsen -M: al@alarsen.net +M: Anders Larsen W: http://www.alarsen.net/linux/qnx4fs/ S: Maintained F: fs/qnx4/ @@ -4819,16 +4153,14 @@ F: include/linux/qnx4_fs.h F: include/linux/qnxtypes.h RADEON FRAMEBUFFER DISPLAY DRIVER -P: Benjamin Herrenschmidt -M: benh@kernel.crashing.org +M: Benjamin Herrenschmidt L: linux-fbdev-devel@lists.sourceforge.net (moderated for non-subscribers) S: Maintained F: drivers/video/aty/radeon* F: include/linux/radeonfb.h RAGE128 FRAMEBUFFER DISPLAY DRIVER -P: Paul Mackerras -M: paulus@samba.org +M: Paul Mackerras L: linux-fbdev-devel@lists.sourceforge.net (moderated for non-subscribers) S: Maintained F: drivers/video/aty/aty128fb.c @@ -4843,64 +4175,53 @@ T: git git://git.kernel.org/pub/scm/linux/kernel/git/ivd/rt2x00.git F: drivers/net/wireless/rt2x00/ RAMDISK RAM BLOCK DEVICE DRIVER -P: Nick Piggin -M: npiggin@suse.de +M: Nick Piggin S: Maintained F: Documentation/blockdev/ramdisk.txt F: drivers/block/brd.c RANDOM NUMBER DRIVER -P: Matt Mackall -M: mpm@selenic.com +M: Matt Mackall S: Maintained F: drivers/char/random.c RAPIDIO SUBSYSTEM -P: Matt Porter -M: mporter@kernel.crashing.org +M: Matt Porter S: Maintained F: drivers/rapidio/ RAYLINK/WEBGEAR 802.11 WIRELESS LAN DRIVER -P: Corey Thomas -M: coreythomas@charter.net +M: Corey Thomas L: linux-wireless@vger.kernel.org S: Maintained F: drivers/net/wireless/ray* RCUTORTURE MODULE -P: Josh Triplett -M: josh@freedesktop.org -P: Paul E. McKenney -M: paulmck@linux.vnet.ibm.com +M: Josh Triplett +M: "Paul E. McKenney" S: Maintained F: Documentation/RCU/torture.txt F: kernel/rcutorture.c RDC R-321X SoC -P: Florian Fainelli -M: florian@openwrt.org +M: Florian Fainelli S: Maintained RDC R6040 FAST ETHERNET DRIVER -P: Florian Fainelli -M: florian@openwrt.org +M: Florian Fainelli L: netdev@vger.kernel.org S: Maintained F: drivers/net/r6040.c RDS - RELIABLE DATAGRAM SOCKETS -P: Andy Grover -M: andy.grover@oracle.com +M: Andy Grover L: rds-devel@oss.oracle.com (moderated for non-subscribers) S: Supported F: net/rds/ READ-COPY UPDATE (RCU) -P: Dipankar Sarma -M: dipankar@in.ibm.com -P: Paul E. McKenney -M: paulmck@linux.vnet.ibm.com +M: Dipankar Sarma +M: "Paul E. McKenney" W: http://www.rdrop.com/users/paulmck/rclock/ S: Supported F: Documentation/RCU/rcu.txt @@ -4910,16 +4231,14 @@ F: include/linux/srcu.h F: kernel/rcupdate.c REAL TIME CLOCK DRIVER -P: Paul Gortmaker -M: p_gortmaker@yahoo.com +M: Paul Gortmaker S: Maintained F: Documentation/rtc.txt F: drivers/rtc/ F: include/linux/rtc.h REAL TIME CLOCK (RTC) SUBSYSTEM -P: Alessandro Zummo -M: a.zummo@towertech.it +M: Alessandro Zummo L: rtc-linux@googlegroups.com S: Maintained F: Documentation/rtc.txt @@ -4932,8 +4251,7 @@ S: Supported F: fs/reiserfs/ RFKILL -P: Johannes Berg -M: johannes@sipsolutions.net +M: Johannes Berg L: linux-wireless@vger.kernel.org S: Maintained F Documentation/rfkill.txt @@ -4952,8 +4270,7 @@ F: Documentation/serial/rocket.txt F: drivers/char/rocket* ROSE NETWORK LAYER -P: Ralf Baechle -M: ralf@linux-mips.org +M: Ralf Baechle L: linux-hams@vger.kernel.org W: http://www.linux-ax25.org/ S: Maintained @@ -4962,8 +4279,7 @@ F: include/net/rose.h F: net/rose/ RTL8180 WIRELESS DRIVER -P: John W. Linville -M: linville@tuxdriver.com +M: "John W. Linville" L: linux-wireless@vger.kernel.org W: http://linuxwireless.org/ T: git git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-testing.git @@ -4971,12 +4287,9 @@ S: Maintained F: drivers/net/wireless/rtl818* RTL8187 WIRELESS DRIVER -P: Herton Ronaldo Krzesinski -M: herton@mandriva.com.br -P: Hin-Tak Leung -M: htl10@users.sourceforge.net -P: Larry Finger -M: Larry.Finger@lwfinger.net +M: Herton Ronaldo Krzesinski +M: Hin-Tak Leung +M: Larry Finger L: linux-wireless@vger.kernel.org W: http://linuxwireless.org/ T: git git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-testing.git @@ -4984,17 +4297,14 @@ S: Maintained F: drivers/net/wireless/rtl818x/rtl8187* S3 SAVAGE FRAMEBUFFER DRIVER -P: Antonino Daplas -M: adaplas@gmail.com +M: Antonino Daplas L: linux-fbdev-devel@lists.sourceforge.net (moderated for non-subscribers) S: Maintained F: drivers/video/savage/ S390 -P: Martin Schwidefsky -M: schwidefsky@de.ibm.com -P: Heiko Carstens -M: heiko.carstens@de.ibm.com +M: Martin Schwidefsky +M: Heiko Carstens M: linux390@de.ibm.com L: linux-s390@vger.kernel.org W: http://www.ibm.com/developerworks/linux/linux390/ @@ -5002,10 +4312,8 @@ S: Supported F: arch/s390/ S390 NETWORK DRIVERS -P: Ursula Braun -M: ursula.braun@de.ibm.com -P: Frank Blaschka -M: blaschka@linux.vnet.ibm.com +M: Ursula Braun +M: Frank Blaschka M: linux390@de.ibm.com L: linux-s390@vger.kernel.org W: http://www.ibm.com/developerworks/linux/linux390/ @@ -5013,20 +4321,16 @@ S: Supported F: drivers/s390/net/ S390 ZCRYPT DRIVER -P: Felix Beck -M: felix.beck@de.ibm.com -P: Ralph Wuerthner -M: ralph.wuerthner@de.ibm.com +M: Felix Beck +M: Ralph Wuerthner M: linux390@de.ibm.com L: linux-s390@vger.kernel.org S: Supported F: drivers/s390/crypto/ S390 ZFCP DRIVER -P: Christof Schmitt -M: christof.schmitt@de.ibm.com -P: Martin Peschke -M: mp3@de.ibm.com +M: Christof Schmitt +M: Martin Peschke M: linux390@de.ibm.com L: linux-s390@vger.kernel.org W: http://www.ibm.com/developerworks/linux/linux390/ @@ -5035,8 +4339,7 @@ F: Documentation/s390/zfcpdump.txt F: drivers/s390/scsi/zfcp_* S390 IUCV NETWORK LAYER -P: Ursula Braun -M: ursula.braun@de.ibm.com +M: Ursula Braun M: linux390@de.ibm.com L: linux-s390@vger.kernel.org W: http://www.ibm.com/developerworks/linux/linux390/ @@ -5046,15 +4349,13 @@ F: include/net/iucv/ F: net/iucv/ S3C24XX SD/MMC Driver -P: Ben Dooks -M: ben-linux@fluff.org +M: Ben Dooks L: linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only) S: Supported F: drivers/mmc/host/s3cmci.* SAA7146 VIDEO4LINUX-2 DRIVER -P: Michael Hunold -M: michael@mihu.de +M: Michael Hunold L: linux-media@vger.kernel.org T: git git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-2.6.git W: http://www.mihu.de/linux/saa7146 @@ -5064,31 +4365,26 @@ F: drivers/media/video/*7146* F: include/media/*7146* SC1200 WDT DRIVER -P: Zwane Mwaikambo -M: zwane@arm.linux.org.uk +M: Zwane Mwaikambo S: Maintained F: drivers/watchdog/sc1200wdt.c SCHEDULER -P: Ingo Molnar -M: mingo@elte.hu -P: Peter Zijlstra -M: peterz@infradead.org +M: Ingo Molnar +M: Peter Zijlstra S: Maintained F: kernel/sched* F: include/linux/sched.h SCSI CDROM DRIVER -P: Jens Axboe -M: axboe@kernel.dk +M: Jens Axboe L: linux-scsi@vger.kernel.org W: http://www.kernel.dk S: Maintained F: drivers/scsi/sr* SCSI SG DRIVER -P: Doug Gilbert -M: dgilbert@interlog.com +M: Doug Gilbert L: linux-scsi@vger.kernel.org W: http://www.torque.net/sg S: Maintained @@ -5096,8 +4392,7 @@ F: drivers/scsi/sg.c F: include/scsi/sg.h SCSI SUBSYSTEM -P: James E.J. Bottomley -M: James.Bottomley@HansenPartnership.com +M: "James E.J. Bottomley" L: linux-scsi@vger.kernel.org T: git git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi-misc-2.6.git T: git git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi-rc-fixes-2.6.git @@ -5107,18 +4402,15 @@ F: drivers/scsi/ F: include/scsi/ SCSI TAPE DRIVER -P: Kai Mäkisara -M: Kai.Makisara@kolumbus.fi +M: Kai Mäkisara L: linux-scsi@vger.kernel.org S: Maintained F: Documentation/scsi/st.txt F: drivers/scsi/st* SCTP PROTOCOL -P: Vlad Yasevich -M: vladislav.yasevich@hp.com -P: Sridhar Samudrala -M: sri@us.ibm.com +M: Vlad Yasevich +M: Sridhar Samudrala L: linux-sctp@vger.kernel.org W: http://lksctp.sourceforge.net S: Supported @@ -5128,8 +4420,7 @@ F: include/net/sctp/ F: net/sctp/ SCx200 CPU SUPPORT -P: Jim Cromie -M: jim.cromie@gmail.com +M: Jim Cromie S: Odd Fixes F: Documentation/i2c/busses/scx200_acb F: arch/x86/kernel/scx200_32.c @@ -5139,49 +4430,42 @@ F: drivers/mtd/maps/scx200_docflash.c F: include/linux/scx200.h SCx200 GPIO DRIVER -P: Jim Cromie -M: jim.cromie@gmail.com +M: Jim Cromie S: Maintained F: drivers/char/scx200_gpio.c F: include/linux/scx200_gpio.h SCx200 HRT CLOCKSOURCE DRIVER -P: Jim Cromie -M: jim.cromie@gmail.com +M: Jim Cromie S: Maintained F: drivers/clocksource/scx200_hrt.c SDRICOH_CS MMC/SD HOST CONTROLLER INTERFACE DRIVER -P: Sascha Sommer -M: saschasommer@freenet.de +M: Sascha Sommer L: sdricohcs-devel@lists.sourceforge.net (subscribers-only) S: Maintained F: drivers/mmc/host/sdricoh_cs.c SECURE DIGITAL HOST CONTROLLER INTERFACE (SDHCI) DRIVER -P: Pierre Ossman -M: pierre@ossman.eu +M: Pierre Ossman L: sdhci-devel@lists.ossman.eu S: Maintained SECURE DIGITAL HOST CONTROLLER INTERFACE, OPEN FIRMWARE BINDINGS (SDHCI-OF) -P: Anton Vorontsov -M: avorontsov@ru.mvista.com +M: Anton Vorontsov L: linuxppc-dev@ozlabs.org L: sdhci-devel@lists.ossman.eu S: Maintained F: drivers/mmc/host/sdhci.* SECURE DIGITAL HOST CONTROLLER INTERFACE (SDHCI) SAMSUNG DRIVER -P: Ben Dooks -M: ben-linux@fluff.org +M: Ben Dooks L: sdhci-devel@lists.ossman.eu S: Maintained F: drivers/mmc/host/sdhci-s3c.c SECURITY SUBSYSTEM -P: James Morris -M: jmorris@namei.org +M: James Morris L: linux-security-module@vger.kernel.org (suggested Cc:) T: git git://www.kernel.org/pub/scm/linux/kernel/git/jmorris/security-testing-2.6.git W: http://security.wiki.kernel.org/ @@ -5189,17 +4473,13 @@ S: Supported F: security/ SECURITY CONTACT -P: Security Officers -M: security@kernel.org +M: Security Officers S: Supported SELINUX SECURITY MODULE -P: Stephen Smalley -M: sds@tycho.nsa.gov -P: James Morris -M: jmorris@namei.org -P: Eric Paris -M: eparis@parisplace.org +M: Stephen Smalley +M: James Morris +M: Eric Paris L: selinux@tycho.nsa.gov (subscribers-only, general discussion) W: http://selinuxproject.org T: git git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/security-testing-2.6.git @@ -5208,15 +4488,13 @@ F: include/linux/selinux* F: security/selinux/ SENSABLE PHANTOM -P: Jiri Slaby -M: jirislaby@gmail.com +M: Jiri Slaby S: Maintained F: drivers/misc/phantom.c F: include/linux/phantom.h SERIAL ATA (SATA) SUBSYSTEM -P: Jeff Garzik -M: jgarzik@pobox.com +M: Jeff Garzik L: linux-ide@vger.kernel.org T: git git://git.kernel.org/pub/scm/linux/kernel/git/jgarzik/libata-dev.git S: Supported @@ -5225,10 +4503,8 @@ F: include/linux/ata.h F: include/linux/libata.h SERVER ENGINES 10Gbps NIC - BladeEngine 2 DRIVER -P: Sathya Perla -M: sathyap@serverengines.com -P: Subbu Seetharaman -M: subbus@serverengines.com +M: Sathya Perla +M: Subbu Seetharaman L: netdev@vger.kernel.org W: http://www.serverengines.com S: Supported @@ -5237,20 +4513,17 @@ F: drivers/net/benet/ SFC NETWORK DRIVER P: Steve Hodgson P: Ben Hutchings -P: Robert Stonehouse -M: linux-net-drivers@solarflare.com +M: Robert Stonehouse S: Supported F: drivers/net/sfc/ SGI GRU DRIVER -P: Jack Steiner -M: steiner@sgi.com +M: Jack Steiner S: Maintained F: drivers/misc/sgi-gru/ SGI SN-IA64 (Altix) SERIAL CONSOLE DRIVER -P: Pat Gefre -M: pfg@sgi.com +M: Pat Gefre L: linux-ia64@vger.kernel.org S: Supported F: Documentation/ia64/serial.txt @@ -5258,22 +4531,19 @@ F: drivers/serial/ioc?_serial.c F: include/linux/ioc?.h SGI VISUAL WORKSTATION 320 AND 540 -P: Andrey Panin -M: pazke@donpac.ru +M: Andrey Panin L: linux-visws-devel@lists.sf.net W: http://linux-visws.sf.net S: Maintained for 2.6. F: Documentation/sgi-visws.txt SGI XP/XPC/XPNET DRIVER -P: Robin Holt -M: holt@sgi.com +M: Robin Holt S: Maintained F: drivers/misc/sgi-xp/ SHARP LH SUPPORT (LH7952X & LH7A40X) -P: Marc Singer -M: elf@buici.com +M: Marc Singer W: http://projects.buici.com/arm L: linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only) S: Maintained @@ -5284,23 +4554,20 @@ F: drivers/usb/gadget/lh7a40* F: drivers/usb/host/ohci-lh7a40* SHPC HOTPLUG DRIVER -P: Kristen Carlson Accardi -M: kristen.c.accardi@intel.com +M: Kristen Carlson Accardi L: linux-pci@vger.kernel.org S: Supported F: drivers/pci/hotplug/shpchp* SIMTEC EB110ATX (Chalice CATS) P: Ben Dooks -P: Vincent Sanders -M: support@simtec.co.uk +M: Vincent Sanders W: http://www.simtec.co.uk/products/EB110ATX/ S: Supported SIMTEC EB2410ITX (BAST) P: Ben Dooks -P: Vincent Sanders -M: support@simtec.co.uk +M: Vincent Sanders W: http://www.simtec.co.uk/products/EB2410ITX/ S: Supported F: arch/arm/mach-s3c2410/ @@ -5308,31 +4575,27 @@ F: drivers/*/*s3c2410* F: drivers/*/*/*s3c2410* SIS 190 ETHERNET DRIVER -P: Francois Romieu -M: romieu@fr.zoreil.com +M: Francois Romieu L: netdev@vger.kernel.org S: Maintained F: drivers/net/sis190.c SIS 900/7016 FAST ETHERNET DRIVER -P: Daniele Venzano -M: venza@brownhat.org +M: Daniele Venzano W: http://www.brownhat.org/sis900.html L: netdev@vger.kernel.org S: Maintained F: drivers/net/sis900.* SIS 96X I2C/SMBUS DRIVER -P: Mark M. Hoffman -M: mhoffman@lightlink.com +M: "Mark M. Hoffman" L: linux-i2c@vger.kernel.org S: Maintained F: Documentation/i2c/busses/i2c-sis96x F: drivers/i2c/busses/i2c-sis96x.c SIS FRAMEBUFFER DRIVER -P: Thomas Winischhofer -M: thomas@winischhofer.net +M: Thomas Winischhofer W: http://www.winischhofer.net/linuxsisvga.shtml S: Maintained F: Documentation/fb/sisfb.txt @@ -5340,70 +4603,59 @@ F: drivers/video/sis/ F: include/video/sisfb.h SIS USB2VGA DRIVER -P: Thomas Winischhofer -M: thomas@winischhofer.net +M: Thomas Winischhofer W: http://www.winischhofer.at/linuxsisusbvga.shtml S: Maintained F: drivers/usb/misc/sisusbvga/ SKGE, SKY2 10/100/1000 GIGABIT ETHERNET DRIVERS -P: Stephen Hemminger -M: shemminger@linux-foundation.org +M: Stephen Hemminger L: netdev@vger.kernel.org S: Maintained F: drivers/net/skge.* F: drivers/net/sky2.* SLAB ALLOCATOR -P: Christoph Lameter -M: cl@linux-foundation.org -P: Pekka Enberg -M: penberg@cs.helsinki.fi -P: Matt Mackall -M: mpm@selenic.com +M: Christoph Lameter +M: Pekka Enberg +M: Matt Mackall L: linux-mm@kvack.org S: Maintained F: include/linux/sl?b*.h F: mm/sl?b.c SMC91x ETHERNET DRIVER -P: Nicolas Pitre -M: nico@cam.org +M: Nicolas Pitre S: Maintained F: drivers/net/smc91x.* SMSC47B397 HARDWARE MONITOR DRIVER -P: Mark M. Hoffman -M: mhoffman@lightlink.com +M: "Mark M. Hoffman" L: lm-sensors@lm-sensors.org S: Maintained F: Documentation/hwmon/smsc47b397 F: drivers/hwmon/smsc47b397.c SMSC911x ETHERNET DRIVER -P: Steve Glendinning -M: steve.glendinning@smsc.com +M: Steve Glendinning L: netdev@vger.kernel.org S: Supported F: include/linux/smsc911x.h F: drivers/net/smsc911x.* SMSC9420 PCI ETHERNET DRIVER -P: Steve Glendinning -M: steve.glendinning@smsc.com +M: Steve Glendinning L: netdev@vger.kernel.org S: Supported F: drivers/net/smsc9420.* SMX UIO Interface -P: Ben Nizette -M: bn@niasdigital.com +M: Ben Nizette S: Maintained F: drivers/uio/uio_smx.c SN-IA64 (Itanium) SUB-PLATFORM -P: Jes Sorensen -M: jes@sgi.com +M: Jes Sorensen L: linux-altix@sgi.com L: linux-ia64@vger.kernel.org W: http://www.sgi.com/altix @@ -5411,8 +4663,7 @@ S: Maintained F: arch/ia64/sn/ SOC-CAMERA V4L2 SUBSYSTEM -P: Guennadi Liakhovetski -M: g.liakhovetski@gmx.de +M: Guennadi Liakhovetski L: linux-media@vger.kernel.org T: git git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-2.6.git S: Maintained @@ -5420,37 +4671,32 @@ F: include/media/v4l2* F: drivers/media/video/v4l2* SOEKRIS NET48XX LED SUPPORT -P: Chris Boot -M: bootc@bootc.net +M: Chris Boot S: Maintained F: drivers/leds/leds-net48xx.c SOFTWARE RAID (Multiple Disks) SUPPORT -P: Neil Brown -M: neilb@suse.de +M: Neil Brown L: linux-raid@vger.kernel.org S: Supported F: drivers/md/ F: include/linux/raid/ SONIC NETWORK DRIVER -P: Thomas Bogendoerfer -M: tsbogend@alpha.franken.de +M: Thomas Bogendoerfer L: netdev@vger.kernel.org S: Maintained F: drivers/net/sonic.* SONICS SILICON BACKPLANE DRIVER (SSB) -P: Michael Buesch -M: mb@bu3sch.de +M: Michael Buesch L: netdev@vger.kernel.org S: Maintained F: drivers/ssb/ F: include/linux/ssb/ SONY VAIO CONTROL DEVICE DRIVER -P: Mattia Dongili -M: malattia@linux.it +M: Mattia Dongili L: linux-acpi@vger.kernel.org W: http://www.linux.it/~malattia/wiki/index.php/Sony_drivers S: Maintained @@ -5460,17 +4706,14 @@ F: drivers/platform/x86/sony-laptop.c F: include/linux/sony-laptop.h SONY MEMORYSTICK CARD SUPPORT -P: Alex Dubov -M: oakad@yahoo.com +M: Alex Dubov W: http://tifmxx.berlios.de/ S: Maintained F: drivers/memstick/host/tifm_ms.c SOUND -P: Jaroslav Kysela -M: perex@perex.cz -P: Takashi Iwai -M: tiwai@suse.de +M: Jaroslav Kysela +M: Takashi Iwai L: alsa-devel@alsa-project.org (moderated for non-subscribers) W: http://www.alsa-project.org/ T: git git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound-2.6.git @@ -5481,10 +4724,8 @@ F: include/sound/ F: sound/ SOUND - SOC LAYER / DYNAMIC AUDIO POWER MANAGEMENT (ASoC) -P: Liam Girdwood -M: lrg@slimlogic.co.uk -P: Mark Brown -M: broonie@opensource.wolfsonmicro.com +M: Liam Girdwood +M: Mark Brown T: git git://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound-2.6.git L: alsa-devel@alsa-project.org (moderated for non-subscribers) W: http://alsa-project.org/main/index.php/ASoC @@ -5493,8 +4734,7 @@ F: sound/soc/ F: include/sound/soc* SPARC + UltraSPARC (sparc/sparc64) -P: David S. Miller -M: davem@davemloft.net +M: "David S. Miller" L: sparclinux@vger.kernel.org T: git git://git.kernel.org/pub/scm/linux/kernel/git/davem/sparc-2.6.git T: git git://git.kernel.org/pub/scm/linux/kernel/git/davem/sparc-next-2.6.git @@ -5502,15 +4742,13 @@ S: Maintained F: arch/sparc/ SPECIALIX IO8+ MULTIPORT SERIAL CARD DRIVER -P: Roger Wolff -M: R.E.Wolff@BitWizard.nl +M: Roger Wolff S: Supported F: Documentation/serial/specialix.txt F: drivers/char/specialix* SPI SUBSYSTEM -P: David Brownell -M: dbrownell@users.sourceforge.net +M: David Brownell L: spi-devel-general@lists.sourceforge.net S: Maintained F: Documentation/spi/ @@ -5518,18 +4756,15 @@ F: drivers/spi/ F: include/linux/spi/ SPIDERNET NETWORK DRIVER for CELL -P: Ishizaki Kou -M: kou.ishizaki@toshiba.co.jp -P: Jens Osterkamp -M: jens@de.ibm.com +M: Ishizaki Kou +M: Jens Osterkamp L: netdev@vger.kernel.org S: Supported F: Documentation/networking/spider_net.txt F: drivers/net/spider_net* SPU FILE SYSTEM -P: Jeremy Kerr -M: jk@ozlabs.org +M: Jeremy Kerr L: linuxppc-dev@ozlabs.org L: cbe-oss-dev@ozlabs.org W: http://www.ibm.com/developerworks/power/cell/ @@ -5538,8 +4773,7 @@ F: Documentation/filesystems/spufs.txt F: arch/powerpc/platforms/cell/spufs/ SQUASHFS FILE SYSTEM -P: Phillip Lougher -M: phillip@lougher.demon.co.uk +M: Phillip Lougher L: squashfs-devel@lists.sourceforge.net (subscribers-only) W: http://squashfs.org.uk S: Maintained @@ -5547,30 +4781,25 @@ F: Documentation/filesystems/squashfs.txt F: fs/squashfs/ SRM (Alpha) environment access -P: Jan-Benedict Glaw -M: jbglaw@lug-owl.de +M: Jan-Benedict Glaw S: Maintained F: arch/alpha/kernel/srm_env.c STABLE BRANCH -P: Greg Kroah-Hartman -M: greg@kroah.com -P: Chris Wright -M: chrisw@sous-sol.org +M: Greg Kroah-Hartman +M: Chris Wright L: stable@kernel.org S: Maintained STAGING SUBSYSTEM -P: Greg Kroah-Hartman -M: gregkh@suse.de +M: Greg Kroah-Hartman T: quilt kernel.org/pub/linux/kernel/people/gregkh/gregkh-2.6/ L: devel@driverdev.osuosl.org S: Maintained F: drivers/staging/ STARFIRE/DURALAN NETWORK DRIVER -P: Ion Badulescu -M: ionut@badula.org +M: Ion Badulescu S: Odd Fixes F: drivers/net/starfire* @@ -5580,15 +4809,13 @@ F: drivers/net/wireless/strip.c F: include/linux/if_strip.h STRADIS MPEG-2 DECODER DRIVER -P: Nathan Laredo -M: laredo@gnu.org +M: Nathan Laredo W: http://www.stradis.com/ S: Maintained F: drivers/media/video/stradis.c SUN3/3X -P: Sam Creasey -M: sammy@sammy.net +M: Sam Creasey W: http://sammy.net/sun3/ S: Maintained F: arch/m68k/kernel/*sun3* @@ -5596,8 +4823,7 @@ F: arch/m68k/sun3*/ F: arch/m68k/include/asm/sun3* SUPERH -P: Paul Mundt -M: lethal@linux-sh.org +M: Paul Mundt L: linux-sh@vger.kernel.org W: http://www.linux-sh.org T: git git://git.kernel.org/pub/scm/linux/kernel/git/lethal/sh-2.6.git @@ -5607,12 +4833,9 @@ F: arch/sh/ F: drivers/sh/ SUSPEND TO RAM -P: Len Brown -M: len.brown@intel.com -P: Pavel Machek -M: pavel@ucw.cz -P: Rafael J. Wysocki -M: rjw@sisk.pl +M: Len Brown +M: Pavel Machek +M: "Rafael J. Wysocki" L: linux-pm@lists.linux-foundation.org S: Supported F: Documentation/power/ @@ -5624,32 +4847,28 @@ F: include/linux/freezer.h F: include/linux/pm.h SVGA HANDLING -P: Martin Mares -M: mj@ucw.cz +M: Martin Mares L: linux-video@atrey.karlin.mff.cuni.cz S: Maintained F: Documentation/svga.txt F: arch/x86/boot/video* SYSV FILESYSTEM -P: Christoph Hellwig -M: hch@infradead.org +M: Christoph Hellwig S: Maintained F: Documentation/filesystems/sysv-fs.txt F: fs/sysv/ F: include/linux/sysv_fs.h TASKSTATS STATISTICS INTERFACE -P: Balbir Singh -M: balbir@linux.vnet.ibm.com +M: Balbir Singh S: Maintained F: Documentation/accounting/taskstats* F: include/linux/taskstats* F: kernel/taskstats.c TC CLASSIFIER -P: Jamal Hadi Salim -M: hadi@cyberus.ca +M: Jamal Hadi Salim L: netdev@vger.kernel.org S: Maintained F: include/linux/pkt_cls.h @@ -5657,38 +4876,31 @@ F: include/net/pkt_cls.h F: net/sched/ TCP LOW PRIORITY MODULE -P: Wong Hoi Sing, Edison -M: hswong3i@gmail.com -P: Hung Hing Lun, Mike -M: hlhung3i@gmail.com +M: "Wong Hoi Sing, Edison" +M: "Hung Hing Lun, Mike" W: http://tcp-lp-mod.sourceforge.net/ S: Maintained F: net/ipv4/tcp_lp.c TEHUTI ETHERNET DRIVER -P: Alexander Indenbaum -M: baum@tehutinetworks.net -P: Andy Gospodarek -M: andy@greyhouse.net +M: Alexander Indenbaum +M: Andy Gospodarek L: netdev@vger.kernel.org S: Supported F: drivers/net/tehuti* Telecom Clock Driver for MCPL0010 -P: Mark Gross -M: mark.gross@intel.com +M: Mark Gross S: Supported F: drivers/char/tlclk.c TENSILICA XTENSA PORT (xtensa) -P: Chris Zankel -M: chris@zankel.net +M: Chris Zankel S: Maintained F: arch/xtensa/ THINKPAD ACPI EXTRAS DRIVER -P: Henrique de Moraes Holschuh -M: ibm-acpi@hmh.eng.br +M: Henrique de Moraes Holschuh L: ibm-acpi-devel@lists.sourceforge.net W: http://ibm-acpi.sourceforge.net W: http://thinkwiki.org/wiki/Ibm-acpi @@ -5697,27 +4909,22 @@ S: Maintained F: drivers/platform/x86/thinkpad_acpi.c TI FLASH MEDIA INTERFACE DRIVER -P: Alex Dubov -M: oakad@yahoo.com +M: Alex Dubov S: Maintained F: drivers/misc/tifm* F: drivers/mmc/host/tifm_sd.c F: include/linux/tifm.h TI TWL4030 SERIES SOC CODEC DRIVER -P: Peter Ujfalusi -M: peter.ujfalusi@nokia.com +M: Peter Ujfalusi L: alsa-devel@alsa-project.org (moderated for non-subscribers) S: Maintained F: sound/soc/codecs/twl4030* TIPC NETWORK LAYER -P: Per Liden -M: per.liden@ericsson.com -P: Jon Maloy -M: jon.maloy@ericsson.com -P: Allan Stephens -M: allan.stephens@windriver.com +M: Per Liden +M: Jon Maloy +M: Allan Stephens L: tipc-discussion@lists.sourceforge.net W: http://tipc.sourceforge.net/ W: http://tipc.cslab.ericsson.net/ @@ -5728,8 +4935,7 @@ F: include/net/tipc/ F: net/tipc/ TLAN NETWORK DRIVER -P: Samuel Chessman -M: chessman@tux.org +M: Samuel Chessman L: tlan-devel@lists.sourceforge.net (subscribers-only) W: http://sourceforge.net/projects/tlan/ S: Maintained @@ -5737,10 +4943,8 @@ F: Documentation/networking/tlan.txt F: drivers/net/tlan.* TOMOYO SECURITY MODULE -P: Kentaro Takeda -M: takedakn@nttdata.co.jp -P: Tetsuo Handa -M: penguin-kernel@I-love.SAKURA.ne.jp +M: Kentaro Takeda +M: Tetsuo Handa L: tomoyo-users-en@lists.sourceforge.jp (subscribers-only, for developers and users in English) L: tomoyo-dev@lists.sourceforge.jp (subscribers-only, for developers in Japanese) L: tomoyo-users@lists.sourceforge.jp (subscribers-only, for users in Japanese) @@ -5754,8 +4958,7 @@ S: Orphan F: drivers/platform/x86/toshiba_acpi.c TOSHIBA SMM DRIVER -P: Jonathan Buzzard -M: jonathan@buzzard.org.uk +M: Jonathan Buzzard L: tlinux-users@tce.toshiba-dme.co.jp W: http://www.buzzard.org.uk/toshiba/ S: Maintained @@ -5763,41 +4966,34 @@ F: drivers/char/toshiba.c F: include/linux/toshiba.h TMIO MMC DRIVER -P: Ian Molton -M: ian@mnementh.co.uk +M: Ian Molton S: Maintained F: drivers/mmc/host/tmio_mmc.* TMPFS (SHMEM FILESYSTEM) -P: Hugh Dickins -M: hugh.dickins@tiscali.co.uk +M: Hugh Dickins L: linux-mm@kvack.org S: Maintained F: include/linux/shmem_fs.h F: mm/shmem.c TPM DEVICE DRIVER -P: Debora Velarde -M: debora@linux.vnet.ibm.com -P: Rajiv Andrade -M: srajiv@linux.vnet.ibm.com +M: Debora Velarde +M: Rajiv Andrade W: http://tpmdd.sourceforge.net -P: Marcel Selhorst -M: m.selhorst@sirrix.com +M: Marcel Selhorst W: http://www.sirrix.com L: tpmdd-devel@lists.sourceforge.net (moderated for non-subscribers) S: Maintained F: drivers/char/tpm/ TRIVIAL PATCHES -P: Jiri Kosina -M: trivial@kernel.org +M: Jiri Kosina T: git git://git.kernel.org/pub/scm/linux/kernel/git/jikos/trivial.git S: Maintained TTY LAYER -P: Alan Cox -M: alan@lxorguk.ukuu.org.uk +M: Alan Cox S: Maintained T: stgit http://zeniv.linux.org.uk/~alan/ttydev/ F: drivers/char/tty_* @@ -5807,17 +5003,14 @@ F: include/linux/serial.h F: include/linux/tty.h TULIP NETWORK DRIVERS -P: Grant Grundler -M: grundler@parisc-linux.org -P: Kyle McMartin -M: kyle@mcmartin.ca +M: Grant Grundler +M: Kyle McMartin L: netdev@vger.kernel.org S: Maintained F: drivers/net/tulip/ TUN/TAP driver -P: Maxim Krasnyansky -M: maxk@qualcomm.com +M: Maxim Krasnyansky L: vtun@office.satix.net W: http://vtun.sourceforge.net/tun S: Maintained @@ -5825,24 +5018,20 @@ F: Documentation/networking/tuntap.txt F: arch/um/os-Linux/drivers/ TURBOCHANNEL SUBSYSTEM -P: Maciej W. Rozycki -M: macro@linux-mips.org +M: "Maciej W. Rozycki" S: Maintained F: drivers/tc/ F: include/linux/tc.h U14-34F SCSI DRIVER -P: Dario Ballabio -M: ballabio_dario@emc.com +M: Dario Ballabio L: linux-scsi@vger.kernel.org S: Maintained F: drivers/scsi/u14-34f.c UBI FILE SYSTEM (UBIFS) -P: Artem Bityutskiy -M: dedekind@infradead.org -P: Adrian Hunter -M: adrian.hunter@nokia.com +M: Artem Bityutskiy +M: Adrian Hunter L: linux-mtd@lists.infradead.org T: git git://git.infradead.org/ubifs-2.6.git W: http://www.linux-mtd.infradead.org/doc/ubifs.html @@ -5851,37 +5040,32 @@ F: Documentation/filesystems/ubifs.txt F: fs/ubifs/ UCLINUX (AND M68KNOMMU) -P: Greg Ungerer -M: gerg@uclinux.org +M: Greg Ungerer W: http://www.uclinux.org/ L: uclinux-dev@uclinux.org (subscribers-only) S: Maintained F: arch/m68knommu/ UCLINUX FOR RENESAS H8/300 (H8300) -P: Yoshinori Sato -M: ysato@users.sourceforge.jp +M: Yoshinori Sato W: http://uclinux-h8.sourceforge.jp/ S: Supported UDF FILESYSTEM -P: Jan Kara -M: jack@suse.cz +M: Jan Kara W: http://linux-udf.sourceforge.net S: Maintained F: Documentation/filesystems/udf.txt F: fs/udf/ UFS FILESYSTEM -P: Evgeniy Dushistov -M: dushistov@mail.ru +M: Evgeniy Dushistov S: Maintained F: Documentation/filesystems/ufs.txt F: fs/ufs/ ULTRA-WIDEBAND (UWB) SUBSYSTEM: -P: David Vrabel -M: david.vrabel@csr.com +M: David Vrabel L: linux-usb@vger.kernel.org S: Supported F: drivers/uwb/* @@ -5889,8 +5073,7 @@ F: include/linux/uwb.h F: include/linux/uwb/ UNIFORM CDROM DRIVER -P: Jens Axboe -M: axboe@kernel.dk +M: Jens Axboe W: http://www.kernel.dk S: Maintained F: Documentation/cdrom/ @@ -5898,8 +5081,7 @@ F: drivers/cdrom/cdrom.c F: include/linux/cdrom.h UNSORTED BLOCK IMAGES (UBI) -P: Artem Bityutskiy -M: dedekind@infradead.org +M: Artem Bityutskiy W: http://www.linux-mtd.infradead.org/ L: linux-mtd@lists.infradead.org T: git git://git.infradead.org/ubi-2.6.git @@ -5909,23 +5091,20 @@ F: include/linux/mtd/ubi.h F: include/mtd/ubi-user.h USB ACM DRIVER -P: Oliver Neukum -M: oliver@neukum.name +M: Oliver Neukum L: linux-usb@vger.kernel.org S: Maintained F: Documentation/usb/acm.txt F: drivers/usb/class/cdc-acm.* USB BLOCK DRIVER (UB ub) -P: Pete Zaitcev -M: zaitcev@redhat.com +M: Pete Zaitcev L: linux-usb@vger.kernel.org S: Supported F: drivers/block/ub.c USB CDC ETHERNET DRIVER -P: Greg Kroah-Hartman -M: greg@kroah.com +M: Greg Kroah-Hartman L: linux-usb@vger.kernel.org S: Maintained W: http://www.kroah.com/linux-usb/ @@ -5933,39 +5112,34 @@ F: drivers/net/usb/cdc_*.c F: include/linux/usb/cdc.h USB CYPRESS C67X00 DRIVER -P: Peter Korsgaard -M: jacmet@sunsite.dk +M: Peter Korsgaard L: linux-usb@vger.kernel.org S: Maintained F: drivers/usb/c67x00/ USB DAVICOM DM9601 DRIVER -P: Peter Korsgaard -M: jacmet@sunsite.dk +M: Peter Korsgaard L: netdev@vger.kernel.org W: http://www.linux-usb.org/usbnet S: Maintained F: drivers/net/usb/dm9601.c USB DIAMOND RIO500 DRIVER -P: Cesar Miquel -M: miquel@df.uba.ar +M: Cesar Miquel L: rio500-users@lists.sourceforge.net W: http://rio500.sourceforge.net S: Maintained F: drivers/usb/misc/rio500* USB EHCI DRIVER -P: David Brownell -M: dbrownell@users.sourceforge.net +M: David Brownell L: linux-usb@vger.kernel.org S: Odd Fixes F: Documentation/usb/ehci.txt F: drivers/usb/host/ehci* USB ET61X[12]51 DRIVER -P: Luca Risolia -M: luca.risolia@studio.unibo.it +M: Luca Risolia L: linux-usb@vger.kernel.org L: linux-media@vger.kernel.org T: git git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-2.6.git @@ -5974,8 +5148,7 @@ S: Maintained F: drivers/media/video/et61x251/ USB GADGET/PERIPHERAL SUBSYSTEM -P: David Brownell -M: dbrownell@users.sourceforge.net +M: David Brownell L: linux-usb@vger.kernel.org W: http://www.linux-usb.org/gadget S: Maintained @@ -5983,8 +5156,7 @@ F: drivers/usb/gadget/ F: include/linux/usb/gadget* USB HID/HIDBP DRIVERS (USB KEYBOARDS, MICE, REMOTE CONTROLS, ...) -P: Jiri Kosina -M: jkosina@suse.cz +M: Jiri Kosina L: linux-usb@vger.kernel.org T: git git://git.kernel.org/pub/scm/linux/kernel/git/jikos/hid.git S: Maintained @@ -5992,23 +5164,20 @@ F: Documentation/usb/hiddev.txt F: drivers/hid/usbhid/ USB ISP116X DRIVER -P: Olav Kongas -M: ok@artecdesign.ee +M: Olav Kongas L: linux-usb@vger.kernel.org S: Maintained F: drivers/usb/host/isp116x* F: include/linux/usb/isp116x.h USB KAWASAKI LSI DRIVER -P: Oliver Neukum -M: oliver@neukum.name +M: Oliver Neukum L: linux-usb@vger.kernel.org S: Maintained F: drivers/usb/serial/kl5kusb105.* USB MASS STORAGE DRIVER -P: Matthew Dharm -M: mdharm-usb@one-eyed-alien.net +M: Matthew Dharm L: linux-usb@vger.kernel.org L: usb-storage@lists.one-eyed-alien.net S: Maintained @@ -6016,31 +5185,27 @@ W: http://www.one-eyed-alien.net/~mdharm/linux-usb/ F: drivers/usb/storage/ USB OHCI DRIVER -P: David Brownell -M: dbrownell@users.sourceforge.net +M: David Brownell L: linux-usb@vger.kernel.org S: Odd Fixes F: Documentation/usb/ohci.txt F: drivers/usb/host/ohci* USB OPTION-CARD DRIVER -P: Matthias Urlichs -M: smurf@smurf.noris.de +M: Matthias Urlichs L: linux-usb@vger.kernel.org S: Maintained F: drivers/usb/serial/option.c USB OV511 DRIVER -P: Mark McClelland -M: mmcclell@bigfoot.com +M: Mark McClelland L: linux-usb@vger.kernel.org W: http://alpha.dyndns.org/ov511/ S: Maintained F: drivers/media/video/ov511.* USB PEGASUS DRIVER -P: Petko Manolov -M: petkan@users.sourceforge.net +M: Petko Manolov L: linux-usb@vger.kernel.org L: netdev@vger.kernel.org W: http://pegasus2.sourceforge.net/ @@ -6048,15 +5213,13 @@ S: Maintained F: drivers/net/usb/pegasus.* USB PRINTER DRIVER (usblp) -P: Pete Zaitcev -M: zaitcev@redhat.com +M: Pete Zaitcev L: linux-usb@vger.kernel.org S: Supported F: drivers/usb/class/usblp.c USB RTL8150 DRIVER -P: Petko Manolov -M: petkan@users.sourceforge.net +M: Petko Manolov L: linux-usb@vger.kernel.org L: netdev@vger.kernel.org W: http://pegasus2.sourceforge.net/ @@ -6064,8 +5227,7 @@ S: Maintained F: drivers/net/usb/rtl8150.c USB SE401 DRIVER -P: Jeroen Vreeken -M: pe1rxq@amsat.org +M: Jeroen Vreeken L: linux-usb@vger.kernel.org W: http://www.chello.nl/~j.vreeken/se401/ S: Maintained @@ -6073,15 +5235,13 @@ F: Documentation/video4linux/se401.txt F: drivers/media/video/se401.* USB SERIAL BELKIN F5U103 DRIVER -P: William Greathouse -M: wgreathouse@smva.com +M: William Greathouse L: linux-usb@vger.kernel.org S: Maintained F: drivers/usb/serial/belkin_sa.* USB SERIAL CYPRESS M8 DRIVER -P: Lonnie Mendez -M: dignome@gmail.com +M: Lonnie Mendez L: linux-usb@vger.kernel.org S: Maintained W: http://geocities.com/i0xox0i @@ -6089,24 +5249,20 @@ W: http://firstlight.net/cvs F: drivers/usb/serial/cypress_m8.* USB SERIAL CYBERJACK DRIVER -P: Matthias Bruestle and Harald Welte -M: support@reiner-sct.com +M: Matthias Bruestle and Harald Welte W: http://www.reiner-sct.de/support/treiber_cyberjack.php S: Maintained F: drivers/usb/serial/cyberjack.c USB SERIAL DIGI ACCELEPORT DRIVER -P: Peter Berger -M: pberger@brimson.com -P: Al Borchers -M: alborchers@steinerpoint.com +M: Peter Berger +M: Al Borchers L: linux-usb@vger.kernel.org S: Maintained F: drivers/usb/serial/digi_acceleport.c USB SERIAL DRIVER -P: Greg Kroah-Hartman -M: gregkh@suse.de +M: Greg Kroah-Hartman L: linux-usb@vger.kernel.org S: Supported F: Documentation/usb/usb-serial.txt @@ -6115,38 +5271,33 @@ F: drivers/usb/serial/usb-serial.c F: include/linux/usb/serial.h USB SERIAL EMPEG EMPEG-CAR MARK I/II DRIVER -P: Gary Brubaker -M: xavyer@ix.netcom.com +M: Gary Brubaker L: linux-usb@vger.kernel.org S: Maintained F: drivers/usb/serial/empeg.c USB SERIAL KEYSPAN DRIVER -P: Greg Kroah-Hartman -M: greg@kroah.com +M: Greg Kroah-Hartman L: linux-usb@vger.kernel.org W: http://www.kroah.com/linux/ S: Maintained F: drivers/usb/serial/*keyspan* USB SERIAL WHITEHEAT DRIVER -P: Support Department -M: support@connecttech.com +M: Support Department L: linux-usb@vger.kernel.org W: http://www.connecttech.com S: Supported F: drivers/usb/serial/whiteheat* USB SMSC95XX ETHERNET DRIVER -P: Steve Glendinning -M: steve.glendinning@smsc.com +M: Steve Glendinning L: netdev@vger.kernel.org S: Supported F: drivers/net/usb/smsc95xx.* USB SN9C1xx DRIVER -P: Luca Risolia -M: luca.risolia@studio.unibo.it +M: Luca Risolia L: linux-usb@vger.kernel.org L: linux-media@vger.kernel.org T: git git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-2.6.git @@ -6156,8 +5307,7 @@ F: Documentation/video4linux/sn9c102.txt F: drivers/media/video/sn9c102/ USB SUBSYSTEM -P: Greg Kroah-Hartman -M: gregkh@suse.de +M: Greg Kroah-Hartman L: linux-usb@vger.kernel.org W: http://www.linux-usb.org T: quilt kernel.org/pub/linux/kernel/people/gregkh/gregkh-2.6/ @@ -6169,15 +5319,13 @@ F: include/linux/usb.h F: include/linux/usb/ USB UHCI DRIVER -P: Alan Stern -M: stern@rowland.harvard.edu +M: Alan Stern L: linux-usb@vger.kernel.org S: Maintained F: drivers/usb/host/uhci* USB "USBNET" DRIVER FRAMEWORK -P: David Brownell -M: dbrownell@users.sourceforge.net +M: David Brownell L: netdev@vger.kernel.org W: http://www.linux-usb.org/usbnet S: Maintained @@ -6185,8 +5333,7 @@ F: drivers/net/usb/usbnet.c F: include/linux/usb/usbnet.h USB VIDEO CLASS -P: Laurent Pinchart -M: laurent.pinchart@skynet.be +M: Laurent Pinchart L: linux-uvc-devel@lists.berlios.de (subscribers-only) L: linux-media@vger.kernel.org T: git git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-2.6.git @@ -6195,8 +5342,7 @@ S: Maintained F: drivers/media/video/uvc/ USB W996[87]CF DRIVER -P: Luca Risolia -M: luca.risolia@studio.unibo.it +M: Luca Risolia L: linux-usb@vger.kernel.org L: linux-media@vger.kernel.org T: git git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-2.6.git @@ -6206,21 +5352,18 @@ F: Documentation/video4linux/w9968cf.txt F: drivers/media/video/w996* USB WIRELESS RNDIS DRIVER (rndis_wlan) -P: Jussi Kivilinna -M: jussi.kivilinna@mbnet.fi +M: Jussi Kivilinna L: linux-wireless@vger.kernel.org S: Maintained F: drivers/net/wireless/rndis_wlan.c USB XHCI DRIVER -P: Sarah Sharp -M: sarah.a.sharp@intel.com +M: Sarah Sharp L: linux-usb@vger.kernel.org S: Supported USB ZC0301 DRIVER -P: Luca Risolia -M: luca.risolia@studio.unibo.it +M: Luca Risolia L: linux-usb@vger.kernel.org L: linux-media@vger.kernel.org T: git git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-2.6.git @@ -6230,16 +5373,14 @@ F: Documentation/video4linux/zc0301.txt F: drivers/media/video/zc0301/ USB ZD1201 DRIVER -P: Jeroen Vreeken -M: pe1rxq@amsat.org +M: Jeroen Vreeken L: linux-usb@vger.kernel.org W: http://linux-lc100020.sourceforge.net S: Maintained F: drivers/net/wireless/zd1201.* USB ZR364XX DRIVER -P: Antoine Jacquet -M: royale@zerezo.com +M: Antoine Jacquet L: linux-usb@vger.kernel.org L: linux-media@vger.kernel.org T: git git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-2.6.git @@ -6249,8 +5390,7 @@ F: Documentation/video4linux/zr364xx.txt F: drivers/media/video/zr364xx.c USER-MODE LINUX (UML) -P: Jeff Dike -M: jdike@addtoit.com +M: Jeff Dike L: user-mode-linux-devel@lists.sourceforge.net L: user-mode-linux-user@lists.sourceforge.net W: http://user-mode-linux.sourceforge.net @@ -6261,26 +5401,22 @@ F: fs/hostfs/ F: fs/hppfs/ USERSPACE I/O (UIO) -P: Hans J. Koch -M: hjk@linutronix.de -P: Greg Kroah-Hartman -M: gregkh@suse.de +M: "Hans J. Koch" +M: Greg Kroah-Hartman S: Maintained F: Documentation/DocBook/uio-howto.tmpl F: drivers/uio/ F: include/linux/uio*.h UTIL-LINUX-NG PACKAGE -P: Karel Zak -M: kzak@redhat.com +M: Karel Zak L: util-linux-ng@vger.kernel.org W: http://kernel.org/~kzak/util-linux-ng/ T: git git://git.kernel.org/pub/scm/utils/util-linux-ng/util-linux-ng.git S: Maintained UVESAFB DRIVER -P: Michal Januszewski -M: spock@gentoo.org +M: Michal Januszewski L: linux-fbdev-devel@lists.sourceforge.net (moderated for non-subscribers) W: http://dev.gentoo.org/~spock/projects/uvesafb/ S: Maintained @@ -6288,53 +5424,44 @@ F: Documentation/fb/uvesafb.txt F: drivers/video/uvesafb.* VFAT/FAT/MSDOS FILESYSTEM -P: OGAWA Hirofumi -M: hirofumi@mail.parknet.co.jp +M: OGAWA Hirofumi S: Maintained F: Documentation/filesystems/vfat.txt F: fs/fat/ VIA RHINE NETWORK DRIVER -P: Roger Luethi -M: rl@hellgate.ch +M: Roger Luethi S: Maintained F: drivers/net/via-rhine.c VIAPRO SMBUS DRIVER -P: Jean Delvare -M: khali@linux-fr.org +M: Jean Delvare L: linux-i2c@vger.kernel.org S: Maintained F: Documentation/i2c/busses/i2c-viapro F: drivers/i2c/busses/i2c-viapro.c VIA SD/MMC CARD CONTROLLER DRIVER -P: Joseph Chan -M: JosephChan@via.com.tw -P: Harald Welte -M: HaraldWelte@viatech.com +M: Joseph Chan +M: Harald Welte S: Maintained F: drivers/mmc/host/via-sdmmc.c VIA UNICHROME(PRO)/CHROME9 FRAMEBUFFER DRIVER -P: Joseph Chan -M: JosephChan@via.com.tw -P: Scott Fang -M: ScottFang@viatech.com.cn +M: Joseph Chan +M: Scott Fang L: linux-fbdev-devel@lists.sourceforge.net (moderated for non-subscribers) S: Maintained F: drivers/video/via/ VIA VELOCITY NETWORK DRIVER -P: Francois Romieu -M: romieu@fr.zoreil.com +M: Francois Romieu L: netdev@vger.kernel.org S: Maintained F: drivers/net/via-velocity.* VLAN (802.1Q) -P: Patrick McHardy -M: kaber@trash.net +M: Patrick McHardy L: netdev@vger.kernel.org S: Maintained F: drivers/net/macvlan.c @@ -6342,18 +5469,15 @@ F: include/linux/if_*vlan.h F: net/8021q/ VLYNQ BUS -P: Florian Fainelli -M: florian@openwrt.org +M: Florian Fainelli L: openwrt-devel@lists.openwrt.org S: Maintained F: drivers/vlynq/vlynq.c F: include/linux/vlynq.h VOLTAGE AND CURRENT REGULATOR FRAMEWORK -P: Liam Girdwood -M: lrg@slimlogic.co.uk -P: Mark Brown -M: broonie@opensource.wolfsonmicro.com +M: Liam Girdwood +M: Mark Brown W: http://opensource.wolfsonmicro.com/node/15 W: http://www.slimlogic.co.uk/?p=48 T: git git://git.kernel.org/pub/scm/linux/kernel/git/lrg/voltage-2.6.git @@ -6362,52 +5486,45 @@ F: drivers/regulator/ F: include/linux/regulator/ VT1211 HARDWARE MONITOR DRIVER -P: Juerg Haefliger -M: juergh@gmail.com +M: Juerg Haefliger L: lm-sensors@lm-sensors.org S: Maintained F: Documentation/hwmon/vt1211 F: drivers/hwmon/vt1211.c VT8231 HARDWARE MONITOR DRIVER -P: Roger Lucas -M: vt8231@hiddenengine.co.uk +M: Roger Lucas L: lm-sensors@lm-sensors.org S: Maintained F: drivers/hwmon/vt8231.c W1 DALLAS'S 1-WIRE BUS -P: Evgeniy Polyakov -M: johnpol@2ka.mipt.ru +M: Evgeniy Polyakov S: Maintained F: Documentation/w1/ F: drivers/w1/ W83791D HARDWARE MONITORING DRIVER -P: Marc Hulsman -M: m.hulsman@tudelft.nl +M: Marc Hulsman L: lm-sensors@lm-sensors.org S: Maintained F: Documentation/hwmon/w83791d F: drivers/hwmon/w83791d.c W83793 HARDWARE MONITORING DRIVER -P: Rudolf Marek -M: r.marek@assembler.cz +M: Rudolf Marek L: lm-sensors@lm-sensors.org S: Maintained F: Documentation/hwmon/w83793 F: drivers/hwmon/w83793.c W83L51xD SD/MMC CARD INTERFACE DRIVER -P: Pierre Ossman -M: pierre@ossman.eu +M: Pierre Ossman S: Maintained F: drivers/mmc/host/wbsd.* WATCHDOG DEVICE DRIVERS -P: Wim Van Sebroeck -M: wim@iguana.be +M: Wim Van Sebroeck T: git git://git.kernel.org/pub/scm/linux/kernel/git/wim/linux-2.6-watchdog.git S: Maintained F: Documentation/watchdog/ @@ -6415,8 +5532,7 @@ F: drivers/watchdog/ F: include/linux/watchdog.h WAVELAN NETWORK DRIVER & WIRELESS EXTENSIONS -P: Jean Tourrilhes -M: jt@hpl.hp.com +M: Jean Tourrilhes L: linux-wireless@vger.kernel.org W: http://www.hpl.hp.com/personal/Jean_Tourrilhes/Linux/ S: Maintained @@ -6424,46 +5540,39 @@ F: Documentation/networking/wavelan.txt F: drivers/net/wireless/wavelan* WD7000 SCSI DRIVER -P: Miroslav Zagorac -M: zaga@fly.cc.fer.hr +M: Miroslav Zagorac L: linux-scsi@vger.kernel.org S: Maintained F: drivers/scsi/wd7000.c WIMAX STACK -P: Inaky Perez-Gonzalez -M: inaky.perez-gonzalez@intel.com +M: Inaky Perez-Gonzalez M: linux-wimax@intel.com L: wimax@linuxwimax.org S: Supported W: http://linuxwimax.org WIMEDIA LLC PROTOCOL (WLP) SUBSYSTEM -P: David Vrabel -M: david.vrabel@csr.com +M: David Vrabel S: Maintained F: include/linux/wlp.h F: drivers/uwb/wlp/ WISTRON LAPTOP BUTTON DRIVER -P: Miloslav Trmac -M: mitr@volny.cz +M: Miloslav Trmac S: Maintained F: drivers/input/misc/wistron_btns.c WL3501 WIRELESS PCMCIA CARD DRIVER -P: Arnaldo Carvalho de Melo -M: acme@ghostprotocols.net +M: Arnaldo Carvalho de Melo L: linux-wireless@vger.kernel.org W: http://oops.ghostprotocols.net:81/blog S: Maintained F: drivers/net/wireless/wl3501* WM97XX TOUCHSCREEN DRIVERS -P: Mark Brown -M: broonie@opensource.wolfsonmicro.com -P: Liam Girdwood -M: lrg@slimlogic.co.uk +M: Mark Brown +M: Liam Girdwood L: linux-input@vger.kernel.org T: git git://opensource.wolfsonmicro.com/linux-2.6-touch W: http://opensource.wolfsonmicro.com/node/7 @@ -6472,8 +5581,7 @@ F: drivers/input/touchscreen/*wm97* F: include/linux/wm97xx.h X.25 NETWORK LAYER -P: Henner Eisen -M: eis@baty.hanse.de +M: Henner Eisen L: linux-x25@vger.kernel.org S: Maintained F: Documentation/networking/x25* @@ -6481,12 +5589,9 @@ F: include/net/x25* F: net/x25/ X86 ARCHITECTURE (32-BIT AND 64-BIT) -P: Thomas Gleixner -M: tglx@linutronix.de -P: Ingo Molnar -M: mingo@redhat.com -P: H. Peter Anvin -M: hpa@zytor.com +M: Thomas Gleixner +M: Ingo Molnar +M: "H. Peter Anvin" M: x86@kernel.org T: git git://git.kernel.org/pub/scm/linux/kernel/git/x86/linux-2.6-x86.git S: Maintained @@ -6494,10 +5599,8 @@ F: Documentation/x86/ F: arch/x86/ XEN HYPERVISOR INTERFACE -P: Jeremy Fitzhardinge -M: jeremy@xensource.com -P: Chris Wright -M: chrisw@sous-sol.org +M: Jeremy Fitzhardinge +M: Chris Wright L: virtualization@lists.osdl.org L: xen-devel@lists.xensource.com S: Supported @@ -6509,8 +5612,7 @@ F: include/xen/ XFS FILESYSTEM P: Silicon Graphics Inc -P: Felix Blyakher -M: felixb@sgi.com +M: Felix Blyakher M: xfs-masters@oss.sgi.com L: xfs@oss.sgi.com W: http://oss.sgi.com/projects/xfs @@ -6520,38 +5622,33 @@ F: Documentation/filesystems/xfs.txt F: fs/xfs/ XILINX SYSTEMACE DRIVER -P: Grant Likely -M: grant.likely@secretlab.ca +M: Grant Likely W: http://www.secretlab.ca/ S: Maintained F: drivers/block/xsysace.c XILINX UARTLITE SERIAL DRIVER -P: Peter Korsgaard -M: jacmet@sunsite.dk +M: Peter Korsgaard L: linux-serial@vger.kernel.org S: Maintained F: drivers/serial/uartlite.c YAM DRIVER FOR AX.25 -P: Jean-Paul Roubelat -M: jpr@f6fbb.org +M: Jean-Paul Roubelat L: linux-hams@vger.kernel.org S: Maintained F: drivers/net/hamradio/yam* F: include/linux/yam.h YEALINK PHONE DRIVER -P: Henk Vergonet -M: Henk.Vergonet@gmail.com +M: Henk Vergonet L: usbb2k-api-dev@nongnu.org S: Maintained F: Documentation/input/yealink.txt F: drivers/input/misc/yealink.* Z8530 DRIVER FOR AX.25 -P: Joerg Reuter -M: jreuter@yaina.de +M: Joerg Reuter W: http://yaina.de/jreuter/ W: http://www.qsl.net/dl1bke/ L: linux-hams@vger.kernel.org @@ -6561,10 +5658,8 @@ F: drivers/net/hamradio/*scc.c F: drivers/net/hamradio/z8530.h ZD1211RW WIRELESS DRIVER -P: Daniel Drake -M: dsd@gentoo.org -P: Ulrich Kunitz -M: kune@deine-taler.de +M: Daniel Drake +M: Ulrich Kunitz W: http://zd1211.ath.cx/wiki/DriverRewrite L: linux-wireless@vger.kernel.org L: zd1211-devs@lists.sourceforge.net (subscribers-only) @@ -6580,14 +5675,12 @@ S: Odd Fixes F: drivers/media/video/zoran/ ZS DECSTATION Z85C30 SERIAL DRIVER -P: Maciej W. Rozycki -M: macro@linux-mips.org +M: "Maciej W. Rozycki" S: Maintained F: drivers/serial/zs.* THE REST -P: Linus Torvalds -M: torvalds@linux-foundation.org +M: Linus Torvalds L: linux-kernel@vger.kernel.org T: git git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6.git S: Buried alive in reporters -- cgit v1.2.3 From 2bed6eeb8cb0b5198d8f93e415ee595704bc3534 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Wed, 29 Jul 2009 15:04:32 -0700 Subject: MAINTAINERS: finish off the email address coalescing Add some touchups to the sample record. Signed-off-by: Joe Perches Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- MAINTAINERS | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/MAINTAINERS b/MAINTAINERS index a013e963fc07..a39f3cf940b6 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -73,8 +73,8 @@ Note: For the hard of thinking, this list is meant to remain in alphabetical order. If you could add yourselves to it in alphabetical order that would be so much easier [Ed] -P: Person -M: Mail patches to +P: Person (obsolete) +M: Mail patches to: FullName L: Mailing list that is relevant to this area W: Web-page with status/info T: SCM tree type and location. Type is one of: git, hg, quilt, stgit. -- cgit v1.2.3 From 084bad91afd0f40ff4db9ceb56e29234c314d8d1 Mon Sep 17 00:00:00 2001 From: Kristoffer Ericson Date: Wed, 29 Jul 2009 15:04:32 -0700 Subject: MAINTAINERS: update HP Jornada 700-series and Epson s1d13xxxfb support Add the relevant git repositories and affected files to the maintainership of HP Jornada 700-series and Epson s1d13xxxfb support. Signed-off-by: Kristoffer Ericson Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- MAINTAINERS | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index a39f3cf940b6..66a3865da88d 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -624,6 +624,9 @@ ARM/HP JORNADA 7XX MACHINE SUPPORT M: Kristoffer Ericson W: www.jlime.com S: Maintained +T: git git://git.kernel.org/pub/scm/linux/kernel/git/kristoffer/linux-hpc.git +F: arch/arm/mach-sa1100/jornada720.c +F: arch/arm/mach-sa1100/include/mach/jornada720.h ARM/INTEL IOP32X ARM ARCHITECTURE M: Lennert Buytenhek @@ -1900,6 +1903,7 @@ F: drivers/video/epson1355fb.c EPSON S1D13XXX FRAMEBUFFER DRIVER M: Kristoffer Ericson S: Maintained +T: git git://git.kernel.org/pub/scm/linux/kernel/git/kristoffer/linux-hpc.git F: drivers/video/s1d13xxxfb.c F: include/video/s1d13xxxfb.h -- cgit v1.2.3