diff --git a/[refs] b/[refs] index 212d7db741b3..45283a2021f1 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 0de4b34d466bae571b50f41c7296b85248205e35 +refs/heads/master: 868baf07b1a259f5f3803c1dc2777b6c358f83cf diff --git a/trunk/Documentation/networking/ip-sysctl.txt b/trunk/Documentation/networking/ip-sysctl.txt index ac3b4a726a1a..d99940dcfc44 100644 --- a/trunk/Documentation/networking/ip-sysctl.txt +++ b/trunk/Documentation/networking/ip-sysctl.txt @@ -187,7 +187,7 @@ tcp_cookie_size - INTEGER tcp_dsack - BOOLEAN Allows TCP to send "duplicate" SACKs. -tcp_ecn - INTEGER +tcp_ecn - BOOLEAN Enable Explicit Congestion Notification (ECN) in TCP. ECN is only used when both ends of the TCP flow support it. It is useful to avoid losses due to congestion (when the bottleneck router supports diff --git a/trunk/Documentation/sound/alsa/HD-Audio-Models.txt b/trunk/Documentation/sound/alsa/HD-Audio-Models.txt index 0caf77e59be4..16ae4300c747 100644 --- a/trunk/Documentation/sound/alsa/HD-Audio-Models.txt +++ b/trunk/Documentation/sound/alsa/HD-Audio-Models.txt @@ -296,7 +296,6 @@ Conexant 5066 ============= laptop Basic Laptop config (default) hp-laptop HP laptops, e g G60 - asus Asus K52JU, Lenovo G560 dell-laptop Dell laptops dell-vostro Dell Vostro olpc-xo-1_5 OLPC XO 1.5 diff --git a/trunk/Documentation/trace/kprobetrace.txt b/trunk/Documentation/trace/kprobetrace.txt index 6d27ab8d6e9f..5f77d94598dd 100644 --- a/trunk/Documentation/trace/kprobetrace.txt +++ b/trunk/Documentation/trace/kprobetrace.txt @@ -42,25 +42,11 @@ Synopsis of kprobe_events +|-offs(FETCHARG) : Fetch memory at FETCHARG +|- offs address.(**) NAME=FETCHARG : Set NAME as the argument name of FETCHARG. FETCHARG:TYPE : Set TYPE as the type of FETCHARG. Currently, basic types - (u8/u16/u32/u64/s8/s16/s32/s64), "string" and bitfield - are supported. + (u8/u16/u32/u64/s8/s16/s32/s64) and string are supported. (*) only for return probe. (**) this is useful for fetching a field of data structures. -Types ------ -Several types are supported for fetch-args. Kprobe tracer will access memory -by given type. Prefix 's' and 'u' means those types are signed and unsigned -respectively. Traced arguments are shown in decimal (signed) or hex (unsigned). -String type is a special type, which fetches a "null-terminated" string from -kernel space. This means it will fail and store NULL if the string container -has been paged out. -Bitfield is another special type, which takes 3 parameters, bit-width, bit- -offset, and container-size (usually 32). The syntax is; - - b@/ - Per-Probe Event Filtering ------------------------- diff --git a/trunk/MAINTAINERS b/trunk/MAINTAINERS index 531c5cf150ba..9511bff301c9 100644 --- a/trunk/MAINTAINERS +++ b/trunk/MAINTAINERS @@ -5551,11 +5551,12 @@ S: Supported F: drivers/scsi/be2iscsi/ SERVER ENGINES 10Gbps NIC - BladeEngine 2 DRIVER -M: Sathya Perla -M: Subbu Seetharaman -M: Ajit Khaparde +M: Sathya Perla +M: Subbu Seetharaman +M: Sarveshwar Bandi +M: Ajit Khaparde L: netdev@vger.kernel.org -W: http://www.emulex.com +W: http://www.serverengines.com S: Supported F: drivers/net/benet/ @@ -6786,12 +6787,12 @@ S: Maintained F: drivers/net/wireless/wl1251/* WL1271 WIRELESS DRIVER -M: Luciano Coelho +M: Luciano Coelho L: linux-wireless@vger.kernel.org -W: http://wireless.kernel.org/en/users/Drivers/wl12xx +W: http://wireless.kernel.org T: git git://git.kernel.org/pub/scm/linux/kernel/git/luca/wl12xx.git S: Maintained -F: drivers/net/wireless/wl12xx/ +F: drivers/net/wireless/wl12xx/wl1271* F: include/linux/wl12xx.h WL3501 WIRELESS PCMCIA CARD DRIVER diff --git a/trunk/Makefile b/trunk/Makefile index c9c8c8fd2591..66e7e977ddc0 100644 --- a/trunk/Makefile +++ b/trunk/Makefile @@ -1,7 +1,7 @@ VERSION = 2 PATCHLEVEL = 6 SUBLEVEL = 38 -EXTRAVERSION = -rc4 +EXTRAVERSION = -rc3 NAME = Flesh-Eating Bats with Fangs # *DOCUMENTATION* diff --git a/trunk/arch/arm/mach-ep93xx/core.c b/trunk/arch/arm/mach-ep93xx/core.c index 82079545adc4..ffdf87be2958 100644 --- a/trunk/arch/arm/mach-ep93xx/core.c +++ b/trunk/arch/arm/mach-ep93xx/core.c @@ -838,7 +838,7 @@ EXPORT_SYMBOL(ep93xx_i2s_release); static struct resource ep93xx_ac97_resources[] = { { .start = EP93XX_AAC_PHYS_BASE, - .end = EP93XX_AAC_PHYS_BASE + 0xac - 1, + .end = EP93XX_AAC_PHYS_BASE + 0xb0 - 1, .flags = IORESOURCE_MEM, }, { diff --git a/trunk/arch/arm/mach-imx/mach-mx25_3ds.c b/trunk/arch/arm/mach-imx/mach-mx25_3ds.c index 8382e7902078..aa76cfd9f348 100644 --- a/trunk/arch/arm/mach-imx/mach-mx25_3ds.c +++ b/trunk/arch/arm/mach-imx/mach-mx25_3ds.c @@ -180,7 +180,7 @@ static const uint32_t mx25pdk_keymap[] = { KEY(3, 3, KEY_POWER), }; -static const struct matrix_keymap_data mx25pdk_keymap_data __initconst = { +static const struct matrix_keymap_data mx25pdk_keymap_data __initdata = { .keymap = mx25pdk_keymap, .keymap_size = ARRAY_SIZE(mx25pdk_keymap), }; diff --git a/trunk/arch/arm/mach-ixp4xx/common.c b/trunk/arch/arm/mach-ixp4xx/common.c index 9fd894271d5d..4dc68d6bb6be 100644 --- a/trunk/arch/arm/mach-ixp4xx/common.c +++ b/trunk/arch/arm/mach-ixp4xx/common.c @@ -432,7 +432,7 @@ static struct clocksource clocksource_ixp4xx = { .flags = CLOCK_SOURCE_IS_CONTINUOUS, }; -unsigned long ixp4xx_timer_freq = IXP4XX_TIMER_FREQ; +unsigned long ixp4xx_timer_freq = FREQ; EXPORT_SYMBOL(ixp4xx_timer_freq); static void __init ixp4xx_clocksource_init(void) { @@ -496,7 +496,7 @@ static struct clock_event_device clockevent_ixp4xx = { static void __init ixp4xx_clockevent_init(void) { - clockevent_ixp4xx.mult = div_sc(IXP4XX_TIMER_FREQ, NSEC_PER_SEC, + clockevent_ixp4xx.mult = div_sc(FREQ, NSEC_PER_SEC, clockevent_ixp4xx.shift); clockevent_ixp4xx.max_delta_ns = clockevent_delta2ns(0xfffffffe, &clockevent_ixp4xx); diff --git a/trunk/arch/arm/mach-ixp4xx/include/mach/timex.h b/trunk/arch/arm/mach-ixp4xx/include/mach/timex.h index c9e930f29339..2c3f93c3eb79 100644 --- a/trunk/arch/arm/mach-ixp4xx/include/mach/timex.h +++ b/trunk/arch/arm/mach-ixp4xx/include/mach/timex.h @@ -10,7 +10,6 @@ * 66.66... MHz. We do a convulted calculation of CLOCK_TICK_RATE b/c the * timer register ignores the bottom 2 bits of the LATCH value. */ -#define IXP4XX_TIMER_FREQ 66666000 -#define CLOCK_TICK_RATE \ - (((IXP4XX_TIMER_FREQ / HZ & ~IXP4XX_OST_RELOAD_MASK) + 1) * HZ) +#define FREQ 66666000 +#define CLOCK_TICK_RATE (((FREQ / HZ & ~IXP4XX_OST_RELOAD_MASK) + 1) * HZ) diff --git a/trunk/arch/arm/mach-ixp4xx/ixp4xx_qmgr.c b/trunk/arch/arm/mach-ixp4xx/ixp4xx_qmgr.c index 852f7c9f87d0..bfdbe4b5a3cc 100644 --- a/trunk/arch/arm/mach-ixp4xx/ixp4xx_qmgr.c +++ b/trunk/arch/arm/mach-ixp4xx/ixp4xx_qmgr.c @@ -265,11 +265,6 @@ void qmgr_release_queue(unsigned int queue) qmgr_queue_descs[queue], queue); qmgr_queue_descs[queue][0] = '\x0'; #endif - - while ((addr = qmgr_get_entry(queue))) - printk(KERN_ERR "qmgr: released queue %i not empty: 0x%08X\n", - queue, addr); - __raw_writel(0, &qmgr_regs->sram[queue]); used_sram_bitmap[0] &= ~mask[0]; @@ -280,6 +275,10 @@ void qmgr_release_queue(unsigned int queue) spin_unlock_irq(&qmgr_lock); module_put(THIS_MODULE); + + while ((addr = qmgr_get_entry(queue))) + printk(KERN_ERR "qmgr: released queue %i not empty: 0x%08X\n", + queue, addr); } static int qmgr_init(void) diff --git a/trunk/arch/arm/mach-mxs/clock-mx23.c b/trunk/arch/arm/mach-mxs/clock-mx23.c index ca72a05ed9c1..b1a362ebfded 100644 --- a/trunk/arch/arm/mach-mxs/clock-mx23.c +++ b/trunk/arch/arm/mach-mxs/clock-mx23.c @@ -304,7 +304,7 @@ static int name##_set_rate(struct clk *clk, unsigned long rate) \ reg = __raw_readl(CLKCTRL_BASE_ADDR + HW_CLKCTRL_##dr); \ reg &= ~BM_CLKCTRL_##dr##_DIV; \ reg |= div << BP_CLKCTRL_##dr##_DIV; \ - if (reg & (1 << clk->enable_shift)) { \ + if (reg | (1 << clk->enable_shift)) { \ pr_err("%s: clock is gated\n", __func__); \ return -EINVAL; \ } \ @@ -347,7 +347,7 @@ static int name##_set_parent(struct clk *clk, struct clk *parent) \ { \ if (parent != clk->parent) { \ __raw_writel(BM_CLKCTRL_CLKSEQ_BYPASS_##bit, \ - CLKCTRL_BASE_ADDR + HW_CLKCTRL_CLKSEQ_TOG); \ + HW_CLKCTRL_CLKSEQ_TOG); \ clk->parent = parent; \ } \ \ diff --git a/trunk/arch/arm/mach-mxs/clock-mx28.c b/trunk/arch/arm/mach-mxs/clock-mx28.c index fd1c4c54b8e5..56312c092a9e 100644 --- a/trunk/arch/arm/mach-mxs/clock-mx28.c +++ b/trunk/arch/arm/mach-mxs/clock-mx28.c @@ -355,12 +355,12 @@ static int name##_set_rate(struct clk *clk, unsigned long rate) \ } else { \ reg &= ~BM_CLKCTRL_##dr##_DIV; \ reg |= div << BP_CLKCTRL_##dr##_DIV; \ - if (reg & (1 << clk->enable_shift)) { \ + if (reg | (1 << clk->enable_shift)) { \ pr_err("%s: clock is gated\n", __func__); \ return -EINVAL; \ } \ } \ - __raw_writel(reg, CLKCTRL_BASE_ADDR + HW_CLKCTRL_##dr); \ + __raw_writel(reg, CLKCTRL_BASE_ADDR + HW_CLKCTRL_CPU); \ \ for (i = 10000; i; i--) \ if (!(__raw_readl(CLKCTRL_BASE_ADDR + \ @@ -483,7 +483,7 @@ static int name##_set_parent(struct clk *clk, struct clk *parent) \ { \ if (parent != clk->parent) { \ __raw_writel(BM_CLKCTRL_CLKSEQ_BYPASS_##bit, \ - CLKCTRL_BASE_ADDR + HW_CLKCTRL_CLKSEQ_TOG); \ + HW_CLKCTRL_CLKSEQ_TOG); \ clk->parent = parent; \ } \ \ @@ -609,6 +609,7 @@ static struct clk_lookup lookups[] = { _REGISTER_CLOCK("duart", NULL, uart_clk) _REGISTER_CLOCK("imx28-fec.0", NULL, fec_clk) _REGISTER_CLOCK("imx28-fec.1", NULL, fec_clk) + _REGISTER_CLOCK("fec.0", NULL, fec_clk) _REGISTER_CLOCK("rtc", NULL, rtc_clk) _REGISTER_CLOCK("pll2", NULL, pll2_clk) _REGISTER_CLOCK(NULL, "hclk", hbus_clk) diff --git a/trunk/arch/arm/mach-mxs/clock.c b/trunk/arch/arm/mach-mxs/clock.c index a7093c88e6a6..e7d2269cf70e 100644 --- a/trunk/arch/arm/mach-mxs/clock.c +++ b/trunk/arch/arm/mach-mxs/clock.c @@ -57,6 +57,7 @@ static void __clk_disable(struct clk *clk) if (clk->disable) clk->disable(clk); __clk_disable(clk->parent); + __clk_disable(clk->secondary); } } @@ -67,6 +68,7 @@ static int __clk_enable(struct clk *clk) if (clk->usecount++ == 0) { __clk_enable(clk->parent); + __clk_enable(clk->secondary); if (clk->enable) clk->enable(clk); diff --git a/trunk/arch/arm/mach-mxs/gpio.c b/trunk/arch/arm/mach-mxs/gpio.c index cb0c0e83a527..d7ad7a61366d 100644 --- a/trunk/arch/arm/mach-mxs/gpio.c +++ b/trunk/arch/arm/mach-mxs/gpio.c @@ -139,8 +139,6 @@ static void mxs_gpio_irq_handler(u32 irq, struct irq_desc *desc) struct mxs_gpio_port *port = (struct mxs_gpio_port *)get_irq_data(irq); u32 gpio_irq_no_base = port->virtual_irq_start; - desc->irq_data.chip->irq_ack(&desc->irq_data); - irq_stat = __raw_readl(port->base + PINCTRL_IRQSTAT(port->id)) & __raw_readl(port->base + PINCTRL_IRQEN(port->id)); diff --git a/trunk/arch/arm/mach-mxs/include/mach/clock.h b/trunk/arch/arm/mach-mxs/include/mach/clock.h index 592c9ab5d760..041e276d8a32 100644 --- a/trunk/arch/arm/mach-mxs/include/mach/clock.h +++ b/trunk/arch/arm/mach-mxs/include/mach/clock.h @@ -29,6 +29,8 @@ struct clk { int id; /* Source clock this clk depends on */ struct clk *parent; + /* Secondary clock to enable/disable with this clock */ + struct clk *secondary; /* Reference count of clock enable/disable */ __s8 usecount; /* Register bit position for clock's enable/disable control. */ diff --git a/trunk/arch/arm/mach-omap1/lcd_dma.c b/trunk/arch/arm/mach-omap1/lcd_dma.c index 453809359ba6..c9088d85da04 100644 --- a/trunk/arch/arm/mach-omap1/lcd_dma.c +++ b/trunk/arch/arm/mach-omap1/lcd_dma.c @@ -37,7 +37,7 @@ int omap_lcd_dma_running(void) * On OMAP1510, internal LCD controller will start the transfer * when it gets enabled, so assume DMA running if LCD enabled. */ - if (cpu_is_omap15xx()) + if (cpu_is_omap1510()) if (omap_readw(OMAP_LCDC_CONTROL) & OMAP_LCDC_CTRL_LCD_EN) return 1; @@ -95,7 +95,7 @@ EXPORT_SYMBOL(omap_set_lcd_dma_single_transfer); void omap_set_lcd_dma_b1_rotation(int rotate) { - if (cpu_is_omap15xx()) { + if (cpu_is_omap1510()) { printk(KERN_ERR "DMA rotation is not supported in 1510 mode\n"); BUG(); return; @@ -106,7 +106,7 @@ EXPORT_SYMBOL(omap_set_lcd_dma_b1_rotation); void omap_set_lcd_dma_b1_mirror(int mirror) { - if (cpu_is_omap15xx()) { + if (cpu_is_omap1510()) { printk(KERN_ERR "DMA mirror is not supported in 1510 mode\n"); BUG(); } @@ -116,7 +116,7 @@ EXPORT_SYMBOL(omap_set_lcd_dma_b1_mirror); void omap_set_lcd_dma_b1_vxres(unsigned long vxres) { - if (cpu_is_omap15xx()) { + if (cpu_is_omap1510()) { printk(KERN_ERR "DMA virtual resulotion is not supported " "in 1510 mode\n"); BUG(); @@ -127,7 +127,7 @@ EXPORT_SYMBOL(omap_set_lcd_dma_b1_vxres); void omap_set_lcd_dma_b1_scale(unsigned int xscale, unsigned int yscale) { - if (cpu_is_omap15xx()) { + if (cpu_is_omap1510()) { printk(KERN_ERR "DMA scale is not supported in 1510 mode\n"); BUG(); } @@ -177,7 +177,7 @@ static void set_b1_regs(void) bottom = PIXADDR(lcd_dma.xres - 1, lcd_dma.yres - 1); /* 1510 DMA requires the bottom address to be 2 more * than the actual last memory access location. */ - if (cpu_is_omap15xx() && + if (cpu_is_omap1510() && lcd_dma.data_type == OMAP_DMA_DATA_TYPE_S32) bottom += 2; ei = PIXSTEP(0, 0, 1, 0); @@ -241,7 +241,7 @@ static void set_b1_regs(void) return; /* Suppress warning about uninitialized vars */ } - if (cpu_is_omap15xx()) { + if (cpu_is_omap1510()) { omap_writew(top >> 16, OMAP1510_DMA_LCD_TOP_F1_U); omap_writew(top, OMAP1510_DMA_LCD_TOP_F1_L); omap_writew(bottom >> 16, OMAP1510_DMA_LCD_BOT_F1_U); @@ -343,7 +343,7 @@ void omap_free_lcd_dma(void) BUG(); return; } - if (!cpu_is_omap15xx()) + if (!cpu_is_omap1510()) omap_writew(omap_readw(OMAP1610_DMA_LCD_CCR) & ~1, OMAP1610_DMA_LCD_CCR); lcd_dma.reserved = 0; @@ -360,7 +360,7 @@ void omap_enable_lcd_dma(void) * connected. Otherwise the OMAP internal controller will * start the transfer when it gets enabled. */ - if (cpu_is_omap15xx() || !lcd_dma.ext_ctrl) + if (cpu_is_omap1510() || !lcd_dma.ext_ctrl) return; w = omap_readw(OMAP1610_DMA_LCD_CTRL); @@ -378,14 +378,14 @@ EXPORT_SYMBOL(omap_enable_lcd_dma); void omap_setup_lcd_dma(void) { BUG_ON(lcd_dma.active); - if (!cpu_is_omap15xx()) { + if (!cpu_is_omap1510()) { /* Set some reasonable defaults */ omap_writew(0x5440, OMAP1610_DMA_LCD_CCR); omap_writew(0x9102, OMAP1610_DMA_LCD_CSDP); omap_writew(0x0004, OMAP1610_DMA_LCD_LCH_CTRL); } set_b1_regs(); - if (!cpu_is_omap15xx()) { + if (!cpu_is_omap1510()) { u16 w; w = omap_readw(OMAP1610_DMA_LCD_CCR); @@ -407,7 +407,7 @@ void omap_stop_lcd_dma(void) u16 w; lcd_dma.active = 0; - if (cpu_is_omap15xx() || !lcd_dma.ext_ctrl) + if (cpu_is_omap1510() || !lcd_dma.ext_ctrl) return; w = omap_readw(OMAP1610_DMA_LCD_CCR); diff --git a/trunk/arch/arm/mach-omap1/time.c b/trunk/arch/arm/mach-omap1/time.c index 6885d2fac183..f83fc335c613 100644 --- a/trunk/arch/arm/mach-omap1/time.c +++ b/trunk/arch/arm/mach-omap1/time.c @@ -44,6 +44,7 @@ #include #include #include +#include #include #include diff --git a/trunk/arch/arm/mach-omap2/board-devkit8000.c b/trunk/arch/arm/mach-omap2/board-devkit8000.c index 9a2a31e011ce..e906e05bb41b 100644 --- a/trunk/arch/arm/mach-omap2/board-devkit8000.c +++ b/trunk/arch/arm/mach-omap2/board-devkit8000.c @@ -115,6 +115,9 @@ static struct omap2_hsmmc_info mmc[] = { static int devkit8000_panel_enable_lcd(struct omap_dss_device *dssdev) { + twl_i2c_write_u8(TWL4030_MODULE_GPIO, 0x80, REG_GPIODATADIR1); + twl_i2c_write_u8(TWL4030_MODULE_LED, 0x0, 0x0); + if (gpio_is_valid(dssdev->reset_gpio)) gpio_set_value_cansleep(dssdev->reset_gpio, 1); return 0; @@ -244,8 +247,6 @@ static struct gpio_led gpio_leds[]; static int devkit8000_twl_gpio_setup(struct device *dev, unsigned gpio, unsigned ngpio) { - int ret; - omap_mux_init_gpio(29, OMAP_PIN_INPUT); /* gpio + 0 is "mmc0_cd" (input/IRQ) */ mmc[0].gpio_cd = gpio + 0; @@ -254,23 +255,17 @@ static int devkit8000_twl_gpio_setup(struct device *dev, /* TWL4030_GPIO_MAX + 1 == ledB, PMU_STAT (out, active low LED) */ gpio_leds[2].gpio = gpio + TWL4030_GPIO_MAX + 1; - /* TWL4030_GPIO_MAX + 0 is "LCD_PWREN" (out, active high) */ - devkit8000_lcd_device.reset_gpio = gpio + TWL4030_GPIO_MAX + 0; - ret = gpio_request_one(devkit8000_lcd_device.reset_gpio, - GPIOF_DIR_OUT | GPIOF_INIT_LOW, "LCD_PWREN"); - if (ret < 0) { - devkit8000_lcd_device.reset_gpio = -EINVAL; - printk(KERN_ERR "Failed to request GPIO for LCD_PWRN\n"); - } + /* gpio + 1 is "LCD_PWREN" (out, active high) */ + devkit8000_lcd_device.reset_gpio = gpio + 1; + gpio_request(devkit8000_lcd_device.reset_gpio, "LCD_PWREN"); + /* Disable until needed */ + gpio_direction_output(devkit8000_lcd_device.reset_gpio, 0); /* gpio + 7 is "DVI_PD" (out, active low) */ devkit8000_dvi_device.reset_gpio = gpio + 7; - ret = gpio_request_one(devkit8000_dvi_device.reset_gpio, - GPIOF_DIR_OUT | GPIOF_INIT_LOW, "DVI PowerDown"); - if (ret < 0) { - devkit8000_dvi_device.reset_gpio = -EINVAL; - printk(KERN_ERR "Failed to request GPIO for DVI PowerDown\n"); - } + gpio_request(devkit8000_dvi_device.reset_gpio, "DVI PowerDown"); + /* Disable until needed */ + gpio_direction_output(devkit8000_dvi_device.reset_gpio, 0); return 0; } diff --git a/trunk/arch/arm/mach-omap2/board-omap4panda.c b/trunk/arch/arm/mach-omap2/board-omap4panda.c index e944025d5ef8..e001a048dc0c 100644 --- a/trunk/arch/arm/mach-omap2/board-omap4panda.c +++ b/trunk/arch/arm/mach-omap2/board-omap4panda.c @@ -409,6 +409,8 @@ static void __init omap4_panda_init(void) platform_add_devices(panda_devices, ARRAY_SIZE(panda_devices)); omap_serial_init(); omap4_twl6030_hsmmc_init(mmc); + /* OMAP4 Panda uses internal transceiver so register nop transceiver */ + usb_nop_xceiv_register(); omap4_ehci_init(); usb_musb_init(&musb_board_data); } diff --git a/trunk/arch/arm/mach-omap2/board-rm680.c b/trunk/arch/arm/mach-omap2/board-rm680.c index 39a71bb8a308..cb77be7ac44f 100644 --- a/trunk/arch/arm/mach-omap2/board-rm680.c +++ b/trunk/arch/arm/mach-omap2/board-rm680.c @@ -40,6 +40,9 @@ static struct regulator_consumer_supply rm680_vemmc_consumers[] = { static struct regulator_init_data rm680_vemmc = { .constraints = { .name = "rm680_vemmc", + .min_uV = 2900000, + .max_uV = 2900000, + .apply_uV = 1, .valid_modes_mask = REGULATOR_MODE_NORMAL | REGULATOR_MODE_STANDBY, .valid_ops_mask = REGULATOR_CHANGE_STATUS diff --git a/trunk/arch/arm/mach-omap2/mux.c b/trunk/arch/arm/mach-omap2/mux.c index 98148b6c36e9..fae49d12bc76 100644 --- a/trunk/arch/arm/mach-omap2/mux.c +++ b/trunk/arch/arm/mach-omap2/mux.c @@ -1000,7 +1000,6 @@ int __init omap_mux_init(const char *name, u32 flags, if (!partition->base) { pr_err("%s: Could not ioremap mux partition at 0x%08x\n", __func__, partition->phys); - kfree(partition); return -ENODEV; } diff --git a/trunk/arch/arm/mach-omap2/pm34xx.c b/trunk/arch/arm/mach-omap2/pm34xx.c index 2f864e4b085d..a4aa1920a75c 100644 --- a/trunk/arch/arm/mach-omap2/pm34xx.c +++ b/trunk/arch/arm/mach-omap2/pm34xx.c @@ -168,10 +168,9 @@ static void omap3_core_restore_context(void) * once during boot sequence, but this works as we are not using secure * services. */ -static void omap3_save_secure_ram_context(void) +static void omap3_save_secure_ram_context(u32 target_mpu_state) { u32 ret; - int mpu_next_state = pwrdm_read_next_pwrst(mpu_pwrdm); if (omap_type() != OMAP2_DEVICE_TYPE_GP) { /* @@ -182,7 +181,7 @@ static void omap3_save_secure_ram_context(void) pwrdm_set_next_pwrst(mpu_pwrdm, PWRDM_POWER_ON); ret = _omap_save_secure_sram((u32 *) __pa(omap3_secure_ram_storage)); - pwrdm_set_next_pwrst(mpu_pwrdm, mpu_next_state); + pwrdm_set_next_pwrst(mpu_pwrdm, target_mpu_state); /* Following is for error tracking, it should not happen */ if (ret) { printk(KERN_ERR "save_secure_sram() returns %08x\n", @@ -1095,7 +1094,7 @@ static int __init omap3_pm_init(void) local_fiq_disable(); omap_dma_global_context_save(); - omap3_save_secure_ram_context(); + omap3_save_secure_ram_context(PWRDM_POWER_ON); omap_dma_global_context_restore(); local_irq_enable(); diff --git a/trunk/arch/arm/mach-omap2/smartreflex.c b/trunk/arch/arm/mach-omap2/smartreflex.c index c37e823266d3..77ecebf3fae2 100644 --- a/trunk/arch/arm/mach-omap2/smartreflex.c +++ b/trunk/arch/arm/mach-omap2/smartreflex.c @@ -780,7 +780,8 @@ static int omap_sr_autocomp_show(void *data, u64 *val) struct omap_sr *sr_info = (struct omap_sr *) data; if (!sr_info) { - pr_warning("%s: omap_sr struct not found\n", __func__); + pr_warning("%s: omap_sr struct for sr_%s not found\n", + __func__, sr_info->voltdm->name); return -EINVAL; } @@ -794,7 +795,8 @@ static int omap_sr_autocomp_store(void *data, u64 val) struct omap_sr *sr_info = (struct omap_sr *) data; if (!sr_info) { - pr_warning("%s: omap_sr struct not found\n", __func__); + pr_warning("%s: omap_sr struct for sr_%s not found\n", + __func__, sr_info->voltdm->name); return -EINVAL; } @@ -832,8 +834,7 @@ static int __init omap_sr_probe(struct platform_device *pdev) if (!pdata) { dev_err(&pdev->dev, "%s: platform data missing\n", __func__); - ret = -EINVAL; - goto err_free_devinfo; + return -EINVAL; } mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); @@ -965,7 +966,7 @@ static int __devexit omap_sr_remove(struct platform_device *pdev) } sr_info = _sr_lookup(pdata->voltdm); - if (IS_ERR(sr_info)) { + if (!sr_info) { dev_warn(&pdev->dev, "%s: omap_sr struct not found\n", __func__); return -EINVAL; diff --git a/trunk/arch/arm/mach-omap2/voltage.c b/trunk/arch/arm/mach-omap2/voltage.c index 12be525b8df4..ed6079c94c57 100644 --- a/trunk/arch/arm/mach-omap2/voltage.c +++ b/trunk/arch/arm/mach-omap2/voltage.c @@ -471,7 +471,6 @@ static void __init vdd_debugfs_init(struct omap_vdd_info *vdd) strcat(name, vdd->voltdm.name); vdd->debug_dir = debugfs_create_dir(name, voltage_dir); - kfree(name); if (IS_ERR(vdd->debug_dir)) { pr_warning("%s: Unable to create debugfs directory for" " vdd_%s\n", __func__, vdd->voltdm.name); diff --git a/trunk/arch/arm/plat-mxc/include/mach/uncompress.h b/trunk/arch/arm/plat-mxc/include/mach/uncompress.h index ff469c4f1d76..3a70ebf0477f 100644 --- a/trunk/arch/arm/plat-mxc/include/mach/uncompress.h +++ b/trunk/arch/arm/plat-mxc/include/mach/uncompress.h @@ -95,7 +95,6 @@ static __inline__ void __arch_decomp_setup(unsigned long arch_id) case MACH_TYPE_MX35_3DS: case MACH_TYPE_PCM043: case MACH_TYPE_LILLY1131: - case MACH_TYPE_VPR200: uart_base = MX3X_UART1_BASE_ADDR; break; case MACH_TYPE_MAGX_ZN5: @@ -103,7 +102,6 @@ static __inline__ void __arch_decomp_setup(unsigned long arch_id) break; case MACH_TYPE_MX51_BABBAGE: case MACH_TYPE_EUKREA_CPUIMX51SD: - case MACH_TYPE_MX51_3DS: uart_base = MX51_UART1_BASE_ADDR; break; case MACH_TYPE_MX50_RDP: diff --git a/trunk/arch/arm/tools/mach-types b/trunk/arch/arm/tools/mach-types index 9d6feaabbe7d..2fea897ebeb1 100644 --- a/trunk/arch/arm/tools/mach-types +++ b/trunk/arch/arm/tools/mach-types @@ -12,7 +12,7 @@ # # http://www.arm.linux.org.uk/developer/machines/?action=new # -# Last update: Mon Feb 7 08:59:27 2011 +# Last update: Sun Dec 12 23:24:27 2010 # # machine_is_xxx CONFIG_xxxx MACH_TYPE_xxx number # @@ -2240,7 +2240,7 @@ arm_ultimator2 MACH_ARM_ULTIMATOR2 ARM_ULTIMATOR2 2250 vs_v210 MACH_VS_V210 VS_V210 2252 vs_v212 MACH_VS_V212 VS_V212 2253 hmt MACH_HMT HMT 2254 -km_kirkwood MACH_KM_KIRKWOOD KM_KIRKWOOD 2255 +suen3 MACH_SUEN3 SUEN3 2255 vesper MACH_VESPER VESPER 2256 str9 MACH_STR9 STR9 2257 omap3_wl_ff MACH_OMAP3_WL_FF OMAP3_WL_FF 2258 @@ -2987,7 +2987,7 @@ pxwnas_500_1000 MACH_PXWNAS_500_1000 PXWNAS_500_1000 3001 ea20 MACH_EA20 EA20 3002 awm2 MACH_AWM2 AWM2 3003 ti8148evm MACH_TI8148EVM TI8148EVM 3004 -seaboard MACH_SEABOARD SEABOARD 3005 +tegra_seaboard MACH_TEGRA_SEABOARD TEGRA_SEABOARD 3005 linkstation_chlv2 MACH_LINKSTATION_CHLV2 LINKSTATION_CHLV2 3006 tera_pro2_rack MACH_TERA_PRO2_RACK TERA_PRO2_RACK 3007 rubys MACH_RUBYS RUBYS 3008 @@ -3190,7 +3190,7 @@ synergy MACH_SYNERGY SYNERGY 3205 ics_if_voip MACH_ICS_IF_VOIP ICS_IF_VOIP 3206 wlf_cragg_6410 MACH_WLF_CRAGG_6410 WLF_CRAGG_6410 3207 punica MACH_PUNICA PUNICA 3208 -trimslice MACH_TRIMSLICE TRIMSLICE 3209 +sbc_nt250 MACH_SBC_NT250 SBC_NT250 3209 mx27_wmultra MACH_MX27_WMULTRA MX27_WMULTRA 3210 mackerel MACH_MACKEREL MACKEREL 3211 fa9x27 MACH_FA9X27 FA9X27 3213 @@ -3219,100 +3219,3 @@ pivicc MACH_PIVICC PIVICC 3235 pcm048 MACH_PCM048 PCM048 3236 dds MACH_DDS DDS 3237 chalten_xa1 MACH_CHALTEN_XA1 CHALTEN_XA1 3238 -ts48xx MACH_TS48XX TS48XX 3239 -tonga2_tfttimer MACH_TONGA2_TFTTIMER TONGA2_TFTTIMER 3240 -whistler MACH_WHISTLER WHISTLER 3241 -asl_phoenix MACH_ASL_PHOENIX ASL_PHOENIX 3242 -at91sam9263otlite MACH_AT91SAM9263OTLITE AT91SAM9263OTLITE 3243 -ddplug MACH_DDPLUG DDPLUG 3244 -d2plug MACH_D2PLUG D2PLUG 3245 -kzm9d MACH_KZM9D KZM9D 3246 -verdi_lte MACH_VERDI_LTE VERDI_LTE 3247 -nanozoom MACH_NANOZOOM NANOZOOM 3248 -dm3730_som_lv MACH_DM3730_SOM_LV DM3730_SOM_LV 3249 -dm3730_torpedo MACH_DM3730_TORPEDO DM3730_TORPEDO 3250 -anchovy MACH_ANCHOVY ANCHOVY 3251 -re2rev20 MACH_RE2REV20 RE2REV20 3253 -re2rev21 MACH_RE2REV21 RE2REV21 3254 -cns21xx MACH_CNS21XX CNS21XX 3255 -rider MACH_RIDER RIDER 3257 -nsk330 MACH_NSK330 NSK330 3258 -cns2133evb MACH_CNS2133EVB CNS2133EVB 3259 -z3_816x_mod MACH_Z3_816X_MOD Z3_816X_MOD 3260 -z3_814x_mod MACH_Z3_814X_MOD Z3_814X_MOD 3261 -beect MACH_BEECT BEECT 3262 -dma_thunderbug MACH_DMA_THUNDERBUG DMA_THUNDERBUG 3263 -omn_at91sam9g20 MACH_OMN_AT91SAM9G20 OMN_AT91SAM9G20 3264 -mx25_e2s_uc MACH_MX25_E2S_UC MX25_E2S_UC 3265 -mione MACH_MIONE MIONE 3266 -top9000_tcu MACH_TOP9000_TCU TOP9000_TCU 3267 -top9000_bsl MACH_TOP9000_BSL TOP9000_BSL 3268 -kingdom MACH_KINGDOM KINGDOM 3269 -armadillo460 MACH_ARMADILLO460 ARMADILLO460 3270 -lq2 MACH_LQ2 LQ2 3271 -sweda_tms2 MACH_SWEDA_TMS2 SWEDA_TMS2 3272 -mx53_loco MACH_MX53_LOCO MX53_LOCO 3273 -acer_a8 MACH_ACER_A8 ACER_A8 3275 -acer_gauguin MACH_ACER_GAUGUIN ACER_GAUGUIN 3276 -guppy MACH_GUPPY GUPPY 3277 -mx61_ard MACH_MX61_ARD MX61_ARD 3278 -tx53 MACH_TX53 TX53 3279 -omapl138_case_a3 MACH_OMAPL138_CASE_A3 OMAPL138_CASE_A3 3280 -uemd MACH_UEMD UEMD 3281 -ccwmx51mut MACH_CCWMX51MUT CCWMX51MUT 3282 -rockhopper MACH_ROCKHOPPER ROCKHOPPER 3283 -nookcolor MACH_NOOKCOLOR NOOKCOLOR 3284 -hkdkc100 MACH_HKDKC100 HKDKC100 3285 -ts42xx MACH_TS42XX TS42XX 3286 -aebl MACH_AEBL AEBL 3287 -wario MACH_WARIO WARIO 3288 -gfs_spm MACH_GFS_SPM GFS_SPM 3289 -cm_t3730 MACH_CM_T3730 CM_T3730 3290 -isc3 MACH_ISC3 ISC3 3291 -rascal MACH_RASCAL RASCAL 3292 -hrefv60 MACH_HREFV60 HREFV60 3293 -tpt_2_0 MACH_TPT_2_0 TPT_2_0 3294 -pyramid_td MACH_PYRAMID_TD PYRAMID_TD 3295 -splendor MACH_SPLENDOR SPLENDOR 3296 -guf_planet MACH_GUF_PLANET GUF_PLANET 3297 -msm8x60_qt MACH_MSM8X60_QT MSM8X60_QT 3298 -htc_hd_mini MACH_HTC_HD_MINI HTC_HD_MINI 3299 -athene MACH_ATHENE ATHENE 3300 -deep_r_ek_1 MACH_DEEP_R_EK_1 DEEP_R_EK_1 3301 -vivow_ct MACH_VIVOW_CT VIVOW_CT 3302 -nery_1000 MACH_NERY_1000 NERY_1000 3303 -rfl109145_ssrv MACH_RFL109145_SSRV RFL109145_SSRV 3304 -nmh MACH_NMH NMH 3305 -wn802t MACH_WN802T WN802T 3306 -dragonet MACH_DRAGONET DRAGONET 3307 -geneva_b MACH_GENEVA_B GENEVA_B 3308 -at91sam9263desk16l MACH_AT91SAM9263DESK16L AT91SAM9263DESK16L 3309 -bcmhana_sv MACH_BCMHANA_SV BCMHANA_SV 3310 -bcmhana_tablet MACH_BCMHANA_TABLET BCMHANA_TABLET 3311 -koi MACH_KOI KOI 3312 -ts4800 MACH_TS4800 TS4800 3313 -tqma9263 MACH_TQMA9263 TQMA9263 3314 -holiday MACH_HOLIDAY HOLIDAY 3315 -dma_6410 MACH_DMA6410 DMA6410 3316 -pcats_overlay MACH_PCATS_OVERLAY PCATS_OVERLAY 3317 -hwgw6410 MACH_HWGW6410 HWGW6410 3318 -shenzhou MACH_SHENZHOU SHENZHOU 3319 -cwme9210 MACH_CWME9210 CWME9210 3320 -cwme9210js MACH_CWME9210JS CWME9210JS 3321 -pgs_v1 MACH_PGS_SITARA PGS_SITARA 3322 -colibri_tegra2 MACH_COLIBRI_TEGRA2 COLIBRI_TEGRA2 3323 -w21 MACH_W21 W21 3324 -polysat1 MACH_POLYSAT1 POLYSAT1 3325 -dataway MACH_DATAWAY DATAWAY 3326 -cobral138 MACH_COBRAL138 COBRAL138 3327 -roverpcs8 MACH_ROVERPCS8 ROVERPCS8 3328 -marvelc MACH_MARVELC MARVELC 3329 -navefihid MACH_NAVEFIHID NAVEFIHID 3330 -dm365_cv100 MACH_DM365_CV100 DM365_CV100 3331 -able MACH_ABLE ABLE 3332 -legacy MACH_LEGACY LEGACY 3333 -icong MACH_ICONG ICONG 3334 -rover_g8 MACH_ROVER_G8 ROVER_G8 3335 -t5388p MACH_T5388P T5388P 3336 -dingo MACH_DINGO DINGO 3337 -goflexhome MACH_GOFLEXHOME GOFLEXHOME 3338 diff --git a/trunk/arch/m32r/kernel/irq.c b/trunk/arch/m32r/kernel/irq.c index 76eaf3883fbd..f745c1287f3a 100644 --- a/trunk/arch/m32r/kernel/irq.c +++ b/trunk/arch/m32r/kernel/irq.c @@ -80,7 +80,7 @@ asmlinkage unsigned int do_IRQ(int irq, struct pt_regs *regs) #ifdef CONFIG_DEBUG_STACKOVERFLOW /* FIXME M32R */ #endif - generic_handle_irq(irq); + __do_IRQ(irq); irq_exit(); set_irq_regs(old_regs); diff --git a/trunk/arch/powerpc/include/asm/mmu-book3e.h b/trunk/arch/powerpc/include/asm/mmu-book3e.h index 17194fcd4040..8eaed81ea642 100644 --- a/trunk/arch/powerpc/include/asm/mmu-book3e.h +++ b/trunk/arch/powerpc/include/asm/mmu-book3e.h @@ -40,8 +40,8 @@ /* MAS registers bit definitions */ -#define MAS0_TLBSEL(x) (((x) << 28) & 0x30000000) -#define MAS0_ESEL(x) (((x) << 16) & 0x0FFF0000) +#define MAS0_TLBSEL(x) ((x << 28) & 0x30000000) +#define MAS0_ESEL(x) ((x << 16) & 0x0FFF0000) #define MAS0_NV(x) ((x) & 0x00000FFF) #define MAS0_HES 0x00004000 #define MAS0_WQ_ALLWAYS 0x00000000 @@ -50,12 +50,12 @@ #define MAS1_VALID 0x80000000 #define MAS1_IPROT 0x40000000 -#define MAS1_TID(x) (((x) << 16) & 0x3FFF0000) +#define MAS1_TID(x) ((x << 16) & 0x3FFF0000) #define MAS1_IND 0x00002000 #define MAS1_TS 0x00001000 #define MAS1_TSIZE_MASK 0x00000f80 #define MAS1_TSIZE_SHIFT 7 -#define MAS1_TSIZE(x) (((x) << MAS1_TSIZE_SHIFT) & MAS1_TSIZE_MASK) +#define MAS1_TSIZE(x) ((x << MAS1_TSIZE_SHIFT) & MAS1_TSIZE_MASK) #define MAS2_EPN 0xFFFFF000 #define MAS2_X0 0x00000040 diff --git a/trunk/arch/powerpc/include/asm/page.h b/trunk/arch/powerpc/include/asm/page.h index da4b20008541..53b64be40eb2 100644 --- a/trunk/arch/powerpc/include/asm/page.h +++ b/trunk/arch/powerpc/include/asm/page.h @@ -101,7 +101,7 @@ extern phys_addr_t kernstart_addr; #ifdef CONFIG_FLATMEM #define ARCH_PFN_OFFSET (MEMORY_START >> PAGE_SHIFT) -#define pfn_valid(pfn) ((pfn) >= ARCH_PFN_OFFSET && (pfn) < max_mapnr) +#define pfn_valid(pfn) ((pfn) >= ARCH_PFN_OFFSET && (pfn) < (ARCH_PFN_OFFSET + max_mapnr)) #endif #define virt_to_page(kaddr) pfn_to_page(__pa(kaddr) >> PAGE_SHIFT) diff --git a/trunk/arch/powerpc/kernel/cpu_setup_6xx.S b/trunk/arch/powerpc/kernel/cpu_setup_6xx.S index f8cd9fba4d35..55cba4a8a959 100644 --- a/trunk/arch/powerpc/kernel/cpu_setup_6xx.S +++ b/trunk/arch/powerpc/kernel/cpu_setup_6xx.S @@ -18,7 +18,7 @@ #include _GLOBAL(__setup_cpu_603) - mflr r5 + mflr r4 BEGIN_MMU_FTR_SECTION li r10,0 mtspr SPRN_SPRG_603_LRU,r10 /* init SW LRU tracking */ @@ -27,60 +27,60 @@ BEGIN_FTR_SECTION bl __init_fpu_registers END_FTR_SECTION_IFCLR(CPU_FTR_FPU_UNAVAILABLE) bl setup_common_caches - mtlr r5 + mtlr r4 blr _GLOBAL(__setup_cpu_604) - mflr r5 + mflr r4 bl setup_common_caches bl setup_604_hid0 - mtlr r5 + mtlr r4 blr _GLOBAL(__setup_cpu_750) - mflr r5 + mflr r4 bl __init_fpu_registers bl setup_common_caches bl setup_750_7400_hid0 - mtlr r5 + mtlr r4 blr _GLOBAL(__setup_cpu_750cx) - mflr r5 + mflr r4 bl __init_fpu_registers bl setup_common_caches bl setup_750_7400_hid0 bl setup_750cx - mtlr r5 + mtlr r4 blr _GLOBAL(__setup_cpu_750fx) - mflr r5 + mflr r4 bl __init_fpu_registers bl setup_common_caches bl setup_750_7400_hid0 bl setup_750fx - mtlr r5 + mtlr r4 blr _GLOBAL(__setup_cpu_7400) - mflr r5 + mflr r4 bl __init_fpu_registers bl setup_7400_workarounds bl setup_common_caches bl setup_750_7400_hid0 - mtlr r5 + mtlr r4 blr _GLOBAL(__setup_cpu_7410) - mflr r5 + mflr r4 bl __init_fpu_registers bl setup_7410_workarounds bl setup_common_caches bl setup_750_7400_hid0 li r3,0 mtspr SPRN_L2CR2,r3 - mtlr r5 + mtlr r4 blr _GLOBAL(__setup_cpu_745x) - mflr r5 + mflr r4 bl setup_common_caches bl setup_745x_specifics - mtlr r5 + mtlr r4 blr /* Enable caches for 603's, 604, 750 & 7400 */ @@ -194,10 +194,10 @@ setup_750cx: cror 4*cr0+eq,4*cr0+eq,4*cr1+eq cror 4*cr0+eq,4*cr0+eq,4*cr2+eq bnelr - lwz r6,CPU_SPEC_FEATURES(r4) + lwz r6,CPU_SPEC_FEATURES(r5) li r7,CPU_FTR_CAN_NAP andc r6,r6,r7 - stw r6,CPU_SPEC_FEATURES(r4) + stw r6,CPU_SPEC_FEATURES(r5) blr /* 750fx specific @@ -225,12 +225,12 @@ BEGIN_FTR_SECTION andis. r11,r11,L3CR_L3E@h beq 1f END_FTR_SECTION_IFSET(CPU_FTR_L3CR) - lwz r6,CPU_SPEC_FEATURES(r4) + lwz r6,CPU_SPEC_FEATURES(r5) andi. r0,r6,CPU_FTR_L3_DISABLE_NAP beq 1f li r7,CPU_FTR_CAN_NAP andc r6,r6,r7 - stw r6,CPU_SPEC_FEATURES(r4) + stw r6,CPU_SPEC_FEATURES(r5) 1: mfspr r11,SPRN_HID0 diff --git a/trunk/arch/powerpc/kernel/cputable.c b/trunk/arch/powerpc/kernel/cputable.c index e8e915ce3d8d..8d74a24c5502 100644 --- a/trunk/arch/powerpc/kernel/cputable.c +++ b/trunk/arch/powerpc/kernel/cputable.c @@ -2076,8 +2076,8 @@ static void __init setup_cpu_spec(unsigned long offset, struct cpu_spec *s) * pointer on ppc64 and booke as we are running at 0 in real mode * on ppc64 and reloc_offset is always 0 on booke. */ - if (t->cpu_setup) { - t->cpu_setup(offset, t); + if (s->cpu_setup) { + s->cpu_setup(offset, s); } #endif /* CONFIG_PPC64 || CONFIG_BOOKE */ } diff --git a/trunk/arch/powerpc/mm/numa.c b/trunk/arch/powerpc/mm/numa.c index fd4812329570..bf5cb91f07de 100644 --- a/trunk/arch/powerpc/mm/numa.c +++ b/trunk/arch/powerpc/mm/numa.c @@ -186,7 +186,7 @@ static void unmap_cpu_from_node(unsigned long cpu) dbg("removing cpu %lu from node %d\n", cpu, node); if (cpumask_test_cpu(cpu, node_to_cpumask_map[node])) { - cpumask_clear_cpu(cpu, node_to_cpumask_map[node]); + cpumask_set_cpu(cpu, node_to_cpumask_map[node]); } else { printk(KERN_ERR "WARNING: cpu %lu not found in node %d\n", cpu, node); @@ -1289,9 +1289,10 @@ u64 memory_hotplug_max(void) } #endif /* CONFIG_MEMORY_HOTPLUG */ -/* Virtual Processor Home Node (VPHN) support */ +/* Vrtual Processor Home Node (VPHN) support */ #ifdef CONFIG_PPC_SPLPAR -static u8 vphn_cpu_change_counts[NR_CPUS][MAX_DISTANCE_REF_POINTS]; +#define VPHN_NR_CHANGE_CTRS (8) +static u8 vphn_cpu_change_counts[NR_CPUS][VPHN_NR_CHANGE_CTRS]; static cpumask_t cpu_associativity_changes_mask; static int vphn_enabled; static void set_topology_timer(void); @@ -1302,18 +1303,16 @@ static void set_topology_timer(void); */ static void setup_cpu_associativity_change_counters(void) { - int cpu; - - /* The VPHN feature supports a maximum of 8 reference points */ - BUILD_BUG_ON(MAX_DISTANCE_REF_POINTS > 8); + int cpu = 0; for_each_possible_cpu(cpu) { - int i; + int i = 0; u8 *counts = vphn_cpu_change_counts[cpu]; volatile u8 *hypervisor_counts = lppaca[cpu].vphn_assoc_counts; - for (i = 0; i < distance_ref_points_depth; i++) + for (i = 0; i < VPHN_NR_CHANGE_CTRS; i++) { counts[i] = hypervisor_counts[i]; + } } } @@ -1330,7 +1329,7 @@ static void setup_cpu_associativity_change_counters(void) */ static int update_cpu_associativity_changes_mask(void) { - int cpu, nr_cpus = 0; + int cpu = 0, nr_cpus = 0; cpumask_t *changes = &cpu_associativity_changes_mask; cpumask_clear(changes); @@ -1340,8 +1339,8 @@ static int update_cpu_associativity_changes_mask(void) u8 *counts = vphn_cpu_change_counts[cpu]; volatile u8 *hypervisor_counts = lppaca[cpu].vphn_assoc_counts; - for (i = 0; i < distance_ref_points_depth; i++) { - if (hypervisor_counts[i] != counts[i]) { + for (i = 0; i < VPHN_NR_CHANGE_CTRS; i++) { + if (hypervisor_counts[i] > counts[i]) { counts[i] = hypervisor_counts[i]; changed = 1; } @@ -1355,11 +1354,8 @@ static int update_cpu_associativity_changes_mask(void) return nr_cpus; } -/* - * 6 64-bit registers unpacked into 12 32-bit associativity values. To form - * the complete property we have to add the length in the first cell. - */ -#define VPHN_ASSOC_BUFSIZE (6*sizeof(u64)/sizeof(u32) + 1) +/* 6 64-bit registers unpacked into 12 32-bit associativity values */ +#define VPHN_ASSOC_BUFSIZE (6*sizeof(u64)/sizeof(u32)) /* * Convert the associativity domain numbers returned from the hypervisor @@ -1367,14 +1363,15 @@ static int update_cpu_associativity_changes_mask(void) */ static int vphn_unpack_associativity(const long *packed, unsigned int *unpacked) { - int i, nr_assoc_doms = 0; + int i = 0; + int nr_assoc_doms = 0; const u16 *field = (const u16*) packed; #define VPHN_FIELD_UNUSED (0xffff) #define VPHN_FIELD_MSB (0x8000) #define VPHN_FIELD_MASK (~VPHN_FIELD_MSB) - for (i = 1; i < VPHN_ASSOC_BUFSIZE; i++) { + for (i = 0; i < VPHN_ASSOC_BUFSIZE; i++) { if (*field == VPHN_FIELD_UNUSED) { /* All significant fields processed, and remaining * fields contain the reserved value of all 1's. @@ -1382,12 +1379,14 @@ static int vphn_unpack_associativity(const long *packed, unsigned int *unpacked) */ unpacked[i] = *((u32*)field); field += 2; - } else if (*field & VPHN_FIELD_MSB) { + } + else if (*field & VPHN_FIELD_MSB) { /* Data is in the lower 15 bits of this field */ unpacked[i] = *field & VPHN_FIELD_MASK; field++; nr_assoc_doms++; - } else { + } + else { /* Data is in the lower 15 bits of this field * concatenated with the next 16 bit field */ @@ -1397,9 +1396,6 @@ static int vphn_unpack_associativity(const long *packed, unsigned int *unpacked) } } - /* The first cell contains the length of the property */ - unpacked[0] = nr_assoc_doms; - return nr_assoc_doms; } @@ -1409,7 +1405,7 @@ static int vphn_unpack_associativity(const long *packed, unsigned int *unpacked) */ static long hcall_vphn(unsigned long cpu, unsigned int *associativity) { - long rc; + long rc = 0; long retbuf[PLPAR_HCALL9_BUFSIZE] = {0}; u64 flags = 1; int hwcpu = get_hard_smp_processor_id(cpu); @@ -1423,7 +1419,7 @@ static long hcall_vphn(unsigned long cpu, unsigned int *associativity) static long vphn_get_associativity(unsigned long cpu, unsigned int *associativity) { - long rc; + long rc = 0; rc = hcall_vphn(cpu, associativity); @@ -1449,9 +1445,9 @@ static long vphn_get_associativity(unsigned long cpu, */ int arch_update_cpu_topology(void) { - int cpu, nid, old_nid; + int cpu = 0, nid = 0, old_nid = 0; unsigned int associativity[VPHN_ASSOC_BUFSIZE] = {0}; - struct sys_device *sysdev; + struct sys_device *sysdev = NULL; for_each_cpu_mask(cpu, cpu_associativity_changes_mask) { vphn_get_associativity(cpu, associativity); @@ -1516,8 +1512,7 @@ int start_topology_update(void) { int rc = 0; - if (firmware_has_feature(FW_FEATURE_VPHN) && - get_lppaca()->shared_proc) { + if (firmware_has_feature(FW_FEATURE_VPHN)) { vphn_enabled = 1; setup_cpu_associativity_change_counters(); init_timer_deferrable(&topology_timer); diff --git a/trunk/arch/powerpc/platforms/pseries/lpar.c b/trunk/arch/powerpc/platforms/pseries/lpar.c index ca5d5898d320..5d3ea9f60dd7 100644 --- a/trunk/arch/powerpc/platforms/pseries/lpar.c +++ b/trunk/arch/powerpc/platforms/pseries/lpar.c @@ -713,13 +713,6 @@ EXPORT_SYMBOL(arch_free_page); /* NB: reg/unreg are called while guarded with the tracepoints_mutex */ extern long hcall_tracepoint_refcount; -/* - * Since the tracing code might execute hcalls we need to guard against - * recursion. One example of this are spinlocks calling H_YIELD on - * shared processor partitions. - */ -static DEFINE_PER_CPU(unsigned int, hcall_trace_depth); - void hcall_tracepoint_regfunc(void) { hcall_tracepoint_refcount++; @@ -732,42 +725,12 @@ void hcall_tracepoint_unregfunc(void) void __trace_hcall_entry(unsigned long opcode, unsigned long *args) { - unsigned long flags; - unsigned int *depth; - - local_irq_save(flags); - - depth = &__get_cpu_var(hcall_trace_depth); - - if (*depth) - goto out; - - (*depth)++; trace_hcall_entry(opcode, args); - (*depth)--; - -out: - local_irq_restore(flags); } void __trace_hcall_exit(long opcode, unsigned long retval, unsigned long *retbuf) { - unsigned long flags; - unsigned int *depth; - - local_irq_save(flags); - - depth = &__get_cpu_var(hcall_trace_depth); - - if (*depth) - goto out; - - (*depth)++; trace_hcall_exit(opcode, retval, retbuf); - (*depth)--; - -out: - local_irq_restore(flags); } #endif diff --git a/trunk/arch/x86/include/asm/mmu_context.h b/trunk/arch/x86/include/asm/mmu_context.h index 8b5393ec1080..4a2d4e0c18d9 100644 --- a/trunk/arch/x86/include/asm/mmu_context.h +++ b/trunk/arch/x86/include/asm/mmu_context.h @@ -36,6 +36,8 @@ static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next, unsigned cpu = smp_processor_id(); if (likely(prev != next)) { + /* stop flush ipis for the previous mm */ + cpumask_clear_cpu(cpu, mm_cpumask(prev)); #ifdef CONFIG_SMP percpu_write(cpu_tlbstate.state, TLBSTATE_OK); percpu_write(cpu_tlbstate.active_mm, next); @@ -45,9 +47,6 @@ static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next, /* Re-load page tables */ load_cr3(next->pgd); - /* stop flush ipis for the previous mm */ - cpumask_clear_cpu(cpu, mm_cpumask(prev)); - /* * load the LDT, if the LDT is different: */ diff --git a/trunk/arch/x86/include/asm/smp.h b/trunk/arch/x86/include/asm/smp.h index 1f4695136776..4c2f63c7fc1b 100644 --- a/trunk/arch/x86/include/asm/smp.h +++ b/trunk/arch/x86/include/asm/smp.h @@ -40,7 +40,10 @@ DECLARE_EARLY_PER_CPU(u16, x86_cpu_to_apicid); DECLARE_EARLY_PER_CPU(u16, x86_bios_cpu_apicid); /* Static state in head.S used to set up a CPU */ -extern unsigned long stack_start; /* Initial stack pointer address */ +extern struct { + void *sp; + unsigned short ss; +} stack_start; struct smp_ops { void (*smp_prepare_boot_cpu)(void); diff --git a/trunk/arch/x86/kernel/acpi/sleep.c b/trunk/arch/x86/kernel/acpi/sleep.c index 68d1537b8c81..69fd72aa5594 100644 --- a/trunk/arch/x86/kernel/acpi/sleep.c +++ b/trunk/arch/x86/kernel/acpi/sleep.c @@ -12,8 +12,10 @@ #include #include #include + +#ifdef CONFIG_X86_32 #include -#include +#endif #include "realmode/wakeup.h" #include "sleep.h" @@ -98,7 +100,7 @@ int acpi_save_state_mem(void) #else /* CONFIG_64BIT */ header->trampoline_segment = setup_trampoline() >> 4; #ifdef CONFIG_SMP - stack_start = (unsigned long)temp_stack + sizeof(temp_stack); + stack_start.sp = temp_stack + sizeof(temp_stack); early_gdt_descr.address = (unsigned long)get_cpu_gdt_table(smp_processor_id()); initial_gs = per_cpu_offset(smp_processor_id()); @@ -147,15 +149,6 @@ void __init acpi_reserve_wakeup_memory(void) memblock_x86_reserve_range(mem, mem + WAKEUP_SIZE, "ACPI WAKEUP"); } -int __init acpi_configure_wakeup_memory(void) -{ - if (acpi_realmode) - set_memory_x(acpi_realmode, WAKEUP_SIZE >> PAGE_SHIFT); - - return 0; -} -arch_initcall(acpi_configure_wakeup_memory); - static int __init acpi_sleep_setup(char *str) { diff --git a/trunk/arch/x86/kernel/cpu/mtrr/main.c b/trunk/arch/x86/kernel/cpu/mtrr/main.c index bebabec5b448..01c0f3ee6cc3 100644 --- a/trunk/arch/x86/kernel/cpu/mtrr/main.c +++ b/trunk/arch/x86/kernel/cpu/mtrr/main.c @@ -793,21 +793,13 @@ void set_mtrr_aps_delayed_init(void) } /* - * Delayed MTRR initialization for all AP's + * MTRR initialization for all AP's */ void mtrr_aps_init(void) { if (!use_intel()) return; - /* - * Check if someone has requested the delay of AP MTRR initialization, - * by doing set_mtrr_aps_delayed_init(), prior to this point. If not, - * then we are done. - */ - if (!mtrr_aps_delayed_init) - return; - set_mtrr(~0U, 0, 0, 0); mtrr_aps_delayed_init = false; } diff --git a/trunk/arch/x86/kernel/cpu/perf_event.c b/trunk/arch/x86/kernel/cpu/perf_event.c index 4d98789b0664..9d977a2ea693 100644 --- a/trunk/arch/x86/kernel/cpu/perf_event.c +++ b/trunk/arch/x86/kernel/cpu/perf_event.c @@ -1389,7 +1389,7 @@ static void __init pmu_check_apic(void) pr_info("no hardware sampling interrupt available.\n"); } -static int __init init_hw_perf_events(void) +int __init init_hw_perf_events(void) { struct event_constraint *c; int err; @@ -1608,7 +1608,7 @@ static int validate_group(struct perf_event *event) return ret; } -static int x86_pmu_event_init(struct perf_event *event) +int x86_pmu_event_init(struct perf_event *event) { struct pmu *tmp; int err; diff --git a/trunk/arch/x86/kernel/head_32.S b/trunk/arch/x86/kernel/head_32.S index 767d6c43de37..fc293dc8dc35 100644 --- a/trunk/arch/x86/kernel/head_32.S +++ b/trunk/arch/x86/kernel/head_32.S @@ -85,8 +85,6 @@ RESERVE_BRK(pagetables, INIT_MAP_SIZE) */ __HEAD ENTRY(startup_32) - movl pa(stack_start),%ecx - /* test KEEP_SEGMENTS flag to see if the bootloader is asking us to not reload segments */ testb $(1<<6), BP_loadflags(%esi) @@ -101,9 +99,7 @@ ENTRY(startup_32) movl %eax,%es movl %eax,%fs movl %eax,%gs - movl %eax,%ss 2: - leal -__PAGE_OFFSET(%ecx),%esp /* * Clear BSS first so that there are no surprises... @@ -149,6 +145,8 @@ ENTRY(startup_32) * _brk_end is set up to point to the first "safe" location. * Mappings are created both at virtual address 0 (identity mapping) * and PAGE_OFFSET for up to _end. + * + * Note that the stack is not yet set up! */ #ifdef CONFIG_X86_PAE @@ -284,9 +282,6 @@ ENTRY(startup_32_smp) movl %eax,%es movl %eax,%fs movl %eax,%gs - movl pa(stack_start),%ecx - movl %eax,%ss - leal -__PAGE_OFFSET(%ecx),%esp #endif /* CONFIG_SMP */ default_entry: @@ -352,8 +347,8 @@ default_entry: movl %eax,%cr0 /* ..and set paging (PG) bit */ ljmp $__BOOT_CS,$1f /* Clear prefetch and normalize %eip */ 1: - /* Shift the stack pointer to a virtual address */ - addl $__PAGE_OFFSET, %esp + /* Set up the stack pointer */ + lss stack_start,%esp /* * Initialize eflags. Some BIOS's leave bits like NT set. This would @@ -365,7 +360,9 @@ default_entry: #ifdef CONFIG_SMP cmpb $0, ready - jnz checkCPUtype + jz 1f /* Initial CPU cleans BSS */ + jmp checkCPUtype +1: #endif /* CONFIG_SMP */ /* @@ -473,7 +470,14 @@ is386: movl $2,%ecx # set MP cld # gcc2 wants the direction flag cleared at all times pushl $0 # fake return address for unwinder +#ifdef CONFIG_SMP + movb ready, %cl movb $1, ready + cmpb $0,%cl # the first CPU calls start_kernel + je 1f + movl (stack_start), %esp +1: +#endif /* CONFIG_SMP */ jmp *(initial_code) /* @@ -666,15 +670,15 @@ ENTRY(initial_page_table) #endif .data -.balign 4 ENTRY(stack_start) .long init_thread_union+THREAD_SIZE + .long __BOOT_DS + +ready: .byte 0 early_recursion_flag: .long 0 -ready: .byte 0 - int_msg: .asciz "Unknown interrupt or fault at: %p %p %p\n" diff --git a/trunk/arch/x86/kernel/smpboot.c b/trunk/arch/x86/kernel/smpboot.c index 03273b6c272c..0cbe8c0b35ed 100644 --- a/trunk/arch/x86/kernel/smpboot.c +++ b/trunk/arch/x86/kernel/smpboot.c @@ -638,7 +638,7 @@ wakeup_secondary_cpu_via_init(int phys_apicid, unsigned long start_eip) * target processor state. */ startup_ipi_hook(phys_apicid, (unsigned long) start_secondary, - stack_start); + (unsigned long)stack_start.sp); /* * Run STARTUP IPI loop. @@ -785,7 +785,7 @@ static int __cpuinit do_boot_cpu(int apicid, int cpu) #endif early_gdt_descr.address = (unsigned long)get_cpu_gdt_table(cpu); initial_code = (unsigned long)start_secondary; - stack_start = c_idle.idle->thread.sp; + stack_start.sp = (void *) c_idle.idle->thread.sp; /* start_ip had better be page-aligned! */ start_ip = setup_trampoline(); diff --git a/trunk/arch/x86/mm/pageattr.c b/trunk/arch/x86/mm/pageattr.c index d343b3c81f3c..8b830ca14ac4 100644 --- a/trunk/arch/x86/mm/pageattr.c +++ b/trunk/arch/x86/mm/pageattr.c @@ -256,6 +256,7 @@ static inline pgprot_t static_protections(pgprot_t prot, unsigned long address, unsigned long pfn) { pgprot_t forbidden = __pgprot(0); + pgprot_t required = __pgprot(0); /* * The BIOS area between 640k and 1Mb needs to be executable for @@ -281,6 +282,12 @@ static inline pgprot_t static_protections(pgprot_t prot, unsigned long address, if (within(pfn, __pa((unsigned long)__start_rodata) >> PAGE_SHIFT, __pa((unsigned long)__end_rodata) >> PAGE_SHIFT)) pgprot_val(forbidden) |= _PAGE_RW; + /* + * .data and .bss should always be writable. + */ + if (within(address, (unsigned long)_sdata, (unsigned long)_edata) || + within(address, (unsigned long)__bss_start, (unsigned long)__bss_stop)) + pgprot_val(required) |= _PAGE_RW; #if defined(CONFIG_X86_64) && defined(CONFIG_DEBUG_RODATA) /* @@ -320,6 +327,7 @@ static inline pgprot_t static_protections(pgprot_t prot, unsigned long address, #endif prot = __pgprot(pgprot_val(prot) & ~pgprot_val(forbidden)); + prot = __pgprot(pgprot_val(prot) | pgprot_val(required)); return prot; } diff --git a/trunk/drivers/char/agp/Kconfig b/trunk/drivers/char/agp/Kconfig index d8b1b576556c..fcd867d923ba 100644 --- a/trunk/drivers/char/agp/Kconfig +++ b/trunk/drivers/char/agp/Kconfig @@ -50,7 +50,7 @@ config AGP_ATI config AGP_AMD tristate "AMD Irongate, 761, and 762 chipset support" - depends on AGP && X86_32 + depends on AGP && (X86_32 || ALPHA) help This option gives you AGP support for the GLX component of X on AMD Irongate, 761, and 762 chipsets. diff --git a/trunk/drivers/char/agp/amd-k7-agp.c b/trunk/drivers/char/agp/amd-k7-agp.c index 45681c0ff3b6..b1b4362bc648 100644 --- a/trunk/drivers/char/agp/amd-k7-agp.c +++ b/trunk/drivers/char/agp/amd-k7-agp.c @@ -41,8 +41,22 @@ static int amd_create_page_map(struct amd_page_map *page_map) if (page_map->real == NULL) return -ENOMEM; +#ifndef CONFIG_X86 + SetPageReserved(virt_to_page(page_map->real)); + global_cache_flush(); + page_map->remapped = ioremap_nocache(virt_to_phys(page_map->real), + PAGE_SIZE); + if (page_map->remapped == NULL) { + ClearPageReserved(virt_to_page(page_map->real)); + free_page((unsigned long) page_map->real); + page_map->real = NULL; + return -ENOMEM; + } + global_cache_flush(); +#else set_memory_uc((unsigned long)page_map->real, 1); page_map->remapped = page_map->real; +#endif for (i = 0; i < PAGE_SIZE / sizeof(unsigned long); i++) { writel(agp_bridge->scratch_page, page_map->remapped+i); @@ -54,7 +68,12 @@ static int amd_create_page_map(struct amd_page_map *page_map) static void amd_free_page_map(struct amd_page_map *page_map) { +#ifndef CONFIG_X86 + iounmap(page_map->remapped); + ClearPageReserved(virt_to_page(page_map->real)); +#else set_memory_wb((unsigned long)page_map->real, 1); +#endif free_page((unsigned long) page_map->real); } diff --git a/trunk/drivers/char/agp/intel-agp.c b/trunk/drivers/char/agp/intel-agp.c index b0a0dccc98c1..857df10c0428 100644 --- a/trunk/drivers/char/agp/intel-agp.c +++ b/trunk/drivers/char/agp/intel-agp.c @@ -773,15 +773,21 @@ static int __devinit agp_intel_probe(struct pci_dev *pdev, dev_info(&pdev->dev, "Intel %s Chipset\n", intel_agp_chipsets[i].name); + /* + * If the device has not been properly setup, the following will catch + * the problem and should stop the system from crashing. + * 20030610 - hamish@zot.org + */ + if (pci_enable_device(pdev)) { + dev_err(&pdev->dev, "can't enable PCI device\n"); + agp_put_bridge(bridge); + return -ENODEV; + } + /* * The following fixes the case where the BIOS has "forgotten" to * provide an address range for the GART. * 20030610 - hamish@zot.org - * This happens before pci_enable_device() intentionally; - * calling pci_enable_device() before assigning the resource - * will result in the GART being disabled on machines with such - * BIOSs (the GART ends up with a BAR starting at 0, which - * conflicts a lot of other devices). */ r = &pdev->resource[0]; if (!r->start && r->end) { @@ -792,17 +798,6 @@ static int __devinit agp_intel_probe(struct pci_dev *pdev, } } - /* - * If the device has not been properly setup, the following will catch - * the problem and should stop the system from crashing. - * 20030610 - hamish@zot.org - */ - if (pci_enable_device(pdev)) { - dev_err(&pdev->dev, "can't enable PCI device\n"); - agp_put_bridge(bridge); - return -ENODEV; - } - /* Fill in the mode register */ if (cap_ptr) { pci_read_config_dword(pdev, diff --git a/trunk/drivers/gpu/drm/drm_crtc.c b/trunk/drivers/gpu/drm/drm_crtc.c index 654faa803dcb..2baa6708e44c 100644 --- a/trunk/drivers/gpu/drm/drm_crtc.c +++ b/trunk/drivers/gpu/drm/drm_crtc.c @@ -2674,23 +2674,3 @@ int drm_mode_page_flip_ioctl(struct drm_device *dev, mutex_unlock(&dev->mode_config.mutex); return ret; } - -void drm_mode_config_reset(struct drm_device *dev) -{ - struct drm_crtc *crtc; - struct drm_encoder *encoder; - struct drm_connector *connector; - - list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) - if (crtc->funcs->reset) - crtc->funcs->reset(crtc); - - list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) - if (encoder->funcs->reset) - encoder->funcs->reset(encoder); - - list_for_each_entry(connector, &dev->mode_config.connector_list, head) - if (connector->funcs->reset) - connector->funcs->reset(connector); -} -EXPORT_SYMBOL(drm_mode_config_reset); diff --git a/trunk/drivers/gpu/drm/drm_crtc_helper.c b/trunk/drivers/gpu/drm/drm_crtc_helper.c index 92369655dca3..952b3d4fb2a6 100644 --- a/trunk/drivers/gpu/drm/drm_crtc_helper.c +++ b/trunk/drivers/gpu/drm/drm_crtc_helper.c @@ -343,12 +343,13 @@ bool drm_crtc_helper_set_mode(struct drm_crtc *crtc, struct drm_encoder *encoder; bool ret = true; + adjusted_mode = drm_mode_duplicate(dev, mode); + crtc->enabled = drm_helper_crtc_in_use(crtc); + if (!crtc->enabled) return true; - adjusted_mode = drm_mode_duplicate(dev, mode); - saved_hwmode = crtc->hwmode; saved_mode = crtc->mode; saved_x = crtc->x; @@ -436,9 +437,10 @@ bool drm_crtc_helper_set_mode(struct drm_crtc *crtc, */ drm_calc_timestamping_constants(crtc); + /* XXX free adjustedmode */ + drm_mode_destroy(dev, adjusted_mode); /* FIXME: add subpixel order */ done: - drm_mode_destroy(dev, adjusted_mode); if (!ret) { crtc->hwmode = saved_hwmode; crtc->mode = saved_mode; @@ -495,17 +497,14 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set) crtc_funcs = set->crtc->helper_private; - if (!set->mode) - set->fb = NULL; - if (set->fb) { DRM_DEBUG_KMS("[CRTC:%d] [FB:%d] #connectors=%d (x y) (%i %i)\n", set->crtc->base.id, set->fb->base.id, (int)set->num_connectors, set->x, set->y); } else { - DRM_DEBUG_KMS("[CRTC:%d] [NOFB]\n", set->crtc->base.id); - set->mode = NULL; - set->num_connectors = 0; + DRM_DEBUG_KMS("[CRTC:%d] [NOFB] #connectors=%d (x y) (%i %i)\n", + set->crtc->base.id, (int)set->num_connectors, + set->x, set->y); } dev = set->crtc->dev; @@ -650,8 +649,8 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set) mode_changed = true; if (mode_changed) { - set->crtc->enabled = drm_helper_crtc_in_use(set->crtc); - if (set->crtc->enabled) { + set->crtc->enabled = (set->mode != NULL); + if (set->mode != NULL) { DRM_DEBUG_KMS("attempting to set mode from" " userspace\n"); drm_mode_debug_printmodeline(set->mode); @@ -666,12 +665,6 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set) ret = -EINVAL; goto fail; } - DRM_DEBUG_KMS("Setting connector DPMS state to on\n"); - for (i = 0; i < set->num_connectors; i++) { - DRM_DEBUG_KMS("\t[CONNECTOR:%d:%s] set DPMS on\n", set->connectors[i]->base.id, - drm_get_connector_name(set->connectors[i])); - set->connectors[i]->dpms = DRM_MODE_DPMS_ON; - } } drm_helper_disable_unused_functions(dev); } else if (fb_changed) { @@ -688,6 +681,12 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set) goto fail; } } + DRM_DEBUG_KMS("Setting connector DPMS state to on\n"); + for (i = 0; i < set->num_connectors; i++) { + DRM_DEBUG_KMS("\t[CONNECTOR:%d:%s] set DPMS on\n", set->connectors[i]->base.id, + drm_get_connector_name(set->connectors[i])); + set->connectors[i]->dpms = DRM_MODE_DPMS_ON; + } kfree(save_connectors); kfree(save_encoders); diff --git a/trunk/drivers/gpu/drm/drm_irq.c b/trunk/drivers/gpu/drm/drm_irq.c index 3dadfa2a8528..0054e957203f 100644 --- a/trunk/drivers/gpu/drm/drm_irq.c +++ b/trunk/drivers/gpu/drm/drm_irq.c @@ -1250,7 +1250,7 @@ void drm_handle_vblank_events(struct drm_device *dev, int crtc) * Drivers should call this routine in their vblank interrupt handlers to * update the vblank counter and send any signals that may be pending. */ -bool drm_handle_vblank(struct drm_device *dev, int crtc) +void drm_handle_vblank(struct drm_device *dev, int crtc) { u32 vblcount; s64 diff_ns; @@ -1258,7 +1258,7 @@ bool drm_handle_vblank(struct drm_device *dev, int crtc) unsigned long irqflags; if (!dev->num_crtcs) - return false; + return; /* Need timestamp lock to prevent concurrent execution with * vblank enable/disable, as this would cause inconsistent @@ -1269,7 +1269,7 @@ bool drm_handle_vblank(struct drm_device *dev, int crtc) /* Vblank irq handling disabled. Nothing to do. */ if (!dev->vblank_enabled[crtc]) { spin_unlock_irqrestore(&dev->vblank_time_lock, irqflags); - return false; + return; } /* Fetch corresponding timestamp for this vblank interval from @@ -1311,6 +1311,5 @@ bool drm_handle_vblank(struct drm_device *dev, int crtc) drm_handle_vblank_events(dev, crtc); spin_unlock_irqrestore(&dev->vblank_time_lock, irqflags); - return true; } EXPORT_SYMBOL(drm_handle_vblank); diff --git a/trunk/drivers/gpu/drm/i915/i915_drv.c b/trunk/drivers/gpu/drm/i915/i915_drv.c index cfb56d0ff367..66796bb82d3e 100644 --- a/trunk/drivers/gpu/drm/i915/i915_drv.c +++ b/trunk/drivers/gpu/drm/i915/i915_drv.c @@ -354,7 +354,6 @@ static int i915_drm_thaw(struct drm_device *dev) error = i915_gem_init_ringbuffer(dev); mutex_unlock(&dev->struct_mutex); - drm_mode_config_reset(dev); drm_irq_install(dev); /* Resume the modeset for every activated CRTC */ @@ -543,7 +542,6 @@ int i915_reset(struct drm_device *dev, u8 flags) mutex_unlock(&dev->struct_mutex); drm_irq_uninstall(dev); - drm_mode_config_reset(dev); drm_irq_install(dev); mutex_lock(&dev->struct_mutex); } @@ -568,14 +566,6 @@ int i915_reset(struct drm_device *dev, u8 flags) static int __devinit i915_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) { - /* Only bind to function 0 of the device. Early generations - * used function 1 as a placeholder for multi-head. This causes - * us confusion instead, especially on the systems where both - * functions have the same PCI-ID! - */ - if (PCI_FUNC(pdev->devfn)) - return -ENODEV; - return drm_get_pci_dev(pdev, ent, &driver); } diff --git a/trunk/drivers/gpu/drm/i915/i915_irq.c b/trunk/drivers/gpu/drm/i915/i915_irq.c index 97f946dcc1aa..062f353497e6 100644 --- a/trunk/drivers/gpu/drm/i915/i915_irq.c +++ b/trunk/drivers/gpu/drm/i915/i915_irq.c @@ -1196,18 +1196,18 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS) intel_finish_page_flip_plane(dev, 1); } - if (pipea_stats & vblank_status && - drm_handle_vblank(dev, 0)) { + if (pipea_stats & vblank_status) { vblank++; + drm_handle_vblank(dev, 0); if (!dev_priv->flip_pending_is_done) { i915_pageflip_stall_check(dev, 0); intel_finish_page_flip(dev, 0); } } - if (pipeb_stats & vblank_status && - drm_handle_vblank(dev, 1)) { + if (pipeb_stats & vblank_status) { vblank++; + drm_handle_vblank(dev, 1); if (!dev_priv->flip_pending_is_done) { i915_pageflip_stall_check(dev, 1); intel_finish_page_flip(dev, 1); diff --git a/trunk/drivers/gpu/drm/i915/intel_crt.c b/trunk/drivers/gpu/drm/i915/intel_crt.c index 8a77ff4a7237..17035b87ee46 100644 --- a/trunk/drivers/gpu/drm/i915/intel_crt.c +++ b/trunk/drivers/gpu/drm/i915/intel_crt.c @@ -535,15 +535,6 @@ static int intel_crt_set_property(struct drm_connector *connector, return 0; } -static void intel_crt_reset(struct drm_connector *connector) -{ - struct drm_device *dev = connector->dev; - struct intel_crt *crt = intel_attached_crt(connector); - - if (HAS_PCH_SPLIT(dev)) - crt->force_hotplug_required = 1; -} - /* * Routines for controlling stuff on the analog port */ @@ -557,7 +548,6 @@ static const struct drm_encoder_helper_funcs intel_crt_helper_funcs = { }; static const struct drm_connector_funcs intel_crt_connector_funcs = { - .reset = intel_crt_reset, .dpms = drm_helper_connector_dpms, .detect = intel_crt_detect, .fill_modes = drm_helper_probe_single_connector_modes, diff --git a/trunk/drivers/gpu/drm/i915/intel_display.c b/trunk/drivers/gpu/drm/i915/intel_display.c index 7e42aa586504..d7f237deaaf0 100644 --- a/trunk/drivers/gpu/drm/i915/intel_display.c +++ b/trunk/drivers/gpu/drm/i915/intel_display.c @@ -5551,18 +5551,6 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc, return ret; } -static void intel_crtc_reset(struct drm_crtc *crtc) -{ - struct intel_crtc *intel_crtc = to_intel_crtc(crtc); - - /* Reset flags back to the 'unknown' status so that they - * will be correctly set on the initial modeset. - */ - intel_crtc->cursor_addr = 0; - intel_crtc->dpms_mode = -1; - intel_crtc->active = true; /* force the pipe off on setup_init_config */ -} - static struct drm_crtc_helper_funcs intel_helper_funcs = { .dpms = intel_crtc_dpms, .mode_fixup = intel_crtc_mode_fixup, @@ -5574,7 +5562,6 @@ static struct drm_crtc_helper_funcs intel_helper_funcs = { }; static const struct drm_crtc_funcs intel_crtc_funcs = { - .reset = intel_crtc_reset, .cursor_set = intel_crtc_cursor_set, .cursor_move = intel_crtc_cursor_move, .gamma_set = intel_crtc_gamma_set, @@ -5665,7 +5652,9 @@ static void intel_crtc_init(struct drm_device *dev, int pipe) dev_priv->plane_to_crtc_mapping[intel_crtc->plane] = &intel_crtc->base; dev_priv->pipe_to_crtc_mapping[intel_crtc->pipe] = &intel_crtc->base; - intel_crtc_reset(&intel_crtc->base); + intel_crtc->cursor_addr = 0; + intel_crtc->dpms_mode = -1; + intel_crtc->active = true; /* force the pipe off on setup_init_config */ if (HAS_PCH_SPLIT(dev)) { intel_helper_funcs.prepare = ironlake_crtc_prepare; diff --git a/trunk/drivers/gpu/drm/i915/intel_sdvo.c b/trunk/drivers/gpu/drm/i915/intel_sdvo.c index 6a09c1413d60..45cd37652a37 100644 --- a/trunk/drivers/gpu/drm/i915/intel_sdvo.c +++ b/trunk/drivers/gpu/drm/i915/intel_sdvo.c @@ -473,6 +473,20 @@ static bool intel_sdvo_write_cmd(struct intel_sdvo *intel_sdvo, u8 cmd, return false; } + i = 3; + while (status == SDVO_CMD_STATUS_PENDING && i--) { + if (!intel_sdvo_read_byte(intel_sdvo, + SDVO_I2C_CMD_STATUS, + &status)) + return false; + } + if (status != SDVO_CMD_STATUS_SUCCESS) { + DRM_DEBUG_KMS("command returns response %s [%d]\n", + status <= SDVO_CMD_STATUS_SCALING_NOT_SUPP ? cmd_status_names[status] : "???", + status); + return false; + } + return true; } @@ -483,8 +497,6 @@ static bool intel_sdvo_read_response(struct intel_sdvo *intel_sdvo, u8 status; int i; - DRM_DEBUG_KMS("%s: R: ", SDVO_NAME(intel_sdvo)); - /* * The documentation states that all commands will be * processed within 15µs, and that we need only poll @@ -493,19 +505,14 @@ static bool intel_sdvo_read_response(struct intel_sdvo *intel_sdvo, * * Check 5 times in case the hardware failed to read the docs. */ - if (!intel_sdvo_read_byte(intel_sdvo, - SDVO_I2C_CMD_STATUS, - &status)) - goto log_fail; - - while (status == SDVO_CMD_STATUS_PENDING && retry--) { - udelay(15); + do { if (!intel_sdvo_read_byte(intel_sdvo, SDVO_I2C_CMD_STATUS, &status)) - goto log_fail; - } + return false; + } while (status == SDVO_CMD_STATUS_PENDING && --retry); + DRM_DEBUG_KMS("%s: R: ", SDVO_NAME(intel_sdvo)); if (status <= SDVO_CMD_STATUS_SCALING_NOT_SUPP) DRM_LOG_KMS("(%s)", cmd_status_names[status]); else @@ -526,7 +533,7 @@ static bool intel_sdvo_read_response(struct intel_sdvo *intel_sdvo, return true; log_fail: - DRM_LOG_KMS("... failed\n"); + DRM_LOG_KMS("\n"); return false; } @@ -543,7 +550,6 @@ static int intel_sdvo_get_pixel_multiplier(struct drm_display_mode *mode) static bool intel_sdvo_set_control_bus_switch(struct intel_sdvo *intel_sdvo, u8 ddc_bus) { - /* This must be the immediately preceding write before the i2c xfer */ return intel_sdvo_write_cmd(intel_sdvo, SDVO_CMD_SET_CONTROL_BUS_SWITCH, &ddc_bus, 1); @@ -551,10 +557,7 @@ static bool intel_sdvo_set_control_bus_switch(struct intel_sdvo *intel_sdvo, static bool intel_sdvo_set_value(struct intel_sdvo *intel_sdvo, u8 cmd, const void *data, int len) { - if (!intel_sdvo_write_cmd(intel_sdvo, cmd, data, len)) - return false; - - return intel_sdvo_read_response(intel_sdvo, NULL, 0); + return intel_sdvo_write_cmd(intel_sdvo, cmd, data, len); } static bool @@ -856,21 +859,18 @@ static bool intel_sdvo_set_avi_infoframe(struct intel_sdvo *intel_sdvo) intel_dip_infoframe_csum(&avi_if); - if (!intel_sdvo_set_value(intel_sdvo, - SDVO_CMD_SET_HBUF_INDEX, + if (!intel_sdvo_write_cmd(intel_sdvo, SDVO_CMD_SET_HBUF_INDEX, set_buf_index, 2)) return false; for (i = 0; i < sizeof(avi_if); i += 8) { - if (!intel_sdvo_set_value(intel_sdvo, - SDVO_CMD_SET_HBUF_DATA, + if (!intel_sdvo_write_cmd(intel_sdvo, SDVO_CMD_SET_HBUF_DATA, data, 8)) return false; data++; } - return intel_sdvo_set_value(intel_sdvo, - SDVO_CMD_SET_HBUF_TXRATE, + return intel_sdvo_write_cmd(intel_sdvo, SDVO_CMD_SET_HBUF_TXRATE, &tx_rate, 1); } diff --git a/trunk/drivers/gpu/drm/nouveau/nouveau_pm.c b/trunk/drivers/gpu/drm/nouveau/nouveau_pm.c index f05c0cddfeca..fb846a3fef15 100644 --- a/trunk/drivers/gpu/drm/nouveau/nouveau_pm.c +++ b/trunk/drivers/gpu/drm/nouveau/nouveau_pm.c @@ -443,7 +443,7 @@ nouveau_hwmon_fini(struct drm_device *dev) struct nouveau_pm_engine *pm = &dev_priv->engine.pm; if (pm->hwmon) { - sysfs_remove_group(&dev->pdev->dev.kobj, &hwmon_attrgroup); + sysfs_remove_group(&pm->hwmon->kobj, &hwmon_attrgroup); hwmon_device_unregister(pm->hwmon); } #endif diff --git a/trunk/drivers/gpu/drm/nouveau/nv50_evo.c b/trunk/drivers/gpu/drm/nouveau/nv50_evo.c index 0ea090f4244a..14e24e906ee8 100644 --- a/trunk/drivers/gpu/drm/nouveau/nv50_evo.c +++ b/trunk/drivers/gpu/drm/nouveau/nv50_evo.c @@ -283,7 +283,8 @@ nv50_evo_create(struct drm_device *dev) nv50_evo_channel_del(&dev_priv->evo); return ret; } - } else { + } else + if (dev_priv->chipset != 0x50) { ret = nv50_evo_dmaobj_new(evo, 0x3d, NvEvoFB16, 0x70, 0x19, 0, 0xffffffff, 0x00010000); if (ret) { diff --git a/trunk/drivers/gpu/drm/radeon/atombios_crtc.c b/trunk/drivers/gpu/drm/radeon/atombios_crtc.c index b1537000a104..842954fe74c5 100644 --- a/trunk/drivers/gpu/drm/radeon/atombios_crtc.c +++ b/trunk/drivers/gpu/drm/radeon/atombios_crtc.c @@ -555,7 +555,6 @@ static u32 atombios_adjust_pll(struct drm_crtc *crtc, dp_clock = dig_connector->dp_clock; } } -/* this might work properly with the new pll algo */ #if 0 /* doesn't work properly on some laptops */ /* use recommended ref_div for ss */ if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) { @@ -573,11 +572,6 @@ static u32 atombios_adjust_pll(struct drm_crtc *crtc, adjusted_clock = mode->clock * 2; if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT)) pll->flags |= RADEON_PLL_PREFER_CLOSEST_LOWER; - /* rv515 needs more testing with this option */ - if (rdev->family != CHIP_RV515) { - if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) - pll->flags |= RADEON_PLL_IS_LCD; - } } else { if (encoder->encoder_type != DRM_MODE_ENCODER_DAC) pll->flags |= RADEON_PLL_NO_ODD_POST_DIV; @@ -957,16 +951,8 @@ static void atombios_crtc_set_pll(struct drm_crtc *crtc, struct drm_display_mode /* adjust pixel clock as needed */ adjusted_clock = atombios_adjust_pll(crtc, mode, pll, ss_enabled, &ss); - /* rv515 seems happier with the old algo */ - if (rdev->family == CHIP_RV515) - radeon_compute_pll_legacy(pll, adjusted_clock, &pll_clock, &fb_div, &frac_fb_div, - &ref_div, &post_div); - else if (ASIC_IS_AVIVO(rdev)) - radeon_compute_pll_avivo(pll, adjusted_clock, &pll_clock, &fb_div, &frac_fb_div, - &ref_div, &post_div); - else - radeon_compute_pll_legacy(pll, adjusted_clock, &pll_clock, &fb_div, &frac_fb_div, - &ref_div, &post_div); + radeon_compute_pll(pll, adjusted_clock, &pll_clock, &fb_div, &frac_fb_div, + &ref_div, &post_div); atombios_crtc_program_ss(crtc, ATOM_DISABLE, radeon_crtc->pll_id, &ss); diff --git a/trunk/drivers/gpu/drm/radeon/evergreen.c b/trunk/drivers/gpu/drm/radeon/evergreen.c index ffdc8332b76e..677af91b555c 100644 --- a/trunk/drivers/gpu/drm/radeon/evergreen.c +++ b/trunk/drivers/gpu/drm/radeon/evergreen.c @@ -97,29 +97,26 @@ u32 evergreen_page_flip(struct radeon_device *rdev, int crtc_id, u64 crtc_base) } /* get temperature in millidegrees */ -int evergreen_get_temp(struct radeon_device *rdev) +u32 evergreen_get_temp(struct radeon_device *rdev) { u32 temp = (RREG32(CG_MULT_THERMAL_STATUS) & ASIC_T_MASK) >> ASIC_T_SHIFT; u32 actual_temp = 0; - if (temp & 0x400) - actual_temp = -256; - else if (temp & 0x200) + if ((temp >> 10) & 1) + actual_temp = 0; + else if ((temp >> 9) & 1) actual_temp = 255; - else if (temp & 0x100) { - actual_temp = temp & 0x1ff; - actual_temp |= ~0x1ff; - } else - actual_temp = temp & 0xff; + else + actual_temp = (temp >> 1) & 0xff; - return (actual_temp * 1000) / 2; + return actual_temp * 1000; } -int sumo_get_temp(struct radeon_device *rdev) +u32 sumo_get_temp(struct radeon_device *rdev) { u32 temp = RREG32(CG_THERMAL_STATUS) & 0xff; - int actual_temp = temp - 49; + u32 actual_temp = (temp >> 1) & 0xff; return actual_temp * 1000; } @@ -1185,18 +1182,6 @@ static void evergreen_mc_program(struct radeon_device *rdev) /* * CP. */ -void evergreen_ring_ib_execute(struct radeon_device *rdev, struct radeon_ib *ib) -{ - /* set to DX10/11 mode */ - radeon_ring_write(rdev, PACKET3(PACKET3_MODE_CONTROL, 0)); - radeon_ring_write(rdev, 1); - /* FIXME: implement */ - radeon_ring_write(rdev, PACKET3(PACKET3_INDIRECT_BUFFER, 2)); - radeon_ring_write(rdev, ib->gpu_addr & 0xFFFFFFFC); - radeon_ring_write(rdev, upper_32_bits(ib->gpu_addr) & 0xFF); - radeon_ring_write(rdev, ib->length_dw); -} - static int evergreen_cp_load_microcode(struct radeon_device *rdev) { @@ -1248,7 +1233,7 @@ static int evergreen_cp_start(struct radeon_device *rdev) cp_me = 0xff; WREG32(CP_ME_CNTL, cp_me); - r = radeon_ring_lock(rdev, evergreen_default_size + 19); + r = radeon_ring_lock(rdev, evergreen_default_size + 15); if (r) { DRM_ERROR("radeon: cp failed to lock ring (%d).\n", r); return r; @@ -1281,11 +1266,6 @@ static int evergreen_cp_start(struct radeon_device *rdev) radeon_ring_write(rdev, 0xffffffff); radeon_ring_write(rdev, 0xffffffff); - radeon_ring_write(rdev, 0xc0026900); - radeon_ring_write(rdev, 0x00000316); - radeon_ring_write(rdev, 0x0000000e); /* VGT_VERTEX_REUSE_BLOCK_CNTL */ - radeon_ring_write(rdev, 0x00000010); /* */ - radeon_ring_unlock_commit(rdev); return 0; @@ -2092,7 +2072,6 @@ static void evergreen_gpu_init(struct radeon_device *rdev) WREG32(VGT_CACHE_INVALIDATION, vgt_cache_invalidation); WREG32(VGT_GS_VERTEX_REUSE, 16); - WREG32(PA_SU_LINE_STIPPLE_VALUE, 0); WREG32(PA_SC_LINE_STIPPLE_STATE, 0); WREG32(VGT_VERTEX_REUSE_BLOCK_CNTL, 14); diff --git a/trunk/drivers/gpu/drm/radeon/evergreen_blit_kms.c b/trunk/drivers/gpu/drm/radeon/evergreen_blit_kms.c index a1ba4b3053d0..d4d4db49a8b8 100644 --- a/trunk/drivers/gpu/drm/radeon/evergreen_blit_kms.c +++ b/trunk/drivers/gpu/drm/radeon/evergreen_blit_kms.c @@ -232,7 +232,7 @@ draw_auto(struct radeon_device *rdev) } -/* emits 36 */ +/* emits 34 */ static void set_default_state(struct radeon_device *rdev) { @@ -499,10 +499,6 @@ set_default_state(struct radeon_device *rdev) radeon_ring_write(rdev, 0x00000000); radeon_ring_write(rdev, 0x00000000); - /* set to DX10/11 mode */ - radeon_ring_write(rdev, PACKET3(PACKET3_MODE_CONTROL, 0)); - radeon_ring_write(rdev, 1); - /* emit an IB pointing at default state */ dwords = ALIGN(rdev->r600_blit.state_len, 0x10); gpu_addr = rdev->r600_blit.shader_gpu_addr + rdev->r600_blit.state_offset; @@ -683,7 +679,7 @@ int evergreen_blit_prepare_copy(struct radeon_device *rdev, int size_bytes) /* calculate number of loops correctly */ ring_size = num_loops * dwords_per_loop; /* set default + shaders */ - ring_size += 52; /* shaders + def state */ + ring_size += 50; /* shaders + def state */ ring_size += 10; /* fence emit for VB IB */ ring_size += 5; /* done copy */ ring_size += 10; /* fence emit for done copy */ @@ -691,7 +687,7 @@ int evergreen_blit_prepare_copy(struct radeon_device *rdev, int size_bytes) if (r) return r; - set_default_state(rdev); /* 36 */ + set_default_state(rdev); /* 34 */ set_shaders(rdev); /* 16 */ return 0; } diff --git a/trunk/drivers/gpu/drm/radeon/evergreend.h b/trunk/drivers/gpu/drm/radeon/evergreend.h index afec1aca2a73..36d32d83d866 100644 --- a/trunk/drivers/gpu/drm/radeon/evergreend.h +++ b/trunk/drivers/gpu/drm/radeon/evergreend.h @@ -240,7 +240,6 @@ #define FORCE_EOV_MAX_CLK_CNT(x) ((x) << 0) #define FORCE_EOV_MAX_REZ_CNT(x) ((x) << 16) #define PA_SC_LINE_STIPPLE 0x28A0C -#define PA_SU_LINE_STIPPLE_VALUE 0x8A60 #define PA_SC_LINE_STIPPLE_STATE 0x8B10 #define SCRATCH_REG0 0x8500 @@ -653,7 +652,6 @@ #define PACKET3_DISPATCH_DIRECT 0x15 #define PACKET3_DISPATCH_INDIRECT 0x16 #define PACKET3_INDIRECT_BUFFER_END 0x17 -#define PACKET3_MODE_CONTROL 0x18 #define PACKET3_SET_PREDICATION 0x20 #define PACKET3_REG_RMW 0x21 #define PACKET3_COND_EXEC 0x22 diff --git a/trunk/drivers/gpu/drm/radeon/r600.c b/trunk/drivers/gpu/drm/radeon/r600.c index 650672a0f5ad..1e10e3e2ba2a 100644 --- a/trunk/drivers/gpu/drm/radeon/r600.c +++ b/trunk/drivers/gpu/drm/radeon/r600.c @@ -97,16 +97,12 @@ void r600_irq_disable(struct radeon_device *rdev); static void r600_pcie_gen2_enable(struct radeon_device *rdev); /* get temperature in millidegrees */ -int rv6xx_get_temp(struct radeon_device *rdev) +u32 rv6xx_get_temp(struct radeon_device *rdev) { u32 temp = (RREG32(CG_THERMAL_STATUS) & ASIC_T_MASK) >> ASIC_T_SHIFT; - int actual_temp = temp & 0xff; - if (temp & 0x100) - actual_temp -= 256; - - return actual_temp * 1000; + return temp * 1000; } void r600_pm_get_dynpm_state(struct radeon_device *rdev) diff --git a/trunk/drivers/gpu/drm/radeon/radeon.h b/trunk/drivers/gpu/drm/radeon/radeon.h index 56c48b67ef3d..71d2a554bbe6 100644 --- a/trunk/drivers/gpu/drm/radeon/radeon.h +++ b/trunk/drivers/gpu/drm/radeon/radeon.h @@ -179,10 +179,10 @@ void radeon_combios_get_power_modes(struct radeon_device *rdev); void radeon_atombios_get_power_modes(struct radeon_device *rdev); void radeon_atom_set_voltage(struct radeon_device *rdev, u16 level); void rs690_pm_info(struct radeon_device *rdev); -extern int rv6xx_get_temp(struct radeon_device *rdev); -extern int rv770_get_temp(struct radeon_device *rdev); -extern int evergreen_get_temp(struct radeon_device *rdev); -extern int sumo_get_temp(struct radeon_device *rdev); +extern u32 rv6xx_get_temp(struct radeon_device *rdev); +extern u32 rv770_get_temp(struct radeon_device *rdev); +extern u32 evergreen_get_temp(struct radeon_device *rdev); +extern u32 sumo_get_temp(struct radeon_device *rdev); /* * Fences. @@ -812,7 +812,8 @@ struct radeon_pm { fixed20_12 sclk; fixed20_12 mclk; fixed20_12 needed_bandwidth; - struct radeon_power_state *power_state; + /* XXX: use a define for num power modes */ + struct radeon_power_state power_state[8]; /* number of valid power states */ int num_power_states; int current_power_state_index; diff --git a/trunk/drivers/gpu/drm/radeon/radeon_asic.c b/trunk/drivers/gpu/drm/radeon/radeon_asic.c index e75d63b8e21d..3a1b16186224 100644 --- a/trunk/drivers/gpu/drm/radeon/radeon_asic.c +++ b/trunk/drivers/gpu/drm/radeon/radeon_asic.c @@ -759,7 +759,7 @@ static struct radeon_asic evergreen_asic = { .gart_tlb_flush = &evergreen_pcie_gart_tlb_flush, .gart_set_page = &rs600_gart_set_page, .ring_test = &r600_ring_test, - .ring_ib_execute = &evergreen_ring_ib_execute, + .ring_ib_execute = &r600_ring_ib_execute, .irq_set = &evergreen_irq_set, .irq_process = &evergreen_irq_process, .get_vblank_counter = &evergreen_get_vblank_counter, @@ -805,7 +805,7 @@ static struct radeon_asic sumo_asic = { .gart_tlb_flush = &evergreen_pcie_gart_tlb_flush, .gart_set_page = &rs600_gart_set_page, .ring_test = &r600_ring_test, - .ring_ib_execute = &evergreen_ring_ib_execute, + .ring_ib_execute = &r600_ring_ib_execute, .irq_set = &evergreen_irq_set, .irq_process = &evergreen_irq_process, .get_vblank_counter = &evergreen_get_vblank_counter, @@ -848,7 +848,7 @@ static struct radeon_asic btc_asic = { .gart_tlb_flush = &evergreen_pcie_gart_tlb_flush, .gart_set_page = &rs600_gart_set_page, .ring_test = &r600_ring_test, - .ring_ib_execute = &evergreen_ring_ib_execute, + .ring_ib_execute = &r600_ring_ib_execute, .irq_set = &evergreen_irq_set, .irq_process = &evergreen_irq_process, .get_vblank_counter = &evergreen_get_vblank_counter, diff --git a/trunk/drivers/gpu/drm/radeon/radeon_asic.h b/trunk/drivers/gpu/drm/radeon/radeon_asic.h index c59bd98a2029..e01f07718539 100644 --- a/trunk/drivers/gpu/drm/radeon/radeon_asic.h +++ b/trunk/drivers/gpu/drm/radeon/radeon_asic.h @@ -355,7 +355,6 @@ int evergreen_resume(struct radeon_device *rdev); bool evergreen_gpu_is_lockup(struct radeon_device *rdev); int evergreen_asic_reset(struct radeon_device *rdev); void evergreen_bandwidth_update(struct radeon_device *rdev); -void evergreen_ring_ib_execute(struct radeon_device *rdev, struct radeon_ib *ib); int evergreen_copy_blit(struct radeon_device *rdev, uint64_t src_offset, uint64_t dst_offset, unsigned num_pages, struct radeon_fence *fence); diff --git a/trunk/drivers/gpu/drm/radeon/radeon_atombios.c b/trunk/drivers/gpu/drm/radeon/radeon_atombios.c index 5c1cc7ad9a15..52777902bbcc 100644 --- a/trunk/drivers/gpu/drm/radeon/radeon_atombios.c +++ b/trunk/drivers/gpu/drm/radeon/radeon_atombios.c @@ -1163,6 +1163,16 @@ bool radeon_atom_get_clock_info(struct drm_device *dev) p1pll->pll_out_min = 64800; else p1pll->pll_out_min = 20000; + } else if (p1pll->pll_out_min > 64800) { + /* Limiting the pll output range is a good thing generally as + * it limits the number of possible pll combinations for a given + * frequency presumably to the ones that work best on each card. + * However, certain duallink DVI monitors seem to like + * pll combinations that would be limited by this at least on + * pre-DCE 3.0 r6xx hardware. This might need to be adjusted per + * family. + */ + p1pll->pll_out_min = 64800; } p1pll->pll_in_min = @@ -1977,9 +1987,6 @@ static int radeon_atombios_parse_power_table_1_3(struct radeon_device *rdev) num_modes = power_info->info.ucNumOfPowerModeEntries; if (num_modes > ATOM_MAX_NUMBEROF_POWER_BLOCK) num_modes = ATOM_MAX_NUMBEROF_POWER_BLOCK; - rdev->pm.power_state = kzalloc(sizeof(struct radeon_power_state) * num_modes, GFP_KERNEL); - if (!rdev->pm.power_state) - return state_index; /* last mode is usually default, array is low to high */ for (i = 0; i < num_modes; i++) { rdev->pm.power_state[state_index].clock_info[0].voltage.type = VOLTAGE_NONE; @@ -2331,10 +2338,6 @@ static int radeon_atombios_parse_power_table_4_5(struct radeon_device *rdev) power_info = (union power_info *)(mode_info->atom_context->bios + data_offset); radeon_atombios_add_pplib_thermal_controller(rdev, &power_info->pplib.sThermalController); - rdev->pm.power_state = kzalloc(sizeof(struct radeon_power_state) * - power_info->pplib.ucNumStates, GFP_KERNEL); - if (!rdev->pm.power_state) - return state_index; /* first mode is usually default, followed by low to high */ for (i = 0; i < power_info->pplib.ucNumStates; i++) { mode_index = 0; @@ -2415,10 +2418,6 @@ static int radeon_atombios_parse_power_table_6(struct radeon_device *rdev) non_clock_info_array = (struct NonClockInfoArray *) (mode_info->atom_context->bios + data_offset + power_info->pplib.usNonClockInfoArrayOffset); - rdev->pm.power_state = kzalloc(sizeof(struct radeon_power_state) * - state_array->ucNumEntries, GFP_KERNEL); - if (!rdev->pm.power_state) - return state_index; for (i = 0; i < state_array->ucNumEntries; i++) { mode_index = 0; power_state = (union pplib_power_state *)&state_array->states[i]; @@ -2492,22 +2491,19 @@ void radeon_atombios_get_power_modes(struct radeon_device *rdev) break; } } else { - rdev->pm.power_state = kzalloc(sizeof(struct radeon_power_state), GFP_KERNEL); - if (rdev->pm.power_state) { - /* add the default mode */ - rdev->pm.power_state[state_index].type = - POWER_STATE_TYPE_DEFAULT; - rdev->pm.power_state[state_index].num_clock_modes = 1; - rdev->pm.power_state[state_index].clock_info[0].mclk = rdev->clock.default_mclk; - rdev->pm.power_state[state_index].clock_info[0].sclk = rdev->clock.default_sclk; - rdev->pm.power_state[state_index].default_clock_mode = - &rdev->pm.power_state[state_index].clock_info[0]; - rdev->pm.power_state[state_index].clock_info[0].voltage.type = VOLTAGE_NONE; - rdev->pm.power_state[state_index].pcie_lanes = 16; - rdev->pm.default_power_state_index = state_index; - rdev->pm.power_state[state_index].flags = 0; - state_index++; - } + /* add the default mode */ + rdev->pm.power_state[state_index].type = + POWER_STATE_TYPE_DEFAULT; + rdev->pm.power_state[state_index].num_clock_modes = 1; + rdev->pm.power_state[state_index].clock_info[0].mclk = rdev->clock.default_mclk; + rdev->pm.power_state[state_index].clock_info[0].sclk = rdev->clock.default_sclk; + rdev->pm.power_state[state_index].default_clock_mode = + &rdev->pm.power_state[state_index].clock_info[0]; + rdev->pm.power_state[state_index].clock_info[0].voltage.type = VOLTAGE_NONE; + rdev->pm.power_state[state_index].pcie_lanes = 16; + rdev->pm.default_power_state_index = state_index; + rdev->pm.power_state[state_index].flags = 0; + state_index++; } rdev->pm.num_power_states = state_index; @@ -2623,7 +2619,7 @@ void radeon_atom_initialize_bios_scratch_regs(struct drm_device *dev) bios_2_scratch &= ~ATOM_S2_VRI_BRIGHT_ENABLE; /* tell the bios not to handle mode switching */ - bios_6_scratch |= ATOM_S6_ACC_BLOCK_DISPLAY_SWITCH; + bios_6_scratch |= (ATOM_S6_ACC_BLOCK_DISPLAY_SWITCH | ATOM_S6_ACC_MODE); if (rdev->family >= CHIP_R600) { WREG32(R600_BIOS_2_SCRATCH, bios_2_scratch); @@ -2674,13 +2670,10 @@ void radeon_atom_output_lock(struct drm_encoder *encoder, bool lock) else bios_6_scratch = RREG32(RADEON_BIOS_6_SCRATCH); - if (lock) { + if (lock) bios_6_scratch |= ATOM_S6_CRITICAL_STATE; - bios_6_scratch &= ~ATOM_S6_ACC_MODE; - } else { + else bios_6_scratch &= ~ATOM_S6_CRITICAL_STATE; - bios_6_scratch |= ATOM_S6_ACC_MODE; - } if (rdev->family >= CHIP_R600) WREG32(R600_BIOS_6_SCRATCH, bios_6_scratch); diff --git a/trunk/drivers/gpu/drm/radeon/radeon_combios.c b/trunk/drivers/gpu/drm/radeon/radeon_combios.c index d27ef74590cd..591fcae8f224 100644 --- a/trunk/drivers/gpu/drm/radeon/radeon_combios.c +++ b/trunk/drivers/gpu/drm/radeon/radeon_combios.c @@ -2442,17 +2442,6 @@ void radeon_combios_get_power_modes(struct radeon_device *rdev) rdev->pm.default_power_state_index = -1; - /* allocate 2 power states */ - rdev->pm.power_state = kzalloc(sizeof(struct radeon_power_state) * 2, GFP_KERNEL); - if (!rdev->pm.power_state) { - rdev->pm.default_power_state_index = state_index; - rdev->pm.num_power_states = 0; - - rdev->pm.current_power_state_index = rdev->pm.default_power_state_index; - rdev->pm.current_clock_mode_index = 0; - return; - } - if (rdev->flags & RADEON_IS_MOBILITY) { offset = combios_get_table_offset(dev, COMBIOS_POWERPLAY_INFO_TABLE); if (offset) { diff --git a/trunk/drivers/gpu/drm/radeon/radeon_display.c b/trunk/drivers/gpu/drm/radeon/radeon_display.c index 2eff98cfd728..d26dabf878d9 100644 --- a/trunk/drivers/gpu/drm/radeon/radeon_display.c +++ b/trunk/drivers/gpu/drm/radeon/radeon_display.c @@ -780,115 +780,6 @@ static int radeon_ddc_dump(struct drm_connector *connector) return ret; } -/* avivo */ -static void avivo_get_fb_div(struct radeon_pll *pll, - u32 target_clock, - u32 post_div, - u32 ref_div, - u32 *fb_div, - u32 *frac_fb_div) -{ - u32 tmp = post_div * ref_div; - - tmp *= target_clock; - *fb_div = tmp / pll->reference_freq; - *frac_fb_div = tmp % pll->reference_freq; -} - -static u32 avivo_get_post_div(struct radeon_pll *pll, - u32 target_clock) -{ - u32 vco, post_div, tmp; - - if (pll->flags & RADEON_PLL_USE_POST_DIV) - return pll->post_div; - - if (pll->flags & RADEON_PLL_PREFER_MINM_OVER_MAXP) { - if (pll->flags & RADEON_PLL_IS_LCD) - vco = pll->lcd_pll_out_min; - else - vco = pll->pll_out_min; - } else { - if (pll->flags & RADEON_PLL_IS_LCD) - vco = pll->lcd_pll_out_max; - else - vco = pll->pll_out_max; - } - - post_div = vco / target_clock; - tmp = vco % target_clock; - - if (pll->flags & RADEON_PLL_PREFER_MINM_OVER_MAXP) { - if (tmp) - post_div++; - } else { - if (!tmp) - post_div--; - } - - return post_div; -} - -#define MAX_TOLERANCE 10 - -void radeon_compute_pll_avivo(struct radeon_pll *pll, - u32 freq, - u32 *dot_clock_p, - u32 *fb_div_p, - u32 *frac_fb_div_p, - u32 *ref_div_p, - u32 *post_div_p) -{ - u32 target_clock = freq / 10; - u32 post_div = avivo_get_post_div(pll, target_clock); - u32 ref_div = pll->min_ref_div; - u32 fb_div = 0, frac_fb_div = 0, tmp; - - if (pll->flags & RADEON_PLL_USE_REF_DIV) - ref_div = pll->reference_div; - - if (pll->flags & RADEON_PLL_USE_FRAC_FB_DIV) { - avivo_get_fb_div(pll, target_clock, post_div, ref_div, &fb_div, &frac_fb_div); - frac_fb_div = (100 * frac_fb_div) / pll->reference_freq; - if (frac_fb_div >= 5) { - frac_fb_div -= 5; - frac_fb_div = frac_fb_div / 10; - frac_fb_div++; - } - if (frac_fb_div >= 10) { - fb_div++; - frac_fb_div = 0; - } - } else { - while (ref_div <= pll->max_ref_div) { - avivo_get_fb_div(pll, target_clock, post_div, ref_div, - &fb_div, &frac_fb_div); - if (frac_fb_div >= (pll->reference_freq / 2)) - fb_div++; - frac_fb_div = 0; - tmp = (pll->reference_freq * fb_div) / (post_div * ref_div); - tmp = (tmp * 10000) / target_clock; - - if (tmp > (10000 + MAX_TOLERANCE)) - ref_div++; - else if (tmp >= (10000 - MAX_TOLERANCE)) - break; - else - ref_div++; - } - } - - *dot_clock_p = ((pll->reference_freq * fb_div * 10) + (pll->reference_freq * frac_fb_div)) / - (ref_div * post_div * 10); - *fb_div_p = fb_div; - *frac_fb_div_p = frac_fb_div; - *ref_div_p = ref_div; - *post_div_p = post_div; - DRM_DEBUG_KMS("%d, pll dividers - fb: %d.%d ref: %d, post %d\n", - *dot_clock_p, fb_div, frac_fb_div, ref_div, post_div); -} - -/* pre-avivo */ static inline uint32_t radeon_div(uint64_t n, uint32_t d) { uint64_t mod; @@ -899,13 +790,13 @@ static inline uint32_t radeon_div(uint64_t n, uint32_t d) return n; } -void radeon_compute_pll_legacy(struct radeon_pll *pll, - uint64_t freq, - uint32_t *dot_clock_p, - uint32_t *fb_div_p, - uint32_t *frac_fb_div_p, - uint32_t *ref_div_p, - uint32_t *post_div_p) +void radeon_compute_pll(struct radeon_pll *pll, + uint64_t freq, + uint32_t *dot_clock_p, + uint32_t *fb_div_p, + uint32_t *frac_fb_div_p, + uint32_t *ref_div_p, + uint32_t *post_div_p) { uint32_t min_ref_div = pll->min_ref_div; uint32_t max_ref_div = pll->max_ref_div; @@ -935,9 +826,6 @@ void radeon_compute_pll_legacy(struct radeon_pll *pll, pll_out_max = pll->pll_out_max; } - if (pll_out_min > 64800) - pll_out_min = 64800; - if (pll->flags & RADEON_PLL_USE_REF_DIV) min_ref_div = max_ref_div = pll->reference_div; else { @@ -961,7 +849,7 @@ void radeon_compute_pll_legacy(struct radeon_pll *pll, max_fractional_feed_div = pll->max_frac_feedback_div; } - for (post_div = min_post_div; post_div <= max_post_div; ++post_div) { + for (post_div = max_post_div; post_div >= min_post_div; --post_div) { uint32_t ref_div; if ((pll->flags & RADEON_PLL_NO_ODD_POST_DIV) && (post_div & 1)) @@ -1077,10 +965,6 @@ void radeon_compute_pll_legacy(struct radeon_pll *pll, *frac_fb_div_p = best_frac_feedback_div; *ref_div_p = best_ref_div; *post_div_p = best_post_div; - DRM_DEBUG_KMS("%d %d, pll dividers - fb: %d.%d ref: %d, post %d\n", - freq, best_freq / 1000, best_feedback_div, best_frac_feedback_div, - best_ref_div, best_post_div); - } static void radeon_user_framebuffer_destroy(struct drm_framebuffer *fb) diff --git a/trunk/drivers/gpu/drm/radeon/radeon_encoders.c b/trunk/drivers/gpu/drm/radeon/radeon_encoders.c index d4a542247618..5e90984d5ad2 100644 --- a/trunk/drivers/gpu/drm/radeon/radeon_encoders.c +++ b/trunk/drivers/gpu/drm/radeon/radeon_encoders.c @@ -1063,7 +1063,7 @@ atombios_set_edp_panel_power(struct drm_connector *connector, int action) if (!ASIC_IS_DCE4(rdev)) return; - if ((action != ATOM_TRANSMITTER_ACTION_POWER_ON) && + if ((action != ATOM_TRANSMITTER_ACTION_POWER_ON) || (action != ATOM_TRANSMITTER_ACTION_POWER_OFF)) return; diff --git a/trunk/drivers/gpu/drm/radeon/radeon_legacy_crtc.c b/trunk/drivers/gpu/drm/radeon/radeon_legacy_crtc.c index cf0638c3b7c7..ace2e6384d40 100644 --- a/trunk/drivers/gpu/drm/radeon/radeon_legacy_crtc.c +++ b/trunk/drivers/gpu/drm/radeon/radeon_legacy_crtc.c @@ -778,9 +778,9 @@ static void radeon_set_pll(struct drm_crtc *crtc, struct drm_display_mode *mode) DRM_DEBUG_KMS("\n"); if (!use_bios_divs) { - radeon_compute_pll_legacy(pll, mode->clock, - &freq, &feedback_div, &frac_fb_div, - &reference_div, &post_divider); + radeon_compute_pll(pll, mode->clock, + &freq, &feedback_div, &frac_fb_div, + &reference_div, &post_divider); for (post_div = &post_divs[0]; post_div->divider; ++post_div) { if (post_div->divider == post_divider) diff --git a/trunk/drivers/gpu/drm/radeon/radeon_mode.h b/trunk/drivers/gpu/drm/radeon/radeon_mode.h index 6794cdf91f28..12bdeab91c86 100644 --- a/trunk/drivers/gpu/drm/radeon/radeon_mode.h +++ b/trunk/drivers/gpu/drm/radeon/radeon_mode.h @@ -149,7 +149,6 @@ struct radeon_tmds_pll { #define RADEON_PLL_PREFER_CLOSEST_LOWER (1 << 11) #define RADEON_PLL_USE_POST_DIV (1 << 12) #define RADEON_PLL_IS_LCD (1 << 13) -#define RADEON_PLL_PREFER_MINM_OVER_MAXP (1 << 14) struct radeon_pll { /* reference frequency */ @@ -511,21 +510,13 @@ extern bool radeon_atombios_get_asic_ss_info(struct radeon_device *rdev, struct radeon_atom_ss *ss, int id, u32 clock); -extern void radeon_compute_pll_legacy(struct radeon_pll *pll, - uint64_t freq, - uint32_t *dot_clock_p, - uint32_t *fb_div_p, - uint32_t *frac_fb_div_p, - uint32_t *ref_div_p, - uint32_t *post_div_p); - -extern void radeon_compute_pll_avivo(struct radeon_pll *pll, - u32 freq, - u32 *dot_clock_p, - u32 *fb_div_p, - u32 *frac_fb_div_p, - u32 *ref_div_p, - u32 *post_div_p); +extern void radeon_compute_pll(struct radeon_pll *pll, + uint64_t freq, + uint32_t *dot_clock_p, + uint32_t *fb_div_p, + uint32_t *frac_fb_div_p, + uint32_t *ref_div_p, + uint32_t *post_div_p); extern void radeon_setup_encoder_clones(struct drm_device *dev); diff --git a/trunk/drivers/gpu/drm/radeon/radeon_pm.c b/trunk/drivers/gpu/drm/radeon/radeon_pm.c index 2aed03bde4b2..3b1b2bf9cdd5 100644 --- a/trunk/drivers/gpu/drm/radeon/radeon_pm.c +++ b/trunk/drivers/gpu/drm/radeon/radeon_pm.c @@ -430,7 +430,7 @@ static ssize_t radeon_hwmon_show_temp(struct device *dev, { struct drm_device *ddev = pci_get_drvdata(to_pci_dev(dev)); struct radeon_device *rdev = ddev->dev_private; - int temp; + u32 temp; switch (rdev->pm.int_thermal_type) { case THERMAL_TYPE_RV6XX: @@ -646,9 +646,6 @@ void radeon_pm_fini(struct radeon_device *rdev) #endif } - if (rdev->pm.power_state) - kfree(rdev->pm.power_state); - radeon_hwmon_fini(rdev); } diff --git a/trunk/drivers/gpu/drm/radeon/rv770.c b/trunk/drivers/gpu/drm/radeon/rv770.c index 2211a323db41..491dc9000655 100644 --- a/trunk/drivers/gpu/drm/radeon/rv770.c +++ b/trunk/drivers/gpu/drm/radeon/rv770.c @@ -78,23 +78,18 @@ u32 rv770_page_flip(struct radeon_device *rdev, int crtc_id, u64 crtc_base) } /* get temperature in millidegrees */ -int rv770_get_temp(struct radeon_device *rdev) +u32 rv770_get_temp(struct radeon_device *rdev) { u32 temp = (RREG32(CG_MULT_THERMAL_STATUS) & ASIC_T_MASK) >> ASIC_T_SHIFT; - int actual_temp; - - if (temp & 0x400) - actual_temp = -256; - else if (temp & 0x200) - actual_temp = 255; - else if (temp & 0x100) { - actual_temp = temp & 0x1ff; - actual_temp |= ~0x1ff; - } else - actual_temp = temp & 0xff; - - return (actual_temp * 1000) / 2; + u32 actual_temp = 0; + + if ((temp >> 9) & 1) + actual_temp = 0; + else + actual_temp = (temp >> 1) & 0xff; + + return actual_temp * 1000; } void rv770_pm_misc(struct radeon_device *rdev) diff --git a/trunk/drivers/infiniband/core/sa_query.c b/trunk/drivers/infiniband/core/sa_query.c index fbbfa24cf572..e38be1bcc01c 100644 --- a/trunk/drivers/infiniband/core/sa_query.c +++ b/trunk/drivers/infiniband/core/sa_query.c @@ -1079,7 +1079,7 @@ static void ib_sa_remove_one(struct ib_device *device) ib_unregister_event_handler(&sa_dev->event_handler); - flush_workqueue(ib_wq); + flush_scheduled_work(); for (i = 0; i <= sa_dev->end_port - sa_dev->start_port; ++i) { if (rdma_port_get_link_layer(device, i + 1) == IB_LINK_LAYER_INFINIBAND) { diff --git a/trunk/drivers/infiniband/core/ucma.c b/trunk/drivers/infiniband/core/ucma.c index ec1e9da1488b..ca12acf38379 100644 --- a/trunk/drivers/infiniband/core/ucma.c +++ b/trunk/drivers/infiniband/core/ucma.c @@ -636,16 +636,6 @@ static void ucma_copy_iboe_route(struct rdma_ucm_query_route_resp *resp, } } -static void ucma_copy_iw_route(struct rdma_ucm_query_route_resp *resp, - struct rdma_route *route) -{ - struct rdma_dev_addr *dev_addr; - - dev_addr = &route->addr.dev_addr; - rdma_addr_get_dgid(dev_addr, (union ib_gid *) &resp->ib_route[0].dgid); - rdma_addr_get_sgid(dev_addr, (union ib_gid *) &resp->ib_route[0].sgid); -} - static ssize_t ucma_query_route(struct ucma_file *file, const char __user *inbuf, int in_len, int out_len) @@ -680,10 +670,8 @@ static ssize_t ucma_query_route(struct ucma_file *file, resp.node_guid = (__force __u64) ctx->cm_id->device->node_guid; resp.port_num = ctx->cm_id->port_num; - switch (rdma_node_get_transport(ctx->cm_id->device->node_type)) { - case RDMA_TRANSPORT_IB: - switch (rdma_port_get_link_layer(ctx->cm_id->device, - ctx->cm_id->port_num)) { + if (rdma_node_get_transport(ctx->cm_id->device->node_type) == RDMA_TRANSPORT_IB) { + switch (rdma_port_get_link_layer(ctx->cm_id->device, ctx->cm_id->port_num)) { case IB_LINK_LAYER_INFINIBAND: ucma_copy_ib_route(&resp, &ctx->cm_id->route); break; @@ -693,12 +681,6 @@ static ssize_t ucma_query_route(struct ucma_file *file, default: break; } - break; - case RDMA_TRANSPORT_IWARP: - ucma_copy_iw_route(&resp, &ctx->cm_id->route); - break; - default: - break; } out: diff --git a/trunk/drivers/infiniband/hw/amso1100/c2_vq.c b/trunk/drivers/infiniband/hw/amso1100/c2_vq.c index 2ec716fb2edb..9ce7819b7b2e 100644 --- a/trunk/drivers/infiniband/hw/amso1100/c2_vq.c +++ b/trunk/drivers/infiniband/hw/amso1100/c2_vq.c @@ -107,7 +107,7 @@ struct c2_vq_req *vq_req_alloc(struct c2_dev *c2dev) r = kmalloc(sizeof(struct c2_vq_req), GFP_KERNEL); if (r) { init_waitqueue_head(&r->wait_object); - r->reply_msg = 0; + r->reply_msg = (u64) NULL; r->event = 0; r->cm_id = NULL; r->qp = NULL; @@ -123,7 +123,7 @@ struct c2_vq_req *vq_req_alloc(struct c2_dev *c2dev) */ void vq_req_free(struct c2_dev *c2dev, struct c2_vq_req *r) { - r->reply_msg = 0; + r->reply_msg = (u64) NULL; if (atomic_dec_and_test(&r->refcnt)) { kfree(r); } @@ -151,7 +151,7 @@ void vq_req_get(struct c2_dev *c2dev, struct c2_vq_req *r) void vq_req_put(struct c2_dev *c2dev, struct c2_vq_req *r) { if (atomic_dec_and_test(&r->refcnt)) { - if (r->reply_msg != 0) + if (r->reply_msg != (u64) NULL) vq_repbuf_free(c2dev, (void *) (unsigned long) r->reply_msg); kfree(r); diff --git a/trunk/drivers/infiniband/hw/cxgb4/cm.c b/trunk/drivers/infiniband/hw/cxgb4/cm.c index 8b00e6c46f01..0dc62b1438be 100644 --- a/trunk/drivers/infiniband/hw/cxgb4/cm.c +++ b/trunk/drivers/infiniband/hw/cxgb4/cm.c @@ -380,7 +380,7 @@ static void send_flowc(struct c4iw_ep *ep, struct sk_buff *skb) 16)) | FW_WR_FLOWID(ep->hwtid)); flowc->mnemval[0].mnemonic = FW_FLOWC_MNEM_PFNVFN; - flowc->mnemval[0].val = cpu_to_be32(PCI_FUNC(ep->com.dev->rdev.lldi.pdev->devfn) << 8); + flowc->mnemval[0].val = cpu_to_be32(0); flowc->mnemval[1].mnemonic = FW_FLOWC_MNEM_CH; flowc->mnemval[1].val = cpu_to_be32(ep->tx_chan); flowc->mnemval[2].mnemonic = FW_FLOWC_MNEM_PORT; diff --git a/trunk/drivers/infiniband/hw/cxgb4/qp.c b/trunk/drivers/infiniband/hw/cxgb4/qp.c index 4f0be25cab1a..20800900ef3f 100644 --- a/trunk/drivers/infiniband/hw/cxgb4/qp.c +++ b/trunk/drivers/infiniband/hw/cxgb4/qp.c @@ -220,7 +220,7 @@ static int create_qp(struct c4iw_rdev *rdev, struct t4_wq *wq, V_FW_RI_RES_WR_DCAEN(0) | V_FW_RI_RES_WR_DCACPU(0) | V_FW_RI_RES_WR_FBMIN(2) | - V_FW_RI_RES_WR_FBMAX(2) | + V_FW_RI_RES_WR_FBMAX(3) | V_FW_RI_RES_WR_CIDXFTHRESHO(0) | V_FW_RI_RES_WR_CIDXFTHRESH(0) | V_FW_RI_RES_WR_EQSIZE(eqsize)); @@ -243,7 +243,7 @@ static int create_qp(struct c4iw_rdev *rdev, struct t4_wq *wq, V_FW_RI_RES_WR_DCAEN(0) | V_FW_RI_RES_WR_DCACPU(0) | V_FW_RI_RES_WR_FBMIN(2) | - V_FW_RI_RES_WR_FBMAX(2) | + V_FW_RI_RES_WR_FBMAX(3) | V_FW_RI_RES_WR_CIDXFTHRESHO(0) | V_FW_RI_RES_WR_CIDXFTHRESH(0) | V_FW_RI_RES_WR_EQSIZE(eqsize)); diff --git a/trunk/drivers/infiniband/hw/qib/qib_iba7322.c b/trunk/drivers/infiniband/hw/qib/qib_iba7322.c index b01809a82cb0..50cceb3ab885 100644 --- a/trunk/drivers/infiniband/hw/qib/qib_iba7322.c +++ b/trunk/drivers/infiniband/hw/qib/qib_iba7322.c @@ -623,6 +623,7 @@ struct qib_chippport_specific { u8 ibmalfusesnap; struct qib_qsfp_data qsfp_data; char epmsgbuf[192]; /* for port error interrupt msg buffer */ + u8 bounced; }; static struct { @@ -1880,7 +1881,23 @@ static noinline void handle_7322_p_errors(struct qib_pportdata *ppd) IB_PHYSPORTSTATE_DISABLED) qib_set_ib_7322_lstate(ppd, 0, QLOGIC_IB_IBCC_LINKINITCMD_DISABLE); - else + else { + u32 lstate; + /* + * We need the current logical link state before + * lflags are set in handle_e_ibstatuschanged. + */ + lstate = qib_7322_iblink_state(ibcs); + + if (IS_QMH(dd) && !ppd->cpspec->bounced && + ltstate == IB_PHYSPORTSTATE_LINKUP && + (lstate >= IB_PORT_INIT && + lstate <= IB_PORT_ACTIVE)) { + ppd->cpspec->bounced = 1; + qib_7322_set_ib_cfg(ppd, QIB_IB_CFG_LSTATE, + IB_LINKCMD_DOWN | IB_LINKINITCMD_POLL); + } + /* * Since going into a recovery state causes the link * state to go down and since recovery is transitory, @@ -1894,6 +1911,7 @@ static noinline void handle_7322_p_errors(struct qib_pportdata *ppd) ltstate != IB_PHYSPORTSTATE_RECOVERY_WAITRMT && ltstate != IB_PHYSPORTSTATE_RECOVERY_IDLE) qib_handle_e_ibstatuschanged(ppd, ibcs); + } } if (*msg && iserr) qib_dev_porterr(dd, ppd->port, "%s error\n", msg); @@ -2363,11 +2381,6 @@ static int qib_7322_bringup_serdes(struct qib_pportdata *ppd) qib_write_kreg_port(ppd, krp_rcvctrl, ppd->p_rcvctrl); spin_unlock_irqrestore(&dd->cspec->rcvmod_lock, flags); - /* Hold the link state machine for mezz boards */ - if (IS_QMH(dd) || IS_QME(dd)) - qib_set_ib_7322_lstate(ppd, 0, - QLOGIC_IB_IBCC_LINKINITCMD_DISABLE); - /* Also enable IBSTATUSCHG interrupt. */ val = qib_read_kreg_port(ppd, krp_errmask); qib_write_kreg_port(ppd, krp_errmask, @@ -5689,11 +5702,6 @@ static void set_no_qsfp_atten(struct qib_devdata *dd, int change) ppd->cpspec->h1_val = h1; /* now change the IBC and serdes, overriding generic */ init_txdds_table(ppd, 1); - /* Re-enable the physical state machine on mezz boards - * now that the correct settings have been set. */ - if (IS_QMH(dd) || IS_QME(dd)) - qib_set_ib_7322_lstate(ppd, 0, - QLOGIC_IB_IBCC_LINKINITCMD_SLEEP); any++; } if (*nxt == '\n') diff --git a/trunk/drivers/input/misc/ixp4xx-beeper.c b/trunk/drivers/input/misc/ixp4xx-beeper.c index 1f38302a5951..9dfd6e5f786f 100644 --- a/trunk/drivers/input/misc/ixp4xx-beeper.c +++ b/trunk/drivers/input/misc/ixp4xx-beeper.c @@ -69,7 +69,11 @@ static int ixp4xx_spkr_event(struct input_dev *dev, unsigned int type, unsigned } if (value > 20 && value < 32767) - count = (IXP4XX_TIMER_FREQ / (value * 4)) - 1; +#ifndef FREQ + count = (ixp4xx_get_board_tick_rate() / (value * 4)) - 1; +#else + count = (FREQ / (value * 4)) - 1; +#endif ixp4xx_spkr_control(pin, count); diff --git a/trunk/drivers/isdn/icn/icn.c b/trunk/drivers/isdn/icn/icn.c index 1f355bb85e54..f2b5bab5e6a1 100644 --- a/trunk/drivers/isdn/icn/icn.c +++ b/trunk/drivers/isdn/icn/icn.c @@ -1627,7 +1627,7 @@ __setup("icn=", icn_setup); static int __init icn_init(void) { char *p; - char rev[21]; + char rev[20]; memset(&dev, 0, sizeof(icn_dev)); dev.memaddr = (membase & 0x0ffc000); @@ -1638,7 +1638,6 @@ static int __init icn_init(void) if ((p = strchr(revision, ':'))) { strncpy(rev, p + 1, 20); - rev[20] = '\0'; p = strchr(rev, '$'); if (p) *p = 0; diff --git a/trunk/drivers/net/atl1c/atl1c_main.c b/trunk/drivers/net/atl1c/atl1c_main.c index 3824382faecc..a699bbf20eb5 100644 --- a/trunk/drivers/net/atl1c/atl1c_main.c +++ b/trunk/drivers/net/atl1c/atl1c_main.c @@ -48,7 +48,6 @@ static DEFINE_PCI_DEVICE_TABLE(atl1c_pci_tbl) = { {PCI_DEVICE(PCI_VENDOR_ID_ATTANSIC, PCI_DEVICE_ID_ATHEROS_L2C_B)}, {PCI_DEVICE(PCI_VENDOR_ID_ATTANSIC, PCI_DEVICE_ID_ATHEROS_L2C_B2)}, {PCI_DEVICE(PCI_VENDOR_ID_ATTANSIC, PCI_DEVICE_ID_ATHEROS_L1D)}, - {PCI_DEVICE(PCI_VENDOR_ID_ATTANSIC, PCI_DEVICE_ID_ATHEROS_L1D_2_0)}, /* required last entry */ { 0 } }; diff --git a/trunk/drivers/net/benet/be_main.c b/trunk/drivers/net/benet/be_main.c index 28a32a6c8bf1..de40d3b7152f 100644 --- a/trunk/drivers/net/benet/be_main.c +++ b/trunk/drivers/net/benet/be_main.c @@ -312,9 +312,11 @@ void be_link_status_update(struct be_adapter *adapter, bool link_up) if (adapter->link_up != link_up) { adapter->link_speed = -1; if (link_up) { + netif_start_queue(netdev); netif_carrier_on(netdev); printk(KERN_INFO "%s: Link up\n", netdev->name); } else { + netif_stop_queue(netdev); netif_carrier_off(netdev); printk(KERN_INFO "%s: Link down\n", netdev->name); } @@ -2626,6 +2628,8 @@ static void be_netdev_init(struct net_device *netdev) netif_napi_add(netdev, &adapter->tx_eq.napi, be_poll_tx_mcc, BE_NAPI_WEIGHT); + + netif_stop_queue(netdev); } static void be_unmap_pci_bars(struct be_adapter *adapter) diff --git a/trunk/drivers/net/bnx2x/bnx2x.h b/trunk/drivers/net/bnx2x/bnx2x.h index 653c62475cb6..8e4183717d91 100644 --- a/trunk/drivers/net/bnx2x/bnx2x.h +++ b/trunk/drivers/net/bnx2x/bnx2x.h @@ -22,8 +22,8 @@ * (you will need to reboot afterwards) */ /* #define BNX2X_STOP_ON_ERROR */ -#define DRV_MODULE_VERSION "1.62.00-5" -#define DRV_MODULE_RELDATE "2011/01/30" +#define DRV_MODULE_VERSION "1.62.00-4" +#define DRV_MODULE_RELDATE "2011/01/18" #define BNX2X_BC_VER 0x040200 #define BNX2X_MULTI_QUEUE diff --git a/trunk/drivers/net/bnx2x/bnx2x_link.c b/trunk/drivers/net/bnx2x/bnx2x_link.c index dd1210fddfff..7160ec51093e 100644 --- a/trunk/drivers/net/bnx2x/bnx2x_link.c +++ b/trunk/drivers/net/bnx2x/bnx2x_link.c @@ -3948,6 +3948,48 @@ static u8 bnx2x_8073_8727_external_rom_boot(struct bnx2x *bp, return rc; } +static void bnx2x_8073_set_xaui_low_power_mode(struct bnx2x *bp, + struct bnx2x_phy *phy) +{ + u16 val; + bnx2x_cl45_read(bp, phy, + MDIO_PMA_DEVAD, MDIO_PMA_REG_8073_CHIP_REV, &val); + + if (val == 0) { + /* Mustn't set low power mode in 8073 A0 */ + return; + } + + /* Disable PLL sequencer (use read-modify-write to clear bit 13) */ + bnx2x_cl45_read(bp, phy, + MDIO_XS_DEVAD, MDIO_XS_PLL_SEQUENCER, &val); + val &= ~(1<<13); + bnx2x_cl45_write(bp, phy, + MDIO_XS_DEVAD, MDIO_XS_PLL_SEQUENCER, val); + + /* PLL controls */ + bnx2x_cl45_write(bp, phy, MDIO_XS_DEVAD, 0x805E, 0x1077); + bnx2x_cl45_write(bp, phy, MDIO_XS_DEVAD, 0x805D, 0x0000); + bnx2x_cl45_write(bp, phy, MDIO_XS_DEVAD, 0x805C, 0x030B); + bnx2x_cl45_write(bp, phy, MDIO_XS_DEVAD, 0x805B, 0x1240); + bnx2x_cl45_write(bp, phy, MDIO_XS_DEVAD, 0x805A, 0x2490); + + /* Tx Controls */ + bnx2x_cl45_write(bp, phy, MDIO_XS_DEVAD, 0x80A7, 0x0C74); + bnx2x_cl45_write(bp, phy, MDIO_XS_DEVAD, 0x80A6, 0x9041); + bnx2x_cl45_write(bp, phy, MDIO_XS_DEVAD, 0x80A5, 0x4640); + + /* Rx Controls */ + bnx2x_cl45_write(bp, phy, MDIO_XS_DEVAD, 0x80FE, 0x01C4); + bnx2x_cl45_write(bp, phy, MDIO_XS_DEVAD, 0x80FD, 0x9249); + bnx2x_cl45_write(bp, phy, MDIO_XS_DEVAD, 0x80FC, 0x2015); + + /* Enable PLL sequencer (use read-modify-write to set bit 13) */ + bnx2x_cl45_read(bp, phy, MDIO_XS_DEVAD, MDIO_XS_PLL_SEQUENCER, &val); + val |= (1<<13); + bnx2x_cl45_write(bp, phy, MDIO_XS_DEVAD, MDIO_XS_PLL_SEQUENCER, val); +} + /******************************************************************/ /* BCM8073 PHY SECTION */ /******************************************************************/ @@ -4106,6 +4148,8 @@ static u8 bnx2x_8073_config_init(struct bnx2x_phy *phy, bnx2x_8073_set_pause_cl37(params, phy, vars); + bnx2x_8073_set_xaui_low_power_mode(bp, phy); + bnx2x_cl45_read(bp, phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_M8051_MSGOUT_REG, &tmp1); @@ -6475,18 +6519,6 @@ static void bnx2x_848xx_set_link_led(struct bnx2x_phy *phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_8481_LED1_MASK, 0x80); - - /* Tell LED3 to blink on source */ - bnx2x_cl45_read(bp, phy, - MDIO_PMA_DEVAD, - MDIO_PMA_REG_8481_LINK_SIGNAL, - &val); - val &= ~(7<<6); - val |= (1<<6); /* A83B[8:6]= 1 */ - bnx2x_cl45_write(bp, phy, - MDIO_PMA_DEVAD, - MDIO_PMA_REG_8481_LINK_SIGNAL, - val); } break; } @@ -7688,13 +7720,10 @@ static u8 bnx2x_8073_common_init_phy(struct bnx2x *bp, struct bnx2x_phy phy[PORT_MAX]; struct bnx2x_phy *phy_blk[PORT_MAX]; u16 val; - s8 port = 0; + s8 port; s8 port_of_path = 0; - u32 swap_val, swap_override; - swap_val = REG_RD(bp, NIG_REG_PORT_SWAP); - swap_override = REG_RD(bp, NIG_REG_STRAP_OVERRIDE); - port ^= (swap_val && swap_override); - bnx2x_ext_phy_hw_reset(bp, port); + + bnx2x_ext_phy_hw_reset(bp, 0); /* PART1 - Reset both phys */ for (port = PORT_MAX - 1; port >= PORT_0; port--) { u32 shmem_base, shmem2_base; diff --git a/trunk/drivers/net/bnx2x/bnx2x_main.c b/trunk/drivers/net/bnx2x/bnx2x_main.c index f40740e68ea5..8cdcf5b39d1e 100644 --- a/trunk/drivers/net/bnx2x/bnx2x_main.c +++ b/trunk/drivers/net/bnx2x/bnx2x_main.c @@ -2301,10 +2301,15 @@ static void bnx2x_rxq_set_mac_filters(struct bnx2x *bp, u16 cl_id, u32 filters) /* accept matched ucast */ drop_all_ucast = 0; } - if (filters & BNX2X_ACCEPT_MULTICAST) + if (filters & BNX2X_ACCEPT_MULTICAST) { /* accept matched mcast */ drop_all_mcast = 0; - + if (IS_MF_SI(bp)) + /* since mcast addresses won't arrive with ovlan, + * fw needs to accept all of them in + * switch-independent mode */ + accp_all_mcast = 1; + } if (filters & BNX2X_ACCEPT_ALL_UNICAST) { /* accept all mcast */ drop_all_ucast = 0; @@ -5291,6 +5296,10 @@ static int bnx2x_init_hw_common(struct bnx2x *bp, u32 load_code) } } + bp->port.need_hw_lock = bnx2x_hw_lock_required(bp, + bp->common.shmem_base, + bp->common.shmem2_base); + bnx2x_setup_fan_failure_detection(bp); /* clear PXP2 attentions */ @@ -5494,6 +5503,9 @@ static int bnx2x_init_hw_port(struct bnx2x *bp) bnx2x_init_block(bp, MCP_BLOCK, init_stage); bnx2x_init_block(bp, DMAE_BLOCK, init_stage); + bp->port.need_hw_lock = bnx2x_hw_lock_required(bp, + bp->common.shmem_base, + bp->common.shmem2_base); if (bnx2x_fan_failure_det_req(bp, bp->common.shmem_base, bp->common.shmem2_base, port)) { u32 reg_addr = (port ? MISC_REG_AEU_ENABLE1_FUNC_1_OUT_0 : @@ -8367,17 +8379,6 @@ static void __devinit bnx2x_get_port_hwinfo(struct bnx2x *bp) (ext_phy_type != PORT_HW_CFG_XGXS_EXT_PHY_TYPE_NOT_CONN)) bp->mdio.prtad = XGXS_EXT_PHY_ADDR(ext_phy_config); - - /* - * Check if hw lock is required to access MDC/MDIO bus to the PHY(s) - * In MF mode, it is set to cover self test cases - */ - if (IS_MF(bp)) - bp->port.need_hw_lock = 1; - else - bp->port.need_hw_lock = bnx2x_hw_lock_required(bp, - bp->common.shmem_base, - bp->common.shmem2_base); } static void __devinit bnx2x_get_mac_hwinfo(struct bnx2x *bp) diff --git a/trunk/drivers/net/can/Kconfig b/trunk/drivers/net/can/Kconfig index 5dec456fd4a4..986195eaa57c 100644 --- a/trunk/drivers/net/can/Kconfig +++ b/trunk/drivers/net/can/Kconfig @@ -23,7 +23,7 @@ config CAN_SLCAN As only the sending and receiving of CAN frames is implemented, this driver should work with the (serial/USB) CAN hardware from: - www.canusb.com / www.can232.com / www.mictronics.de / www.canhack.de + www.canusb.com / www.can232.com / www.mictronic.com / www.canhack.de Userspace tools to attach the SLCAN line discipline (slcan_attach, slcand) can be found in the can-utils at the SocketCAN SVN, see diff --git a/trunk/drivers/net/can/at91_can.c b/trunk/drivers/net/can/at91_can.c index 57d2ffbbb433..2532b9631538 100644 --- a/trunk/drivers/net/can/at91_can.c +++ b/trunk/drivers/net/can/at91_can.c @@ -1109,7 +1109,7 @@ static ssize_t at91_sysfs_set_mb0_id(struct device *dev, return ret; } -static DEVICE_ATTR(mb0_id, S_IWUSR | S_IRUGO, +static DEVICE_ATTR(mb0_id, S_IWUGO | S_IRUGO, at91_sysfs_show_mb0_id, at91_sysfs_set_mb0_id); static struct attribute *at91_sysfs_attrs[] = { diff --git a/trunk/drivers/net/can/janz-ican3.c b/trunk/drivers/net/can/janz-ican3.c index 366f5cc050ae..b9a6d7a5a739 100644 --- a/trunk/drivers/net/can/janz-ican3.c +++ b/trunk/drivers/net/can/janz-ican3.c @@ -1618,7 +1618,7 @@ static ssize_t ican3_sysfs_set_term(struct device *dev, return count; } -static DEVICE_ATTR(termination, S_IWUSR | S_IRUGO, ican3_sysfs_show_term, +static DEVICE_ATTR(termination, S_IWUGO | S_IRUGO, ican3_sysfs_show_term, ican3_sysfs_set_term); static struct attribute *ican3_sysfs_attrs[] = { diff --git a/trunk/drivers/net/can/softing/Kconfig b/trunk/drivers/net/can/softing/Kconfig index 8ba81b3ddd90..92bd6bdde5e3 100644 --- a/trunk/drivers/net/can/softing/Kconfig +++ b/trunk/drivers/net/can/softing/Kconfig @@ -1,6 +1,6 @@ config CAN_SOFTING tristate "Softing Gmbh CAN generic support" - depends on CAN_DEV && HAS_IOMEM + depends on CAN_DEV ---help--- Support for CAN cards from Softing Gmbh & some cards from Vector Gmbh. diff --git a/trunk/drivers/net/depca.c b/trunk/drivers/net/depca.c index 8b0084d17c8c..1b48b68ad4fd 100644 --- a/trunk/drivers/net/depca.c +++ b/trunk/drivers/net/depca.c @@ -1094,7 +1094,7 @@ static int depca_rx(struct net_device *dev) } } /* Change buffer ownership for this last frame, back to the adapter */ - for (; lp->rx_old != entry; lp->rx_old = (lp->rx_old + 1) & lp->rxRingMask) { + for (; lp->rx_old != entry; lp->rx_old = (++lp->rx_old) & lp->rxRingMask) { writel(readl(&lp->rx_ring[lp->rx_old].base) | R_OWN, &lp->rx_ring[lp->rx_old].base); } writel(readl(&lp->rx_ring[entry].base) | R_OWN, &lp->rx_ring[entry].base); @@ -1103,7 +1103,7 @@ static int depca_rx(struct net_device *dev) /* ** Update entry information */ - lp->rx_new = (lp->rx_new + 1) & lp->rxRingMask; + lp->rx_new = (++lp->rx_new) & lp->rxRingMask; } return 0; @@ -1148,7 +1148,7 @@ static int depca_tx(struct net_device *dev) } /* Update all the pointers */ - lp->tx_old = (lp->tx_old + 1) & lp->txRingMask; + lp->tx_old = (++lp->tx_old) & lp->txRingMask; } return 0; diff --git a/trunk/drivers/net/dl2k.c b/trunk/drivers/net/dl2k.c index c05db6046050..e1a8216ff692 100644 --- a/trunk/drivers/net/dl2k.c +++ b/trunk/drivers/net/dl2k.c @@ -1753,6 +1753,8 @@ rio_close (struct net_device *dev) /* Free all the skbuffs in the queue. */ for (i = 0; i < RX_RING_SIZE; i++) { + np->rx_ring[i].status = 0; + np->rx_ring[i].fraginfo = 0; skb = np->rx_skbuff[i]; if (skb) { pci_unmap_single(np->pdev, @@ -1761,8 +1763,6 @@ rio_close (struct net_device *dev) dev_kfree_skb (skb); np->rx_skbuff[i] = NULL; } - np->rx_ring[i].status = 0; - np->rx_ring[i].fraginfo = 0; } for (i = 0; i < TX_RING_SIZE; i++) { skb = np->tx_skbuff[i]; diff --git a/trunk/drivers/net/enc28j60.c b/trunk/drivers/net/enc28j60.c index 907b05a1c659..112c5aa9af7f 100644 --- a/trunk/drivers/net/enc28j60.c +++ b/trunk/drivers/net/enc28j60.c @@ -812,7 +812,7 @@ static void enc28j60_read_tsv(struct enc28j60_net *priv, u8 tsv[TSV_SIZE]) if (netif_msg_hw(priv)) printk(KERN_DEBUG DRV_NAME ": reading TSV at addr:0x%04x\n", endptr + 1); - enc28j60_mem_read(priv, endptr + 1, TSV_SIZE, tsv); + enc28j60_mem_read(priv, endptr + 1, sizeof(tsv), tsv); } static void enc28j60_dump_tsv(struct enc28j60_net *priv, const char *msg, diff --git a/trunk/drivers/net/mlx4/main.c b/trunk/drivers/net/mlx4/main.c index 2765a3ce9c24..4ffdc18fcb8a 100644 --- a/trunk/drivers/net/mlx4/main.c +++ b/trunk/drivers/net/mlx4/main.c @@ -1286,21 +1286,6 @@ static DEFINE_PCI_DEVICE_TABLE(mlx4_pci_table) = { { PCI_VDEVICE(MELLANOX, 0x6764) }, /* MT26468 ConnectX EN 10GigE PCIe gen2*/ { PCI_VDEVICE(MELLANOX, 0x6746) }, /* MT26438 ConnectX EN 40GigE PCIe gen2 5GT/s */ { PCI_VDEVICE(MELLANOX, 0x676e) }, /* MT26478 ConnectX2 40GigE PCIe gen2 */ - { PCI_VDEVICE(MELLANOX, 0x1002) }, /* MT25400 Family [ConnectX-2 Virtual Function] */ - { PCI_VDEVICE(MELLANOX, 0x1003) }, /* MT27500 Family [ConnectX-3] */ - { PCI_VDEVICE(MELLANOX, 0x1004) }, /* MT27500 Family [ConnectX-3 Virtual Function] */ - { PCI_VDEVICE(MELLANOX, 0x1005) }, /* MT27510 Family */ - { PCI_VDEVICE(MELLANOX, 0x1006) }, /* MT27511 Family */ - { PCI_VDEVICE(MELLANOX, 0x1007) }, /* MT27520 Family */ - { PCI_VDEVICE(MELLANOX, 0x1008) }, /* MT27521 Family */ - { PCI_VDEVICE(MELLANOX, 0x1009) }, /* MT27530 Family */ - { PCI_VDEVICE(MELLANOX, 0x100a) }, /* MT27531 Family */ - { PCI_VDEVICE(MELLANOX, 0x100b) }, /* MT27540 Family */ - { PCI_VDEVICE(MELLANOX, 0x100c) }, /* MT27541 Family */ - { PCI_VDEVICE(MELLANOX, 0x100d) }, /* MT27550 Family */ - { PCI_VDEVICE(MELLANOX, 0x100e) }, /* MT27551 Family */ - { PCI_VDEVICE(MELLANOX, 0x100f) }, /* MT27560 Family */ - { PCI_VDEVICE(MELLANOX, 0x1010) }, /* MT27561 Family */ { 0, } }; diff --git a/trunk/drivers/net/niu.c b/trunk/drivers/net/niu.c index 9fb59d3f9c92..2541321bad82 100644 --- a/trunk/drivers/net/niu.c +++ b/trunk/drivers/net/niu.c @@ -4489,9 +4489,6 @@ static int niu_alloc_channels(struct niu *np) { struct niu_parent *parent = np->parent; int first_rx_channel, first_tx_channel; - int num_rx_rings, num_tx_rings; - struct rx_ring_info *rx_rings; - struct tx_ring_info *tx_rings; int i, port, err; port = np->port; @@ -4501,21 +4498,18 @@ static int niu_alloc_channels(struct niu *np) first_tx_channel += parent->txchan_per_port[i]; } - num_rx_rings = parent->rxchan_per_port[port]; - num_tx_rings = parent->txchan_per_port[port]; + np->num_rx_rings = parent->rxchan_per_port[port]; + np->num_tx_rings = parent->txchan_per_port[port]; - rx_rings = kcalloc(num_rx_rings, sizeof(struct rx_ring_info), - GFP_KERNEL); + netif_set_real_num_rx_queues(np->dev, np->num_rx_rings); + netif_set_real_num_tx_queues(np->dev, np->num_tx_rings); + + np->rx_rings = kcalloc(np->num_rx_rings, sizeof(struct rx_ring_info), + GFP_KERNEL); err = -ENOMEM; - if (!rx_rings) + if (!np->rx_rings) goto out_err; - np->num_rx_rings = num_rx_rings; - smp_wmb(); - np->rx_rings = rx_rings; - - netif_set_real_num_rx_queues(np->dev, num_rx_rings); - for (i = 0; i < np->num_rx_rings; i++) { struct rx_ring_info *rp = &np->rx_rings[i]; @@ -4544,18 +4538,12 @@ static int niu_alloc_channels(struct niu *np) return err; } - tx_rings = kcalloc(num_tx_rings, sizeof(struct tx_ring_info), - GFP_KERNEL); + np->tx_rings = kcalloc(np->num_tx_rings, sizeof(struct tx_ring_info), + GFP_KERNEL); err = -ENOMEM; - if (!tx_rings) + if (!np->tx_rings) goto out_err; - np->num_tx_rings = num_tx_rings; - smp_wmb(); - np->tx_rings = tx_rings; - - netif_set_real_num_tx_queues(np->dev, num_tx_rings); - for (i = 0; i < np->num_tx_rings; i++) { struct tx_ring_info *rp = &np->tx_rings[i]; @@ -6258,17 +6246,11 @@ static void niu_sync_mac_stats(struct niu *np) static void niu_get_rx_stats(struct niu *np) { unsigned long pkts, dropped, errors, bytes; - struct rx_ring_info *rx_rings; int i; pkts = dropped = errors = bytes = 0; - - rx_rings = ACCESS_ONCE(np->rx_rings); - if (!rx_rings) - goto no_rings; - for (i = 0; i < np->num_rx_rings; i++) { - struct rx_ring_info *rp = &rx_rings[i]; + struct rx_ring_info *rp = &np->rx_rings[i]; niu_sync_rx_discard_stats(np, rp, 0); @@ -6277,8 +6259,6 @@ static void niu_get_rx_stats(struct niu *np) dropped += rp->rx_dropped; errors += rp->rx_errors; } - -no_rings: np->dev->stats.rx_packets = pkts; np->dev->stats.rx_bytes = bytes; np->dev->stats.rx_dropped = dropped; @@ -6288,24 +6268,16 @@ static void niu_get_rx_stats(struct niu *np) static void niu_get_tx_stats(struct niu *np) { unsigned long pkts, errors, bytes; - struct tx_ring_info *tx_rings; int i; pkts = errors = bytes = 0; - - tx_rings = ACCESS_ONCE(np->tx_rings); - if (!tx_rings) - goto no_rings; - for (i = 0; i < np->num_tx_rings; i++) { - struct tx_ring_info *rp = &tx_rings[i]; + struct tx_ring_info *rp = &np->tx_rings[i]; pkts += rp->tx_packets; bytes += rp->tx_bytes; errors += rp->tx_errors; } - -no_rings: np->dev->stats.tx_packets = pkts; np->dev->stats.tx_bytes = bytes; np->dev->stats.tx_errors = errors; @@ -6315,10 +6287,9 @@ static struct net_device_stats *niu_get_stats(struct net_device *dev) { struct niu *np = netdev_priv(dev); - if (netif_running(dev)) { - niu_get_rx_stats(np); - niu_get_tx_stats(np); - } + niu_get_rx_stats(np); + niu_get_tx_stats(np); + return &dev->stats; } diff --git a/trunk/drivers/net/pcmcia/axnet_cs.c b/trunk/drivers/net/pcmcia/axnet_cs.c index d3cb77205863..1f42f6ac8551 100644 --- a/trunk/drivers/net/pcmcia/axnet_cs.c +++ b/trunk/drivers/net/pcmcia/axnet_cs.c @@ -1488,10 +1488,12 @@ static void ei_rx_overrun(struct net_device *dev) /* * Wait a full Tx time (1.2ms) + some guard time, NS says 1.6ms total. - * We wait at least 2ms. + * Early datasheets said to poll the reset bit, but now they say that + * it "is not a reliable indicator and subsequently should be ignored." + * We wait at least 10ms. */ - mdelay(2); + mdelay(10); /* * Reset RBCR[01] back to zero as per magic incantation. diff --git a/trunk/drivers/net/r8169.c b/trunk/drivers/net/r8169.c index 59ccf0c5c610..bde7d61f1930 100644 --- a/trunk/drivers/net/r8169.c +++ b/trunk/drivers/net/r8169.c @@ -973,8 +973,7 @@ static void __rtl8169_check_link_status(struct net_device *dev, if (pm) pm_request_resume(&tp->pci_dev->dev); netif_carrier_on(dev); - if (net_ratelimit()) - netif_info(tp, ifup, dev, "link up\n"); + netif_info(tp, ifup, dev, "link up\n"); } else { netif_carrier_off(dev); netif_info(tp, ifdown, dev, "link down\n"); @@ -3758,8 +3757,7 @@ static void rtl_hw_start_8168(struct net_device *dev) RTL_W16(IntrMitigate, 0x5151); /* Work around for RxFIFO overflow. */ - if (tp->mac_version == RTL_GIGA_MAC_VER_11 || - tp->mac_version == RTL_GIGA_MAC_VER_22) { + if (tp->mac_version == RTL_GIGA_MAC_VER_11) { tp->intr_event |= RxFIFOOver | PCSTimeout; tp->intr_event &= ~RxOverflow; } @@ -4641,33 +4639,12 @@ static irqreturn_t rtl8169_interrupt(int irq, void *dev_instance) break; } - if (unlikely(status & RxFIFOOver)) { - switch (tp->mac_version) { - /* Work around for rx fifo overflow */ - case RTL_GIGA_MAC_VER_11: - case RTL_GIGA_MAC_VER_22: - case RTL_GIGA_MAC_VER_26: - netif_stop_queue(dev); - rtl8169_tx_timeout(dev); - goto done; - /* Testers needed. */ - case RTL_GIGA_MAC_VER_17: - case RTL_GIGA_MAC_VER_19: - case RTL_GIGA_MAC_VER_20: - case RTL_GIGA_MAC_VER_21: - case RTL_GIGA_MAC_VER_23: - case RTL_GIGA_MAC_VER_24: - case RTL_GIGA_MAC_VER_27: - case RTL_GIGA_MAC_VER_28: - /* Experimental science. Pktgen proof. */ - case RTL_GIGA_MAC_VER_12: - case RTL_GIGA_MAC_VER_25: - if (status == RxFIFOOver) - goto done; - break; - default: - break; - } + /* Work around for rx fifo overflow */ + if (unlikely(status & RxFIFOOver) && + (tp->mac_version == RTL_GIGA_MAC_VER_11)) { + netif_stop_queue(dev); + rtl8169_tx_timeout(dev); + break; } if (unlikely(status & SYSErr)) { @@ -4703,7 +4680,7 @@ static irqreturn_t rtl8169_interrupt(int irq, void *dev_instance) (status & RxFIFOOver) ? (status | RxOverflow) : status); status = RTL_R16(IntrStatus); } -done: + return IRQ_RETVAL(handled); } diff --git a/trunk/drivers/net/vxge/vxge-config.c b/trunk/drivers/net/vxge/vxge-config.c index 228d4f7a58af..01c05f53e2f9 100644 --- a/trunk/drivers/net/vxge/vxge-config.c +++ b/trunk/drivers/net/vxge/vxge-config.c @@ -3690,7 +3690,7 @@ __vxge_hw_vpath_rts_table_get(struct __vxge_hw_vpath_handle *vp, if (status != VXGE_HW_OK) goto exit; - if ((rts_table != VXGE_HW_RTS_ACCESS_STEER_CTRL_DATA_STRUCT_SEL_DA) && + if ((rts_table != VXGE_HW_RTS_ACCESS_STEER_CTRL_DATA_STRUCT_SEL_DA) || (rts_table != VXGE_HW_RTS_ACS_STEER_CTRL_DATA_STRUCT_SEL_RTH_MULTI_IT)) *data1 = 0; diff --git a/trunk/drivers/net/wireless/ath/ath5k/dma.c b/trunk/drivers/net/wireless/ath/ath5k/dma.c index 21091c26a9a5..0064be7ce5c9 100644 --- a/trunk/drivers/net/wireless/ath/ath5k/dma.c +++ b/trunk/drivers/net/wireless/ath/ath5k/dma.c @@ -838,9 +838,9 @@ int ath5k_hw_dma_stop(struct ath5k_hw *ah) for (i = 0; i < qmax; i++) { err = ath5k_hw_stop_tx_dma(ah, i); /* -EINVAL -> queue inactive */ - if (err && err != -EINVAL) + if (err != -EINVAL) return err; } - return 0; + return err; } diff --git a/trunk/drivers/net/wireless/ath/ath5k/pcu.c b/trunk/drivers/net/wireless/ath/ath5k/pcu.c index a702817daf72..e5f2b96a4c63 100644 --- a/trunk/drivers/net/wireless/ath/ath5k/pcu.c +++ b/trunk/drivers/net/wireless/ath/ath5k/pcu.c @@ -86,7 +86,7 @@ int ath5k_hw_get_frame_duration(struct ath5k_hw *ah, if (!ah->ah_bwmode) { dur = ieee80211_generic_frame_duration(sc->hw, NULL, len, rate); - return le16_to_cpu(dur); + return dur; } bitrate = rate->bitrate; @@ -265,6 +265,8 @@ static inline void ath5k_hw_write_rate_duration(struct ath5k_hw *ah) * what rate we should choose to TX ACKs. */ tx_time = ath5k_hw_get_frame_duration(ah, 10, rate); + tx_time = le16_to_cpu(tx_time); + ath5k_hw_reg_write(ah, tx_time, reg); if (!(rate->flags & IEEE80211_RATE_SHORT_PREAMBLE)) diff --git a/trunk/drivers/net/wireless/ath/ath9k/ar9002_hw.c b/trunk/drivers/net/wireless/ath/ath9k/ar9002_hw.c index f44c84ab5dce..f8a7771faee2 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/ar9002_hw.c +++ b/trunk/drivers/net/wireless/ath/ath9k/ar9002_hw.c @@ -426,8 +426,9 @@ static void ar9002_hw_configpcipowersave(struct ath_hw *ah, } /* WAR for ASPM system hang */ - if (AR_SREV_9285(ah) || AR_SREV_9287(ah)) + if (AR_SREV_9280(ah) || AR_SREV_9285(ah) || AR_SREV_9287(ah)) { val |= (AR_WA_BIT6 | AR_WA_BIT7); + } if (AR_SREV_9285E_20(ah)) val |= AR_WA_BIT23; diff --git a/trunk/drivers/net/wireless/ath/ath9k/htc_drv_init.c b/trunk/drivers/net/wireless/ath/ath9k/htc_drv_init.c index 0352f0994caa..38433f9bfe59 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/htc_drv_init.c +++ b/trunk/drivers/net/wireless/ath/ath9k/htc_drv_init.c @@ -142,6 +142,9 @@ static void ath9k_deinit_priv(struct ath9k_htc_priv *priv) { ath9k_htc_exit_debug(priv->ah); ath9k_hw_deinit(priv->ah); + tasklet_kill(&priv->swba_tasklet); + tasklet_kill(&priv->rx_tasklet); + tasklet_kill(&priv->tx_tasklet); kfree(priv->ah); priv->ah = NULL; } diff --git a/trunk/drivers/net/wireless/ath/ath9k/htc_drv_main.c b/trunk/drivers/net/wireless/ath/ath9k/htc_drv_main.c index 6bb59958f71e..f4d576bc3ccd 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/htc_drv_main.c +++ b/trunk/drivers/net/wireless/ath/ath9k/htc_drv_main.c @@ -1025,6 +1025,12 @@ static void ath9k_htc_stop(struct ieee80211_hw *hw) int ret = 0; u8 cmd_rsp; + /* Cancel all the running timers/work .. */ + cancel_work_sync(&priv->fatal_work); + cancel_work_sync(&priv->ps_work); + cancel_delayed_work_sync(&priv->ath9k_led_blink_work); + ath9k_led_stop_brightness(priv); + mutex_lock(&priv->mutex); if (priv->op_flags & OP_INVALID) { @@ -1038,23 +1044,8 @@ static void ath9k_htc_stop(struct ieee80211_hw *hw) WMI_CMD(WMI_DISABLE_INTR_CMDID); WMI_CMD(WMI_DRAIN_TXQ_ALL_CMDID); WMI_CMD(WMI_STOP_RECV_CMDID); - - tasklet_kill(&priv->swba_tasklet); - tasklet_kill(&priv->rx_tasklet); - tasklet_kill(&priv->tx_tasklet); - skb_queue_purge(&priv->tx_queue); - mutex_unlock(&priv->mutex); - - /* Cancel all the running timers/work .. */ - cancel_work_sync(&priv->fatal_work); - cancel_work_sync(&priv->ps_work); - cancel_delayed_work_sync(&priv->ath9k_led_blink_work); - ath9k_led_stop_brightness(priv); - - mutex_lock(&priv->mutex); - /* Remove monitor interface here */ if (ah->opmode == NL80211_IFTYPE_MONITOR) { if (ath9k_htc_remove_monitor_interface(priv)) diff --git a/trunk/drivers/net/wireless/ath/ath9k/init.c b/trunk/drivers/net/wireless/ath/ath9k/init.c index 087a6a95edd5..767d8b86f1e1 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/init.c +++ b/trunk/drivers/net/wireless/ath/ath9k/init.c @@ -598,6 +598,8 @@ static int ath9k_init_softc(u16 devid, struct ath_softc *sc, u16 subsysid, err_queues: ath9k_hw_deinit(ah); err_hw: + tasklet_kill(&sc->intr_tq); + tasklet_kill(&sc->bcon_tasklet); kfree(ah); sc->sc_ah = NULL; @@ -805,6 +807,9 @@ static void ath9k_deinit_softc(struct ath_softc *sc) ath9k_hw_deinit(sc->sc_ah); + tasklet_kill(&sc->intr_tq); + tasklet_kill(&sc->bcon_tasklet); + kfree(sc->sc_ah); sc->sc_ah = NULL; } @@ -819,8 +824,6 @@ void ath9k_deinit_device(struct ath_softc *sc) wiphy_rfkill_stop_polling(sc->hw->wiphy); ath_deinit_leds(sc); - ath9k_ps_restore(sc); - for (i = 0; i < sc->num_sec_wiphy; i++) { struct ath_wiphy *aphy = sc->sec_wiphy[i]; if (aphy == NULL) diff --git a/trunk/drivers/net/wireless/ath/ath9k/main.c b/trunk/drivers/net/wireless/ath/ath9k/main.c index 9040c2ff1909..c79c97be6cd4 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/main.c +++ b/trunk/drivers/net/wireless/ath/ath9k/main.c @@ -325,8 +325,6 @@ static bool ath_paprd_send_frame(struct ath_softc *sc, struct sk_buff *skb, int { struct ieee80211_hw *hw = sc->hw; struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); - struct ath_hw *ah = sc->sc_ah; - struct ath_common *common = ath9k_hw_common(ah); struct ath_tx_control txctl; int time_left; @@ -344,12 +342,8 @@ static bool ath_paprd_send_frame(struct ath_softc *sc, struct sk_buff *skb, int init_completion(&sc->paprd_complete); sc->paprd_pending = true; txctl.paprd = BIT(chain); - - if (ath_tx_start(hw, skb, &txctl) != 0) { - ath_dbg(common, ATH_DBG_XMIT, "PAPRD TX failed\n"); - dev_kfree_skb_any(skb); + if (ath_tx_start(hw, skb, &txctl) != 0) return false; - } time_left = wait_for_completion_timeout(&sc->paprd_complete, msecs_to_jiffies(ATH_PAPRD_TIMEOUT)); @@ -959,6 +953,8 @@ void ath_radio_disable(struct ath_softc *sc, struct ieee80211_hw *hw) spin_unlock_bh(&sc->sc_pcu_lock); ath9k_ps_restore(sc); + + ath9k_setpower(sc, ATH9K_PM_FULL_SLEEP); } int ath_reset(struct ath_softc *sc, bool retry_tx) @@ -1313,9 +1309,6 @@ static void ath9k_stop(struct ieee80211_hw *hw) spin_lock_bh(&sc->sc_pcu_lock); - /* prevent tasklets to enable interrupts once we disable them */ - ah->imask &= ~ATH9K_INT_GLOBAL; - /* make sure h/w will not generate any interrupt * before setting the invalid flag. */ ath9k_hw_disable_interrupts(ah); @@ -1333,12 +1326,6 @@ static void ath9k_stop(struct ieee80211_hw *hw) spin_unlock_bh(&sc->sc_pcu_lock); - /* we can now sync irq and kill any running tasklets, since we already - * disabled interrupts and not holding a spin lock */ - synchronize_irq(sc->irq); - tasklet_kill(&sc->intr_tq); - tasklet_kill(&sc->bcon_tasklet); - ath9k_ps_restore(sc); sc->ps_idle = true; diff --git a/trunk/drivers/net/wireless/rtlwifi/efuse.c b/trunk/drivers/net/wireless/rtlwifi/efuse.c index 62876cd5c41a..b8433f3a9bc2 100644 --- a/trunk/drivers/net/wireless/rtlwifi/efuse.c +++ b/trunk/drivers/net/wireless/rtlwifi/efuse.c @@ -726,9 +726,9 @@ static int efuse_pg_packet_read(struct ieee80211_hw *hw, u8 offset, u8 *data) } static void efuse_write_data_case1(struct ieee80211_hw *hw, u16 *efuse_addr, - u8 efuse_data, u8 offset, int *bcontinual, - u8 *write_state, struct pgpkt_struct *target_pkt, - int *repeat_times, int *bresult, u8 word_en) + u8 efuse_data, u8 offset, int *bcontinual, + u8 *write_state, struct pgpkt_struct target_pkt, + int *repeat_times, int *bresult, u8 word_en) { struct rtl_priv *rtlpriv = rtl_priv(hw); struct pgpkt_struct tmp_pkt; @@ -744,8 +744,8 @@ static void efuse_write_data_case1(struct ieee80211_hw *hw, u16 *efuse_addr, tmp_pkt.word_en = tmp_header & 0x0F; tmp_word_cnts = efuse_calculate_word_cnts(tmp_pkt.word_en); - if (tmp_pkt.offset != target_pkt->offset) { - *efuse_addr = *efuse_addr + (tmp_word_cnts * 2) + 1; + if (tmp_pkt.offset != target_pkt.offset) { + efuse_addr = efuse_addr + (tmp_word_cnts * 2) + 1; *write_state = PG_STATE_HEADER; } else { for (tmpindex = 0; tmpindex < (tmp_word_cnts * 2); tmpindex++) { @@ -756,23 +756,23 @@ static void efuse_write_data_case1(struct ieee80211_hw *hw, u16 *efuse_addr, } if (bdataempty == false) { - *efuse_addr = *efuse_addr + (tmp_word_cnts * 2) + 1; + efuse_addr = efuse_addr + (tmp_word_cnts * 2) + 1; *write_state = PG_STATE_HEADER; } else { match_word_en = 0x0F; - if (!((target_pkt->word_en & BIT(0)) | + if (!((target_pkt.word_en & BIT(0)) | (tmp_pkt.word_en & BIT(0)))) match_word_en &= (~BIT(0)); - if (!((target_pkt->word_en & BIT(1)) | + if (!((target_pkt.word_en & BIT(1)) | (tmp_pkt.word_en & BIT(1)))) match_word_en &= (~BIT(1)); - if (!((target_pkt->word_en & BIT(2)) | + if (!((target_pkt.word_en & BIT(2)) | (tmp_pkt.word_en & BIT(2)))) match_word_en &= (~BIT(2)); - if (!((target_pkt->word_en & BIT(3)) | + if (!((target_pkt.word_en & BIT(3)) | (tmp_pkt.word_en & BIT(3)))) match_word_en &= (~BIT(3)); @@ -780,7 +780,7 @@ static void efuse_write_data_case1(struct ieee80211_hw *hw, u16 *efuse_addr, badworden = efuse_word_enable_data_write( hw, *efuse_addr + 1, tmp_pkt.word_en, - target_pkt->data); + target_pkt.data); if (0x0F != (badworden & 0x0F)) { u8 reorg_offset = offset; @@ -791,26 +791,26 @@ static void efuse_write_data_case1(struct ieee80211_hw *hw, u16 *efuse_addr, } tmp_word_en = 0x0F; - if ((target_pkt->word_en & BIT(0)) ^ + if ((target_pkt.word_en & BIT(0)) ^ (match_word_en & BIT(0))) tmp_word_en &= (~BIT(0)); - if ((target_pkt->word_en & BIT(1)) ^ + if ((target_pkt.word_en & BIT(1)) ^ (match_word_en & BIT(1))) tmp_word_en &= (~BIT(1)); - if ((target_pkt->word_en & BIT(2)) ^ + if ((target_pkt.word_en & BIT(2)) ^ (match_word_en & BIT(2))) tmp_word_en &= (~BIT(2)); - if ((target_pkt->word_en & BIT(3)) ^ + if ((target_pkt.word_en & BIT(3)) ^ (match_word_en & BIT(3))) tmp_word_en &= (~BIT(3)); if ((tmp_word_en & 0x0F) != 0x0F) { *efuse_addr = efuse_get_current_size(hw); - target_pkt->offset = offset; - target_pkt->word_en = tmp_word_en; + target_pkt.offset = offset; + target_pkt.word_en = tmp_word_en; } else *bcontinual = false; *write_state = PG_STATE_HEADER; @@ -821,8 +821,8 @@ static void efuse_write_data_case1(struct ieee80211_hw *hw, u16 *efuse_addr, } } else { *efuse_addr += (2 * tmp_word_cnts) + 1; - target_pkt->offset = offset; - target_pkt->word_en = word_en; + target_pkt.offset = offset; + target_pkt.word_en = word_en; *write_state = PG_STATE_HEADER; } } @@ -938,7 +938,7 @@ static int efuse_pg_packet_write(struct ieee80211_hw *hw, efuse_write_data_case1(hw, &efuse_addr, efuse_data, offset, &bcontinual, - &write_state, &target_pkt, + &write_state, target_pkt, &repeat_times, &bresult, word_en); else diff --git a/trunk/drivers/net/wireless/wl12xx/spi.c b/trunk/drivers/net/wireless/wl12xx/spi.c index 7145ea543783..46714910f98c 100644 --- a/trunk/drivers/net/wireless/wl12xx/spi.c +++ b/trunk/drivers/net/wireless/wl12xx/spi.c @@ -110,8 +110,9 @@ static void wl1271_spi_reset(struct wl1271 *wl) spi_message_add_tail(&t, &m); spi_sync(wl_to_spi(wl), &m); - wl1271_dump(DEBUG_SPI, "spi reset -> ", cmd, WSPI_INIT_CMD_LEN); kfree(cmd); + + wl1271_dump(DEBUG_SPI, "spi reset -> ", cmd, WSPI_INIT_CMD_LEN); } static void wl1271_spi_init(struct wl1271 *wl) diff --git a/trunk/drivers/net/xen-netfront.c b/trunk/drivers/net/xen-netfront.c index da1f12120346..546de5749824 100644 --- a/trunk/drivers/net/xen-netfront.c +++ b/trunk/drivers/net/xen-netfront.c @@ -120,9 +120,6 @@ struct netfront_info { unsigned long rx_pfn_array[NET_RX_RING_SIZE]; struct multicall_entry rx_mcl[NET_RX_RING_SIZE+1]; struct mmu_update rx_mmu[NET_RX_RING_SIZE]; - - /* Statistics */ - int rx_gso_checksum_fixup; }; struct netfront_rx_info { @@ -773,29 +770,11 @@ static RING_IDX xennet_fill_frags(struct netfront_info *np, return cons; } -static int checksum_setup(struct net_device *dev, struct sk_buff *skb) +static int skb_checksum_setup(struct sk_buff *skb) { struct iphdr *iph; unsigned char *th; int err = -EPROTO; - int recalculate_partial_csum = 0; - - /* - * A GSO SKB must be CHECKSUM_PARTIAL. However some buggy - * peers can fail to set NETRXF_csum_blank when sending a GSO - * frame. In this case force the SKB to CHECKSUM_PARTIAL and - * recalculate the partial checksum. - */ - if (skb->ip_summed != CHECKSUM_PARTIAL && skb_is_gso(skb)) { - struct netfront_info *np = netdev_priv(dev); - np->rx_gso_checksum_fixup++; - skb->ip_summed = CHECKSUM_PARTIAL; - recalculate_partial_csum = 1; - } - - /* A non-CHECKSUM_PARTIAL SKB does not require setup. */ - if (skb->ip_summed != CHECKSUM_PARTIAL) - return 0; if (skb->protocol != htons(ETH_P_IP)) goto out; @@ -809,23 +788,9 @@ static int checksum_setup(struct net_device *dev, struct sk_buff *skb) switch (iph->protocol) { case IPPROTO_TCP: skb->csum_offset = offsetof(struct tcphdr, check); - - if (recalculate_partial_csum) { - struct tcphdr *tcph = (struct tcphdr *)th; - tcph->check = ~csum_tcpudp_magic(iph->saddr, iph->daddr, - skb->len - iph->ihl*4, - IPPROTO_TCP, 0); - } break; case IPPROTO_UDP: skb->csum_offset = offsetof(struct udphdr, check); - - if (recalculate_partial_csum) { - struct udphdr *udph = (struct udphdr *)th; - udph->check = ~csum_tcpudp_magic(iph->saddr, iph->daddr, - skb->len - iph->ihl*4, - IPPROTO_UDP, 0); - } break; default: if (net_ratelimit()) @@ -864,11 +829,13 @@ static int handle_incoming_queue(struct net_device *dev, /* Ethernet work: Delayed to here as it peeks the header. */ skb->protocol = eth_type_trans(skb, dev); - if (checksum_setup(dev, skb)) { - kfree_skb(skb); - packets_dropped++; - dev->stats.rx_errors++; - continue; + if (skb->ip_summed == CHECKSUM_PARTIAL) { + if (skb_checksum_setup(skb)) { + kfree_skb(skb); + packets_dropped++; + dev->stats.rx_errors++; + continue; + } } dev->stats.rx_packets++; @@ -1665,59 +1632,12 @@ static void netback_changed(struct xenbus_device *dev, } } -static const struct xennet_stat { - char name[ETH_GSTRING_LEN]; - u16 offset; -} xennet_stats[] = { - { - "rx_gso_checksum_fixup", - offsetof(struct netfront_info, rx_gso_checksum_fixup) - }, -}; - -static int xennet_get_sset_count(struct net_device *dev, int string_set) -{ - switch (string_set) { - case ETH_SS_STATS: - return ARRAY_SIZE(xennet_stats); - default: - return -EINVAL; - } -} - -static void xennet_get_ethtool_stats(struct net_device *dev, - struct ethtool_stats *stats, u64 * data) -{ - void *np = netdev_priv(dev); - int i; - - for (i = 0; i < ARRAY_SIZE(xennet_stats); i++) - data[i] = *(int *)(np + xennet_stats[i].offset); -} - -static void xennet_get_strings(struct net_device *dev, u32 stringset, u8 * data) -{ - int i; - - switch (stringset) { - case ETH_SS_STATS: - for (i = 0; i < ARRAY_SIZE(xennet_stats); i++) - memcpy(data + i * ETH_GSTRING_LEN, - xennet_stats[i].name, ETH_GSTRING_LEN); - break; - } -} - static const struct ethtool_ops xennet_ethtool_ops = { .set_tx_csum = ethtool_op_set_tx_csum, .set_sg = xennet_set_sg, .set_tso = xennet_set_tso, .get_link = ethtool_op_get_link, - - .get_sset_count = xennet_get_sset_count, - .get_ethtool_stats = xennet_get_ethtool_stats, - .get_strings = xennet_get_strings, }; #ifdef CONFIG_SYSFS diff --git a/trunk/drivers/rtc/class.c b/trunk/drivers/rtc/class.c index c404b61386bf..9583cbcc6b79 100644 --- a/trunk/drivers/rtc/class.c +++ b/trunk/drivers/rtc/class.c @@ -143,7 +143,6 @@ struct rtc_device *rtc_device_register(const char *name, struct device *dev, rtc->id = id; rtc->ops = ops; rtc->owner = owner; - rtc->irq_freq = 1; rtc->max_user_freq = 64; rtc->dev.parent = dev; rtc->dev.class = rtc_class; diff --git a/trunk/drivers/rtc/interface.c b/trunk/drivers/rtc/interface.c index a0c01967244d..925006d33109 100644 --- a/trunk/drivers/rtc/interface.c +++ b/trunk/drivers/rtc/interface.c @@ -464,9 +464,6 @@ int rtc_irq_set_freq(struct rtc_device *rtc, struct rtc_task *task, int freq) int err = 0; unsigned long flags; - if (freq <= 0) - return -EINVAL; - spin_lock_irqsave(&rtc->irq_task_lock, flags); if (rtc->irq_task != NULL && task == NULL) err = -EBUSY; diff --git a/trunk/drivers/s390/net/netiucv.c b/trunk/drivers/s390/net/netiucv.c index b6a6356d09b3..65ebee0a3266 100644 --- a/trunk/drivers/s390/net/netiucv.c +++ b/trunk/drivers/s390/net/netiucv.c @@ -565,7 +565,7 @@ static int netiucv_callback_connreq(struct iucv_path *path, struct iucv_event ev; int rc; - if (memcmp(iucvMagic, ipuser, 16)) + if (memcmp(iucvMagic, ipuser, sizeof(ipuser))) /* ipuser must match iucvMagic. */ return -EINVAL; rc = -EINVAL; diff --git a/trunk/drivers/s390/net/qeth_core_main.c b/trunk/drivers/s390/net/qeth_core_main.c index 019ae58ab913..29f848bfc12f 100644 --- a/trunk/drivers/s390/net/qeth_core_main.c +++ b/trunk/drivers/s390/net/qeth_core_main.c @@ -988,30 +988,16 @@ static void qeth_get_channel_path_desc(struct qeth_card *card) chp_dsc = (struct channelPath_dsc *)ccw_device_get_chp_desc(ccwdev, 0); if (chp_dsc != NULL) { /* CHPP field bit 6 == 1 -> single queue */ - if ((chp_dsc->chpp & 0x02) == 0x02) { - if ((atomic_read(&card->qdio.state) != - QETH_QDIO_UNINITIALIZED) && - (card->qdio.no_out_queues == 4)) - /* change from 4 to 1 outbound queues */ - qeth_free_qdio_buffers(card); + if ((chp_dsc->chpp & 0x02) == 0x02) card->qdio.no_out_queues = 1; - if (card->qdio.default_out_queue != 0) - dev_info(&card->gdev->dev, - "Priority Queueing not supported\n"); - card->qdio.default_out_queue = 0; - } else { - if ((atomic_read(&card->qdio.state) != - QETH_QDIO_UNINITIALIZED) && - (card->qdio.no_out_queues == 1)) { - /* change from 1 to 4 outbound queues */ - qeth_free_qdio_buffers(card); - card->qdio.default_out_queue = 2; - } - card->qdio.no_out_queues = 4; - } card->info.func_level = 0x4100 + chp_dsc->desc; kfree(chp_dsc); } + if (card->qdio.no_out_queues == 1) { + card->qdio.default_out_queue = 0; + dev_info(&card->gdev->dev, + "Priority Queueing not supported\n"); + } QETH_DBF_TEXT_(SETUP, 2, "nr:%x", card->qdio.no_out_queues); QETH_DBF_TEXT_(SETUP, 2, "lvl:%02x", card->info.func_level); return; @@ -1846,6 +1832,33 @@ static inline int qeth_get_initial_mtu_for_card(struct qeth_card *card) } } +static inline int qeth_get_max_mtu_for_card(int cardtype) +{ + switch (cardtype) { + + case QETH_CARD_TYPE_UNKNOWN: + case QETH_CARD_TYPE_OSD: + case QETH_CARD_TYPE_OSN: + case QETH_CARD_TYPE_OSM: + case QETH_CARD_TYPE_OSX: + return 61440; + case QETH_CARD_TYPE_IQD: + return 57344; + default: + return 1500; + } +} + +static inline int qeth_get_mtu_out_of_mpc(int cardtype) +{ + switch (cardtype) { + case QETH_CARD_TYPE_IQD: + return 1; + default: + return 0; + } +} + static inline int qeth_get_mtu_outof_framesize(int framesize) { switch (framesize) { @@ -1868,9 +1881,10 @@ static inline int qeth_mtu_is_valid(struct qeth_card *card, int mtu) case QETH_CARD_TYPE_OSD: case QETH_CARD_TYPE_OSM: case QETH_CARD_TYPE_OSX: + return ((mtu >= 576) && (mtu <= 61440)); case QETH_CARD_TYPE_IQD: return ((mtu >= 576) && - (mtu <= card->info.max_mtu)); + (mtu <= card->info.max_mtu + 4096 - 32)); case QETH_CARD_TYPE_OSN: case QETH_CARD_TYPE_UNKNOWN: default: @@ -1893,7 +1907,7 @@ static int qeth_ulp_enable_cb(struct qeth_card *card, struct qeth_reply *reply, memcpy(&card->token.ulp_filter_r, QETH_ULP_ENABLE_RESP_FILTER_TOKEN(iob->data), QETH_MPC_TOKEN_LENGTH); - if (card->info.type == QETH_CARD_TYPE_IQD) { + if (qeth_get_mtu_out_of_mpc(card->info.type)) { memcpy(&framesize, QETH_ULP_ENABLE_RESP_MAX_MTU(iob->data), 2); mtu = qeth_get_mtu_outof_framesize(framesize); if (!mtu) { @@ -1901,21 +1915,12 @@ static int qeth_ulp_enable_cb(struct qeth_card *card, struct qeth_reply *reply, QETH_DBF_TEXT_(SETUP, 2, " rc%d", iob->rc); return 0; } - if (card->info.initial_mtu && (card->info.initial_mtu != mtu)) { - /* frame size has changed */ - if (card->dev && - ((card->dev->mtu == card->info.initial_mtu) || - (card->dev->mtu > mtu))) - card->dev->mtu = mtu; - qeth_free_qdio_buffers(card); - } - card->info.initial_mtu = mtu; card->info.max_mtu = mtu; + card->info.initial_mtu = mtu; card->qdio.in_buf_size = mtu + 2 * PAGE_SIZE; } else { card->info.initial_mtu = qeth_get_initial_mtu_for_card(card); - card->info.max_mtu = *(__u16 *)QETH_ULP_ENABLE_RESP_MAX_MTU( - iob->data); + card->info.max_mtu = qeth_get_max_mtu_for_card(card->info.type); card->qdio.in_buf_size = QETH_IN_BUF_SIZE_DEFAULT; } @@ -3770,47 +3775,6 @@ static inline int qeth_get_qdio_q_format(struct qeth_card *card) } } -static void qeth_determine_capabilities(struct qeth_card *card) -{ - int rc; - int length; - char *prcd; - struct ccw_device *ddev; - int ddev_offline = 0; - - QETH_DBF_TEXT(SETUP, 2, "detcapab"); - ddev = CARD_DDEV(card); - if (!ddev->online) { - ddev_offline = 1; - rc = ccw_device_set_online(ddev); - if (rc) { - QETH_DBF_TEXT_(SETUP, 2, "3err%d", rc); - goto out; - } - } - - rc = qeth_read_conf_data(card, (void **) &prcd, &length); - if (rc) { - QETH_DBF_MESSAGE(2, "%s qeth_read_conf_data returned %i\n", - dev_name(&card->gdev->dev), rc); - QETH_DBF_TEXT_(SETUP, 2, "5err%d", rc); - goto out_offline; - } - qeth_configure_unitaddr(card, prcd); - qeth_configure_blkt_default(card, prcd); - kfree(prcd); - - rc = qdio_get_ssqd_desc(ddev, &card->ssqd); - if (rc) - QETH_DBF_TEXT_(SETUP, 2, "6err%d", rc); - -out_offline: - if (ddev_offline == 1) - ccw_device_set_offline(ddev); -out: - return; -} - static int qeth_qdio_establish(struct qeth_card *card) { struct qdio_initialize init_data; @@ -3941,7 +3905,6 @@ int qeth_core_hardsetup_card(struct qeth_card *card) QETH_DBF_TEXT(SETUP, 2, "hrdsetup"); atomic_set(&card->force_alloc_skb, 0); - qeth_get_channel_path_desc(card); retry: if (retries) QETH_DBF_MESSAGE(2, "%s Retrying to do IDX activates.\n", @@ -3970,7 +3933,6 @@ int qeth_core_hardsetup_card(struct qeth_card *card) else goto retry; } - qeth_determine_capabilities(card); qeth_init_tokens(card); qeth_init_func_level(card); rc = qeth_idx_activate_channel(&card->read, qeth_idx_read_cb); @@ -4240,6 +4202,41 @@ void qeth_core_free_discipline(struct qeth_card *card) card->discipline.ccwgdriver = NULL; } +static void qeth_determine_capabilities(struct qeth_card *card) +{ + int rc; + int length; + char *prcd; + + QETH_DBF_TEXT(SETUP, 2, "detcapab"); + rc = ccw_device_set_online(CARD_DDEV(card)); + if (rc) { + QETH_DBF_TEXT_(SETUP, 2, "3err%d", rc); + goto out; + } + + + rc = qeth_read_conf_data(card, (void **) &prcd, &length); + if (rc) { + QETH_DBF_MESSAGE(2, "%s qeth_read_conf_data returned %i\n", + dev_name(&card->gdev->dev), rc); + QETH_DBF_TEXT_(SETUP, 2, "5err%d", rc); + goto out_offline; + } + qeth_configure_unitaddr(card, prcd); + qeth_configure_blkt_default(card, prcd); + kfree(prcd); + + rc = qdio_get_ssqd_desc(CARD_DDEV(card), &card->ssqd); + if (rc) + QETH_DBF_TEXT_(SETUP, 2, "6err%d", rc); + +out_offline: + ccw_device_set_offline(CARD_DDEV(card)); +out: + return; +} + static int qeth_core_probe_device(struct ccwgroup_device *gdev) { struct qeth_card *card; diff --git a/trunk/drivers/s390/net/qeth_l2_main.c b/trunk/drivers/s390/net/qeth_l2_main.c index ada0fe782373..2ac8f6aff5a4 100644 --- a/trunk/drivers/s390/net/qeth_l2_main.c +++ b/trunk/drivers/s390/net/qeth_l2_main.c @@ -573,13 +573,13 @@ static int qeth_l2_send_setmac_cb(struct qeth_card *card, case IPA_RC_L2_DUP_LAYER3_MAC: dev_warn(&card->gdev->dev, "MAC address %pM already exists\n", - cmd->data.setdelmac.mac); + card->dev->dev_addr); break; case IPA_RC_L2_MAC_NOT_AUTH_BY_HYP: case IPA_RC_L2_MAC_NOT_AUTH_BY_ADP: dev_warn(&card->gdev->dev, "MAC address %pM is not authorized\n", - cmd->data.setdelmac.mac); + card->dev->dev_addr); break; default: break; diff --git a/trunk/drivers/s390/net/smsgiucv.c b/trunk/drivers/s390/net/smsgiucv.c index 207b7d742443..65e1cf104943 100644 --- a/trunk/drivers/s390/net/smsgiucv.c +++ b/trunk/drivers/s390/net/smsgiucv.c @@ -60,7 +60,7 @@ static struct iucv_handler smsg_handler = { static int smsg_path_pending(struct iucv_path *path, u8 ipvmid[8], u8 ipuser[16]) { - if (strncmp(ipvmid, "*MSG ", 8) != 0) + if (strncmp(ipvmid, "*MSG ", sizeof(ipvmid)) != 0) return -EINVAL; /* Path pending from *MSG. */ return iucv_path_accept(path, &smsg_handler, "SMSGIUCV ", NULL); diff --git a/trunk/drivers/scsi/arcmsr/arcmsr.h b/trunk/drivers/scsi/arcmsr/arcmsr.h index 77b26f5b9c33..475c31ae985c 100644 --- a/trunk/drivers/scsi/arcmsr/arcmsr.h +++ b/trunk/drivers/scsi/arcmsr/arcmsr.h @@ -2,7 +2,7 @@ ******************************************************************************* ** O.S : Linux ** FILE NAME : arcmsr.h -** BY : Nick Cheng +** BY : Erich Chen ** Description: SCSI RAID Device Driver for ** ARECA RAID Host adapter ******************************************************************************* @@ -46,12 +46,8 @@ struct device_attribute; /*The limit of outstanding scsi command that firmware can handle*/ #define ARCMSR_MAX_OUTSTANDING_CMD 256 -#ifdef CONFIG_XEN - #define ARCMSR_MAX_FREECCB_NUM 160 -#else - #define ARCMSR_MAX_FREECCB_NUM 320 -#endif -#define ARCMSR_DRIVER_VERSION "Driver Version 1.20.00.15 2010/08/05" +#define ARCMSR_MAX_FREECCB_NUM 320 +#define ARCMSR_DRIVER_VERSION "Driver Version 1.20.00.15 2010/02/02" #define ARCMSR_SCSI_INITIATOR_ID 255 #define ARCMSR_MAX_XFER_SECTORS 512 #define ARCMSR_MAX_XFER_SECTORS_B 4096 @@ -64,6 +60,7 @@ struct device_attribute; #define ARCMSR_MAX_HBB_POSTQUEUE 264 #define ARCMSR_MAX_XFER_LEN 0x26000 /* 152K */ #define ARCMSR_CDB_SG_PAGE_LENGTH 256 +#define SCSI_CMD_ARECA_SPECIFIC 0xE1 #ifndef PCI_DEVICE_ID_ARECA_1880 #define PCI_DEVICE_ID_ARECA_1880 0x1880 #endif diff --git a/trunk/drivers/scsi/arcmsr/arcmsr_attr.c b/trunk/drivers/scsi/arcmsr/arcmsr_attr.c index acdae33de521..a4e04c50c436 100644 --- a/trunk/drivers/scsi/arcmsr/arcmsr_attr.c +++ b/trunk/drivers/scsi/arcmsr/arcmsr_attr.c @@ -2,7 +2,7 @@ ******************************************************************************* ** O.S : Linux ** FILE NAME : arcmsr_attr.c -** BY : Nick Cheng +** BY : Erich Chen ** Description: attributes exported to sysfs and device host ******************************************************************************* ** Copyright (C) 2002 - 2005, Areca Technology Corporation All rights reserved diff --git a/trunk/drivers/scsi/arcmsr/arcmsr_hba.c b/trunk/drivers/scsi/arcmsr/arcmsr_hba.c index 984bd527c6c9..1cadcd6b7da6 100644 --- a/trunk/drivers/scsi/arcmsr/arcmsr_hba.c +++ b/trunk/drivers/scsi/arcmsr/arcmsr_hba.c @@ -2,7 +2,7 @@ ******************************************************************************* ** O.S : Linux ** FILE NAME : arcmsr_hba.c -** BY : Nick Cheng +** BY : Erich Chen ** Description: SCSI RAID Device Driver for ** ARECA RAID Host adapter ******************************************************************************* @@ -76,7 +76,7 @@ MODULE_DESCRIPTION("ARECA (ARC11xx/12xx/16xx/1880) SATA/SAS RAID Host Bus Adapte MODULE_LICENSE("Dual BSD/GPL"); MODULE_VERSION(ARCMSR_DRIVER_VERSION); static int sleeptime = 10; -static int retrycount = 12; +static int retrycount = 30; wait_queue_head_t wait_q; static int arcmsr_iop_message_xfer(struct AdapterControlBlock *acb, struct scsi_cmnd *cmd); @@ -187,6 +187,7 @@ int arcmsr_sleep_for_bus_reset(struct scsi_cmnd *cmd) if (isleep > 0) { msleep(isleep*1000); } + printk(KERN_NOTICE "wake-up\n"); return 0; } @@ -920,6 +921,7 @@ static void arcmsr_report_ccb_state(struct AdapterControlBlock *acb, } static void arcmsr_drain_donequeue(struct AdapterControlBlock *acb, struct CommandControlBlock *pCCB, bool error) + { int id, lun; if ((pCCB->acb != acb) || (pCCB->startdone != ARCMSR_CCB_START)) { @@ -946,7 +948,7 @@ static void arcmsr_drain_donequeue(struct AdapterControlBlock *acb, struct Comma , pCCB->startdone , atomic_read(&acb->ccboutstandingcount)); return; - } + } arcmsr_report_ccb_state(acb, pCCB, error); } @@ -979,7 +981,7 @@ static void arcmsr_done4abort_postqueue(struct AdapterControlBlock *acb) case ACB_ADAPTER_TYPE_B: { struct MessageUnit_B *reg = acb->pmuB; /*clear all outbound posted Q*/ - writel(ARCMSR_DOORBELL_INT_CLEAR_PATTERN, reg->iop2drv_doorbell); /* clear doorbell interrupt */ + writel(ARCMSR_DOORBELL_INT_CLEAR_PATTERN, ®->iop2drv_doorbell); /* clear doorbell interrupt */ for (i = 0; i < ARCMSR_MAX_HBB_POSTQUEUE; i++) { if ((flag_ccb = readl(®->done_qbuffer[i])) != 0) { writel(0, ®->done_qbuffer[i]); @@ -1509,6 +1511,7 @@ static void arcmsr_hba_postqueue_isr(struct AdapterControlBlock *acb) arcmsr_drain_donequeue(acb, pCCB, error); } } + static void arcmsr_hbb_postqueue_isr(struct AdapterControlBlock *acb) { uint32_t index; @@ -2103,6 +2106,10 @@ static int arcmsr_queue_command_lck(struct scsi_cmnd *cmd, if (atomic_read(&acb->ccboutstandingcount) >= ARCMSR_MAX_OUTSTANDING_CMD) return SCSI_MLQUEUE_HOST_BUSY; + if ((scsicmd == SCSI_CMD_ARECA_SPECIFIC)) { + printk(KERN_NOTICE "Receiveing SCSI_CMD_ARECA_SPECIFIC command..\n"); + return 0; + } ccb = arcmsr_get_freeccb(acb); if (!ccb) return SCSI_MLQUEUE_HOST_BUSY; @@ -2386,7 +2393,6 @@ static int arcmsr_polling_hbb_ccbdone(struct AdapterControlBlock *acb, int index, rtn; bool error; polling_hbb_ccb_retry: - poll_count++; /* clear doorbell interrupt */ writel(ARCMSR_DOORBELL_INT_CLEAR_PATTERN, reg->iop2drv_doorbell); @@ -2657,7 +2663,6 @@ static void arcmsr_request_hba_device_map(struct AdapterControlBlock *acb) { struct MessageUnit_A __iomem *reg = acb->pmuA; if (unlikely(atomic_read(&acb->rq_map_token) == 0) || ((acb->acb_flags & ACB_F_BUS_RESET) != 0 ) || ((acb->acb_flags & ACB_F_ABORT) != 0 )){ - mod_timer(&acb->eternal_timer, jiffies + msecs_to_jiffies(6 * HZ)); return; } else { acb->fw_flag = FW_NORMAL; @@ -2665,10 +2670,8 @@ static void arcmsr_request_hba_device_map(struct AdapterControlBlock *acb) atomic_set(&acb->rq_map_token, 16); } atomic_set(&acb->ante_token_value, atomic_read(&acb->rq_map_token)); - if (atomic_dec_and_test(&acb->rq_map_token)) { - mod_timer(&acb->eternal_timer, jiffies + msecs_to_jiffies(6 * HZ)); + if (atomic_dec_and_test(&acb->rq_map_token)) return; - } writel(ARCMSR_INBOUND_MESG0_GET_CONFIG, ®->inbound_msgaddr0); mod_timer(&acb->eternal_timer, jiffies + msecs_to_jiffies(6 * HZ)); } @@ -2679,18 +2682,15 @@ static void arcmsr_request_hbb_device_map(struct AdapterControlBlock *acb) { struct MessageUnit_B __iomem *reg = acb->pmuB; if (unlikely(atomic_read(&acb->rq_map_token) == 0) || ((acb->acb_flags & ACB_F_BUS_RESET) != 0 ) || ((acb->acb_flags & ACB_F_ABORT) != 0 )){ - mod_timer(&acb->eternal_timer, jiffies + msecs_to_jiffies(6 * HZ)); return; } else { acb->fw_flag = FW_NORMAL; if (atomic_read(&acb->ante_token_value) == atomic_read(&acb->rq_map_token)) { - atomic_set(&acb->rq_map_token, 16); + atomic_set(&acb->rq_map_token,16); } atomic_set(&acb->ante_token_value, atomic_read(&acb->rq_map_token)); - if (atomic_dec_and_test(&acb->rq_map_token)) { - mod_timer(&acb->eternal_timer, jiffies + msecs_to_jiffies(6 * HZ)); + if(atomic_dec_and_test(&acb->rq_map_token)) return; - } writel(ARCMSR_MESSAGE_GET_CONFIG, reg->drv2iop_doorbell); mod_timer(&acb->eternal_timer, jiffies + msecs_to_jiffies(6 * HZ)); } @@ -2701,7 +2701,6 @@ static void arcmsr_request_hbc_device_map(struct AdapterControlBlock *acb) { struct MessageUnit_C __iomem *reg = acb->pmuC; if (unlikely(atomic_read(&acb->rq_map_token) == 0) || ((acb->acb_flags & ACB_F_BUS_RESET) != 0) || ((acb->acb_flags & ACB_F_ABORT) != 0)) { - mod_timer(&acb->eternal_timer, jiffies + msecs_to_jiffies(6 * HZ)); return; } else { acb->fw_flag = FW_NORMAL; @@ -2709,10 +2708,8 @@ static void arcmsr_request_hbc_device_map(struct AdapterControlBlock *acb) atomic_set(&acb->rq_map_token, 16); } atomic_set(&acb->ante_token_value, atomic_read(&acb->rq_map_token)); - if (atomic_dec_and_test(&acb->rq_map_token)) { - mod_timer(&acb->eternal_timer, jiffies + msecs_to_jiffies(6 * HZ)); + if (atomic_dec_and_test(&acb->rq_map_token)) return; - } writel(ARCMSR_INBOUND_MESG0_GET_CONFIG, ®->inbound_msgaddr0); writel(ARCMSR_HBCMU_DRV2IOP_MESSAGE_CMD_DONE, ®->inbound_doorbell); mod_timer(&acb->eternal_timer, jiffies + msecs_to_jiffies(6 * HZ)); @@ -2900,8 +2897,6 @@ static uint8_t arcmsr_iop_reset(struct AdapterControlBlock *acb) uint32_t intmask_org; uint8_t rtnval = 0x00; int i = 0; - unsigned long flags; - if (atomic_read(&acb->ccboutstandingcount) != 0) { /* disable all outbound interrupt */ intmask_org = arcmsr_disable_outbound_ints(acb); @@ -2912,12 +2907,7 @@ static uint8_t arcmsr_iop_reset(struct AdapterControlBlock *acb) for (i = 0; i < ARCMSR_MAX_FREECCB_NUM; i++) { ccb = acb->pccb_pool[i]; if (ccb->startdone == ARCMSR_CCB_START) { - scsi_dma_unmap(ccb->pcmd); - ccb->startdone = ARCMSR_CCB_DONE; - ccb->ccb_flags = 0; - spin_lock_irqsave(&acb->ccblist_lock, flags); - list_add_tail(&ccb->list, &acb->ccb_free_list); - spin_unlock_irqrestore(&acb->ccblist_lock, flags); + arcmsr_ccb_complete(ccb); } } atomic_set(&acb->ccboutstandingcount, 0); @@ -2930,7 +2920,8 @@ static uint8_t arcmsr_iop_reset(struct AdapterControlBlock *acb) static int arcmsr_bus_reset(struct scsi_cmnd *cmd) { - struct AdapterControlBlock *acb; + struct AdapterControlBlock *acb = + (struct AdapterControlBlock *)cmd->device->host->hostdata; uint32_t intmask_org, outbound_doorbell; int retry_count = 0; int rtn = FAILED; @@ -2980,16 +2971,31 @@ static int arcmsr_bus_reset(struct scsi_cmnd *cmd) atomic_set(&acb->rq_map_token, 16); atomic_set(&acb->ante_token_value, 16); acb->fw_flag = FW_NORMAL; - mod_timer(&acb->eternal_timer, jiffies + msecs_to_jiffies(6 * HZ)); + init_timer(&acb->eternal_timer); + acb->eternal_timer.expires = jiffies + msecs_to_jiffies(6*HZ); + acb->eternal_timer.data = (unsigned long) acb; + acb->eternal_timer.function = &arcmsr_request_device_map; + add_timer(&acb->eternal_timer); acb->acb_flags &= ~ACB_F_BUS_RESET; rtn = SUCCESS; printk(KERN_ERR "arcmsr: scsi bus reset eh returns with success\n"); } else { acb->acb_flags &= ~ACB_F_BUS_RESET; - atomic_set(&acb->rq_map_token, 16); - atomic_set(&acb->ante_token_value, 16); - acb->fw_flag = FW_NORMAL; - mod_timer(&acb->eternal_timer, jiffies + msecs_to_jiffies(6*HZ)); + if (atomic_read(&acb->rq_map_token) == 0) { + atomic_set(&acb->rq_map_token, 16); + atomic_set(&acb->ante_token_value, 16); + acb->fw_flag = FW_NORMAL; + init_timer(&acb->eternal_timer); + acb->eternal_timer.expires = jiffies + msecs_to_jiffies(6*HZ); + acb->eternal_timer.data = (unsigned long) acb; + acb->eternal_timer.function = &arcmsr_request_device_map; + add_timer(&acb->eternal_timer); + } else { + atomic_set(&acb->rq_map_token, 16); + atomic_set(&acb->ante_token_value, 16); + acb->fw_flag = FW_NORMAL; + mod_timer(&acb->eternal_timer, jiffies + msecs_to_jiffies(6*HZ)); + } rtn = SUCCESS; } break; @@ -3001,10 +3007,21 @@ static int arcmsr_bus_reset(struct scsi_cmnd *cmd) rtn = FAILED; } else { acb->acb_flags &= ~ACB_F_BUS_RESET; - atomic_set(&acb->rq_map_token, 16); - atomic_set(&acb->ante_token_value, 16); - acb->fw_flag = FW_NORMAL; - mod_timer(&acb->eternal_timer, jiffies + msecs_to_jiffies(6 * HZ)); + if (atomic_read(&acb->rq_map_token) == 0) { + atomic_set(&acb->rq_map_token, 16); + atomic_set(&acb->ante_token_value, 16); + acb->fw_flag = FW_NORMAL; + init_timer(&acb->eternal_timer); + acb->eternal_timer.expires = jiffies + msecs_to_jiffies(6*HZ); + acb->eternal_timer.data = (unsigned long) acb; + acb->eternal_timer.function = &arcmsr_request_device_map; + add_timer(&acb->eternal_timer); + } else { + atomic_set(&acb->rq_map_token, 16); + atomic_set(&acb->ante_token_value, 16); + acb->fw_flag = FW_NORMAL; + mod_timer(&acb->eternal_timer, jiffies + msecs_to_jiffies(6*HZ)); + } rtn = SUCCESS; } break; @@ -3050,16 +3067,31 @@ static int arcmsr_bus_reset(struct scsi_cmnd *cmd) atomic_set(&acb->rq_map_token, 16); atomic_set(&acb->ante_token_value, 16); acb->fw_flag = FW_NORMAL; - mod_timer(&acb->eternal_timer, jiffies + msecs_to_jiffies(6 * HZ)); + init_timer(&acb->eternal_timer); + acb->eternal_timer.expires = jiffies + msecs_to_jiffies(6 * HZ); + acb->eternal_timer.data = (unsigned long) acb; + acb->eternal_timer.function = &arcmsr_request_device_map; + add_timer(&acb->eternal_timer); acb->acb_flags &= ~ACB_F_BUS_RESET; rtn = SUCCESS; printk(KERN_ERR "arcmsr: scsi bus reset eh returns with success\n"); } else { acb->acb_flags &= ~ACB_F_BUS_RESET; - atomic_set(&acb->rq_map_token, 16); - atomic_set(&acb->ante_token_value, 16); - acb->fw_flag = FW_NORMAL; - mod_timer(&acb->eternal_timer, jiffies + msecs_to_jiffies(6*HZ)); + if (atomic_read(&acb->rq_map_token) == 0) { + atomic_set(&acb->rq_map_token, 16); + atomic_set(&acb->ante_token_value, 16); + acb->fw_flag = FW_NORMAL; + init_timer(&acb->eternal_timer); + acb->eternal_timer.expires = jiffies + msecs_to_jiffies(6*HZ); + acb->eternal_timer.data = (unsigned long) acb; + acb->eternal_timer.function = &arcmsr_request_device_map; + add_timer(&acb->eternal_timer); + } else { + atomic_set(&acb->rq_map_token, 16); + atomic_set(&acb->ante_token_value, 16); + acb->fw_flag = FW_NORMAL; + mod_timer(&acb->eternal_timer, jiffies + msecs_to_jiffies(6*HZ)); + } rtn = SUCCESS; } break; diff --git a/trunk/drivers/scsi/libsas/sas_scsi_host.c b/trunk/drivers/scsi/libsas/sas_scsi_host.c index 9a7aaf5f1311..5815cbeb27a6 100644 --- a/trunk/drivers/scsi/libsas/sas_scsi_host.c +++ b/trunk/drivers/scsi/libsas/sas_scsi_host.c @@ -646,7 +646,6 @@ void sas_scsi_recover_host(struct Scsi_Host *shost) spin_lock_irqsave(shost->host_lock, flags); list_splice_init(&shost->eh_cmd_q, &eh_work_q); - shost->host_eh_scheduled = 0; spin_unlock_irqrestore(shost->host_lock, flags); SAS_DPRINTK("Enter %s\n", __func__); diff --git a/trunk/drivers/scsi/mpt2sas/mpt2sas_base.c b/trunk/drivers/scsi/mpt2sas/mpt2sas_base.c index 9ead0399808a..b2a817055b8b 100644 --- a/trunk/drivers/scsi/mpt2sas/mpt2sas_base.c +++ b/trunk/drivers/scsi/mpt2sas/mpt2sas_base.c @@ -2176,9 +2176,9 @@ _base_allocate_memory_pools(struct MPT2SAS_ADAPTER *ioc, int sleep_flag) /* adjust hba_queue_depth, reply_free_queue_depth, * and queue_size */ - ioc->hba_queue_depth -= (queue_diff / 2); - ioc->reply_free_queue_depth -= (queue_diff / 2); - queue_size = facts->MaxReplyDescriptorPostQueueDepth; + ioc->hba_queue_depth -= queue_diff; + ioc->reply_free_queue_depth -= queue_diff; + queue_size -= queue_diff; } ioc->reply_post_queue_depth = queue_size; @@ -3941,8 +3941,6 @@ mpt2sas_base_detach(struct MPT2SAS_ADAPTER *ioc) static void _base_reset_handler(struct MPT2SAS_ADAPTER *ioc, int reset_phase) { - mpt2sas_scsih_reset_handler(ioc, reset_phase); - mpt2sas_ctl_reset_handler(ioc, reset_phase); switch (reset_phase) { case MPT2_IOC_PRE_RESET: dtmprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: " @@ -3973,6 +3971,8 @@ _base_reset_handler(struct MPT2SAS_ADAPTER *ioc, int reset_phase) "MPT2_IOC_DONE_RESET\n", ioc->name, __func__)); break; } + mpt2sas_scsih_reset_handler(ioc, reset_phase); + mpt2sas_ctl_reset_handler(ioc, reset_phase); } /** @@ -4026,7 +4026,6 @@ mpt2sas_base_hard_reset_handler(struct MPT2SAS_ADAPTER *ioc, int sleep_flag, { int r; unsigned long flags; - u8 pe_complete = ioc->wait_for_port_enable_to_complete; dtmprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: enter\n", ioc->name, __func__)); @@ -4069,14 +4068,6 @@ mpt2sas_base_hard_reset_handler(struct MPT2SAS_ADAPTER *ioc, int sleep_flag, if (r) goto out; _base_reset_handler(ioc, MPT2_IOC_AFTER_RESET); - - /* If this hard reset is called while port enable is active, then - * there is no reason to call make_ioc_operational - */ - if (pe_complete) { - r = -EFAULT; - goto out; - } r = _base_make_ioc_operational(ioc, sleep_flag); if (!r) _base_reset_handler(ioc, MPT2_IOC_DONE_RESET); diff --git a/trunk/drivers/scsi/mpt2sas/mpt2sas_scsih.c b/trunk/drivers/scsi/mpt2sas/mpt2sas_scsih.c index 5ded3db6e316..eda347c57979 100644 --- a/trunk/drivers/scsi/mpt2sas/mpt2sas_scsih.c +++ b/trunk/drivers/scsi/mpt2sas/mpt2sas_scsih.c @@ -819,7 +819,7 @@ _scsih_is_end_device(u32 device_info) } /** - * _scsih_scsi_lookup_get - returns scmd entry + * mptscsih_get_scsi_lookup - returns scmd entry * @ioc: per adapter object * @smid: system request message index * @@ -831,28 +831,6 @@ _scsih_scsi_lookup_get(struct MPT2SAS_ADAPTER *ioc, u16 smid) return ioc->scsi_lookup[smid - 1].scmd; } -/** - * _scsih_scsi_lookup_get_clear - returns scmd entry - * @ioc: per adapter object - * @smid: system request message index - * - * Returns the smid stored scmd pointer. - * Then will derefrence the stored scmd pointer. - */ -static inline struct scsi_cmnd * -_scsih_scsi_lookup_get_clear(struct MPT2SAS_ADAPTER *ioc, u16 smid) -{ - unsigned long flags; - struct scsi_cmnd *scmd; - - spin_lock_irqsave(&ioc->scsi_lookup_lock, flags); - scmd = ioc->scsi_lookup[smid - 1].scmd; - ioc->scsi_lookup[smid - 1].scmd = NULL; - spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags); - - return scmd; -} - /** * _scsih_scsi_lookup_find_by_scmd - scmd lookup * @ioc: per adapter object @@ -3003,6 +2981,9 @@ _scsih_check_topo_delete_events(struct MPT2SAS_ADAPTER *ioc, u16 handle; for (i = 0 ; i < event_data->NumEntries; i++) { + if (event_data->PHY[i].PhyStatus & + MPI2_EVENT_SAS_TOPO_PHYSTATUS_VACANT) + continue; handle = le16_to_cpu(event_data->PHY[i].AttachedDevHandle); if (!handle) continue; @@ -3229,7 +3210,7 @@ _scsih_flush_running_cmds(struct MPT2SAS_ADAPTER *ioc) u16 count = 0; for (smid = 1; smid <= ioc->scsiio_depth; smid++) { - scmd = _scsih_scsi_lookup_get_clear(ioc, smid); + scmd = _scsih_scsi_lookup_get(ioc, smid); if (!scmd) continue; count++; @@ -3823,7 +3804,7 @@ _scsih_io_done(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 msix_index, u32 reply) u32 response_code = 0; mpi_reply = mpt2sas_base_get_reply_virt_addr(ioc, reply); - scmd = _scsih_scsi_lookup_get_clear(ioc, smid); + scmd = _scsih_scsi_lookup_get(ioc, smid); if (scmd == NULL) return 1; @@ -5024,12 +5005,6 @@ _scsih_sas_device_status_change_event(struct MPT2SAS_ADAPTER *ioc, event_data); #endif - /* In MPI Revision K (0xC), the internal device reset complete was - * implemented, so avoid setting tm_busy flag for older firmware. - */ - if ((ioc->facts.HeaderVersion >> 8) < 0xC) - return; - if (event_data->ReasonCode != MPI2_EVENT_SAS_DEV_STAT_RC_INTERNAL_DEVICE_RESET && event_data->ReasonCode != @@ -5124,7 +5099,6 @@ _scsih_sas_broadcast_primative_event(struct MPT2SAS_ADAPTER *ioc, struct fw_event_work *fw_event) { struct scsi_cmnd *scmd; - struct scsi_device *sdev; u16 smid, handle; u32 lun; struct MPT2SAS_DEVICE *sas_device_priv_data; @@ -5135,17 +5109,12 @@ _scsih_sas_broadcast_primative_event(struct MPT2SAS_ADAPTER *ioc, Mpi2EventDataSasBroadcastPrimitive_t *event_data = fw_event->event_data; #endif u16 ioc_status; - unsigned long flags; - int r; - dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "broadcast primative: " "phy number(%d), width(%d)\n", ioc->name, event_data->PhyNum, event_data->PortWidth)); dtmprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: enter\n", ioc->name, __func__)); - spin_lock_irqsave(&ioc->scsi_lookup_lock, flags); - ioc->broadcast_aen_busy = 0; termination_count = 0; query_count = 0; mpi_reply = ioc->tm_cmds.reply; @@ -5153,8 +5122,7 @@ _scsih_sas_broadcast_primative_event(struct MPT2SAS_ADAPTER *ioc, scmd = _scsih_scsi_lookup_get(ioc, smid); if (!scmd) continue; - sdev = scmd->device; - sas_device_priv_data = sdev->hostdata; + sas_device_priv_data = scmd->device->hostdata; if (!sas_device_priv_data || !sas_device_priv_data->sas_target) continue; /* skip hidden raid components */ @@ -5170,7 +5138,6 @@ _scsih_sas_broadcast_primative_event(struct MPT2SAS_ADAPTER *ioc, lun = sas_device_priv_data->lun; query_count++; - spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags); mpt2sas_scsih_issue_tm(ioc, handle, 0, 0, lun, MPI2_SCSITASKMGMT_TASKTYPE_QUERY_TASK, smid, 30, NULL); ioc->tm_cmds.status = MPT2_CMD_NOT_USED; @@ -5180,20 +5147,14 @@ _scsih_sas_broadcast_primative_event(struct MPT2SAS_ADAPTER *ioc, (mpi_reply->ResponseCode == MPI2_SCSITASKMGMT_RSP_TM_SUCCEEDED || mpi_reply->ResponseCode == - MPI2_SCSITASKMGMT_RSP_IO_QUEUED_ON_IOC)) { - spin_lock_irqsave(&ioc->scsi_lookup_lock, flags); + MPI2_SCSITASKMGMT_RSP_IO_QUEUED_ON_IOC)) continue; - } - r = mpt2sas_scsih_issue_tm(ioc, handle, sdev->channel, sdev->id, - sdev->lun, MPI2_SCSITASKMGMT_TASKTYPE_ABORT_TASK, smid, 30, - scmd); - if (r == FAILED) - sdev_printk(KERN_WARNING, sdev, "task abort: FAILED " - "scmd(%p)\n", scmd); + + mpt2sas_scsih_issue_tm(ioc, handle, 0, 0, lun, + MPI2_SCSITASKMGMT_TASKTYPE_ABRT_TASK_SET, 0, 30, NULL); termination_count += le32_to_cpu(mpi_reply->TerminationCount); - spin_lock_irqsave(&ioc->scsi_lookup_lock, flags); } - spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags); + ioc->broadcast_aen_busy = 0; dtmprintk(ioc, printk(MPT2SAS_INFO_FMT "%s - exit, query_count = %d termination_count = %d\n", @@ -6665,7 +6626,6 @@ _scsih_remove(struct pci_dev *pdev) destroy_workqueue(wq); /* release all the volumes */ - _scsih_ir_shutdown(ioc); list_for_each_entry_safe(raid_device, next, &ioc->raid_device_list, list) { if (raid_device->starget) { diff --git a/trunk/drivers/vhost/net.c b/trunk/drivers/vhost/net.c index f616cefc95ba..9b3ca103135f 100644 --- a/trunk/drivers/vhost/net.c +++ b/trunk/drivers/vhost/net.c @@ -128,7 +128,8 @@ static void handle_tx(struct vhost_net *net) size_t hdr_size; struct socket *sock; - /* TODO: check that we are running from vhost_worker? */ + /* TODO: check that we are running from vhost_worker? + * Not sure it's worth it, it's straight-forward enough. */ sock = rcu_dereference_check(vq->private_data, 1); if (!sock) return; @@ -305,8 +306,7 @@ static void handle_rx_big(struct vhost_net *net) size_t len, total_len = 0; int err; size_t hdr_size; - /* TODO: check that we are running from vhost_worker? */ - struct socket *sock = rcu_dereference_check(vq->private_data, 1); + struct socket *sock = rcu_dereference(vq->private_data); if (!sock || skb_queue_empty(&sock->sk->sk_receive_queue)) return; @@ -415,8 +415,7 @@ static void handle_rx_mergeable(struct vhost_net *net) int err, headcount; size_t vhost_hlen, sock_hlen; size_t vhost_len, sock_len; - /* TODO: check that we are running from vhost_worker? */ - struct socket *sock = rcu_dereference_check(vq->private_data, 1); + struct socket *sock = rcu_dereference(vq->private_data); if (!sock || skb_queue_empty(&sock->sk->sk_receive_queue)) return; diff --git a/trunk/drivers/vhost/vhost.h b/trunk/drivers/vhost/vhost.h index b3363ae38518..2af44b7b1f3f 100644 --- a/trunk/drivers/vhost/vhost.h +++ b/trunk/drivers/vhost/vhost.h @@ -173,9 +173,9 @@ static inline int vhost_has_feature(struct vhost_dev *dev, int bit) { unsigned acked_features; - /* TODO: check that we are running from vhost_worker or dev mutex is - * held? */ - acked_features = rcu_dereference_index_check(dev->acked_features, 1); + acked_features = + rcu_dereference_index_check(dev->acked_features, + lockdep_is_held(&dev->mutex)); return acked_features & (1 << bit); } diff --git a/trunk/fs/btrfs/acl.c b/trunk/fs/btrfs/acl.c index 9c949348510b..15b5ca2a2606 100644 --- a/trunk/fs/btrfs/acl.c +++ b/trunk/fs/btrfs/acl.c @@ -37,9 +37,6 @@ static struct posix_acl *btrfs_get_acl(struct inode *inode, int type) char *value = NULL; struct posix_acl *acl; - if (!IS_POSIXACL(inode)) - return NULL; - acl = get_cached_acl(inode, type); if (acl != ACL_NOT_CACHED) return acl; @@ -87,9 +84,6 @@ static int btrfs_xattr_acl_get(struct dentry *dentry, const char *name, struct posix_acl *acl; int ret = 0; - if (!IS_POSIXACL(dentry->d_inode)) - return -EOPNOTSUPP; - acl = btrfs_get_acl(dentry->d_inode, type); if (IS_ERR(acl)) diff --git a/trunk/fs/btrfs/compression.c b/trunk/fs/btrfs/compression.c index 4d2110eafe29..f745287fbf2e 100644 --- a/trunk/fs/btrfs/compression.c +++ b/trunk/fs/btrfs/compression.c @@ -562,7 +562,7 @@ int btrfs_submit_compressed_read(struct inode *inode, struct bio *bio, u64 em_len; u64 em_start; struct extent_map *em; - int ret = -ENOMEM; + int ret; u32 *sums; tree = &BTRFS_I(inode)->io_tree; @@ -577,9 +577,6 @@ int btrfs_submit_compressed_read(struct inode *inode, struct bio *bio, compressed_len = em->block_len; cb = kmalloc(compressed_bio_size(root, compressed_len), GFP_NOFS); - if (!cb) - goto out; - atomic_set(&cb->pending_bios, 0); cb->errors = 0; cb->inode = inode; @@ -600,18 +597,13 @@ int btrfs_submit_compressed_read(struct inode *inode, struct bio *bio, nr_pages = (compressed_len + PAGE_CACHE_SIZE - 1) / PAGE_CACHE_SIZE; - cb->compressed_pages = kzalloc(sizeof(struct page *) * nr_pages, + cb->compressed_pages = kmalloc(sizeof(struct page *) * nr_pages, GFP_NOFS); - if (!cb->compressed_pages) - goto fail1; - bdev = BTRFS_I(inode)->root->fs_info->fs_devices->latest_bdev; for (page_index = 0; page_index < nr_pages; page_index++) { cb->compressed_pages[page_index] = alloc_page(GFP_NOFS | __GFP_HIGHMEM); - if (!cb->compressed_pages[page_index]) - goto fail2; } cb->nr_pages = nr_pages; @@ -622,8 +614,6 @@ int btrfs_submit_compressed_read(struct inode *inode, struct bio *bio, cb->len = uncompressed_len; comp_bio = compressed_bio_alloc(bdev, cur_disk_byte, GFP_NOFS); - if (!comp_bio) - goto fail2; comp_bio->bi_private = cb; comp_bio->bi_end_io = end_compressed_bio_read; atomic_inc(&cb->pending_bios); @@ -691,17 +681,6 @@ int btrfs_submit_compressed_read(struct inode *inode, struct bio *bio, bio_put(comp_bio); return 0; - -fail2: - for (page_index = 0; page_index < nr_pages; page_index++) - free_page((unsigned long)cb->compressed_pages[page_index]); - - kfree(cb->compressed_pages); -fail1: - kfree(cb); -out: - free_extent_map(em); - return ret; } static struct list_head comp_idle_workspace[BTRFS_COMPRESS_TYPES]; @@ -921,7 +900,7 @@ int btrfs_decompress(int type, unsigned char *data_in, struct page *dest_page, return ret; } -void btrfs_exit_compress(void) +void __exit btrfs_exit_compress(void) { free_workspaces(); } diff --git a/trunk/fs/btrfs/disk-io.c b/trunk/fs/btrfs/disk-io.c index fdce8799b98d..b531c36455d8 100644 --- a/trunk/fs/btrfs/disk-io.c +++ b/trunk/fs/btrfs/disk-io.c @@ -1550,7 +1550,6 @@ static int transaction_kthread(void *arg) spin_unlock(&root->fs_info->new_trans_lock); trans = btrfs_join_transaction(root, 1); - BUG_ON(IS_ERR(trans)); if (transid == trans->transid) { ret = btrfs_commit_transaction(trans, root); BUG_ON(ret); @@ -2454,14 +2453,10 @@ int btrfs_commit_super(struct btrfs_root *root) up_write(&root->fs_info->cleanup_work_sem); trans = btrfs_join_transaction(root, 1); - if (IS_ERR(trans)) - return PTR_ERR(trans); ret = btrfs_commit_transaction(trans, root); BUG_ON(ret); /* run commit again to drop the original snapshot */ trans = btrfs_join_transaction(root, 1); - if (IS_ERR(trans)) - return PTR_ERR(trans); btrfs_commit_transaction(trans, root); ret = btrfs_write_and_wait_transaction(NULL, root); BUG_ON(ret); @@ -2559,8 +2554,6 @@ int close_ctree(struct btrfs_root *root) kfree(fs_info->chunk_root); kfree(fs_info->dev_root); kfree(fs_info->csum_root); - kfree(fs_info); - return 0; } diff --git a/trunk/fs/btrfs/export.c b/trunk/fs/btrfs/export.c index ff27d7a477b2..9786963b07e5 100644 --- a/trunk/fs/btrfs/export.c +++ b/trunk/fs/btrfs/export.c @@ -171,8 +171,6 @@ static struct dentry *btrfs_get_parent(struct dentry *child) int ret; path = btrfs_alloc_path(); - if (!path) - return ERR_PTR(-ENOMEM); if (dir->i_ino == BTRFS_FIRST_FREE_OBJECTID) { key.objectid = root->root_key.objectid; diff --git a/trunk/fs/btrfs/extent-tree.c b/trunk/fs/btrfs/extent-tree.c index 4e7e012ad667..b55269340cec 100644 --- a/trunk/fs/btrfs/extent-tree.c +++ b/trunk/fs/btrfs/extent-tree.c @@ -320,6 +320,11 @@ static int caching_kthread(void *data) if (!path) return -ENOMEM; + exclude_super_stripes(extent_root, block_group); + spin_lock(&block_group->space_info->lock); + block_group->space_info->bytes_readonly += block_group->bytes_super; + spin_unlock(&block_group->space_info->lock); + last = max_t(u64, block_group->key.objectid, BTRFS_SUPER_INFO_OFFSET); /* @@ -462,10 +467,8 @@ static int cache_block_group(struct btrfs_block_group_cache *cache, cache->cached = BTRFS_CACHE_NO; } spin_unlock(&cache->lock); - if (ret == 1) { - free_excluded_extents(fs_info->extent_root, cache); + if (ret == 1) return 0; - } } if (load_cache_only) @@ -3341,10 +3344,8 @@ static int shrink_delalloc(struct btrfs_trans_handle *trans, u64 reserved; u64 max_reclaim; u64 reclaimed = 0; - long time_left; int pause = 1; int nr_pages = (2 * 1024 * 1024) >> PAGE_CACHE_SHIFT; - int loops = 0; block_rsv = &root->fs_info->delalloc_block_rsv; space_info = block_rsv->space_info; @@ -3357,7 +3358,7 @@ static int shrink_delalloc(struct btrfs_trans_handle *trans, max_reclaim = min(reserved, to_reclaim); - while (loops < 1024) { + while (1) { /* have the flusher threads jump in and do some IO */ smp_mb(); nr_pages = min_t(unsigned long, nr_pages, @@ -3365,12 +3366,8 @@ static int shrink_delalloc(struct btrfs_trans_handle *trans, writeback_inodes_sb_nr_if_idle(root->fs_info->sb, nr_pages); spin_lock(&space_info->lock); - if (reserved > space_info->bytes_reserved) { - loops = 0; + if (reserved > space_info->bytes_reserved) reclaimed += reserved - space_info->bytes_reserved; - } else { - loops++; - } reserved = space_info->bytes_reserved; spin_unlock(&space_info->lock); @@ -3381,12 +3378,7 @@ static int shrink_delalloc(struct btrfs_trans_handle *trans, return -EAGAIN; __set_current_state(TASK_INTERRUPTIBLE); - time_left = schedule_timeout(pause); - - /* We were interrupted, exit */ - if (time_left) - break; - + schedule_timeout(pause); pause <<= 1; if (pause > HZ / 10) pause = HZ / 10; @@ -3596,20 +3588,8 @@ void block_rsv_release_bytes(struct btrfs_block_rsv *block_rsv, if (num_bytes > 0) { if (dest) { - spin_lock(&dest->lock); - if (!dest->full) { - u64 bytes_to_add; - - bytes_to_add = dest->size - dest->reserved; - bytes_to_add = min(num_bytes, bytes_to_add); - dest->reserved += bytes_to_add; - if (dest->reserved >= dest->size) - dest->full = 1; - num_bytes -= bytes_to_add; - } - spin_unlock(&dest->lock); - } - if (num_bytes) { + block_rsv_add_bytes(dest, num_bytes, 0); + } else { spin_lock(&space_info->lock); space_info->bytes_reserved -= num_bytes; spin_unlock(&space_info->lock); @@ -4032,7 +4012,6 @@ void btrfs_delalloc_release_metadata(struct inode *inode, u64 num_bytes) num_bytes = ALIGN(num_bytes, root->sectorsize); atomic_dec(&BTRFS_I(inode)->outstanding_extents); - WARN_ON(atomic_read(&BTRFS_I(inode)->outstanding_extents) < 0); spin_lock(&BTRFS_I(inode)->accounting_lock); nr_extents = atomic_read(&BTRFS_I(inode)->outstanding_extents); @@ -5654,7 +5633,6 @@ use_block_rsv(struct btrfs_trans_handle *trans, struct btrfs_root *root, u32 blocksize) { struct btrfs_block_rsv *block_rsv; - struct btrfs_block_rsv *global_rsv = &root->fs_info->global_block_rsv; int ret; block_rsv = get_block_rsv(trans, root); @@ -5662,39 +5640,14 @@ use_block_rsv(struct btrfs_trans_handle *trans, if (block_rsv->size == 0) { ret = reserve_metadata_bytes(trans, root, block_rsv, blocksize, 0); - /* - * If we couldn't reserve metadata bytes try and use some from - * the global reserve. - */ - if (ret && block_rsv != global_rsv) { - ret = block_rsv_use_bytes(global_rsv, blocksize); - if (!ret) - return global_rsv; - return ERR_PTR(ret); - } else if (ret) { + if (ret) return ERR_PTR(ret); - } return block_rsv; } ret = block_rsv_use_bytes(block_rsv, blocksize); if (!ret) return block_rsv; - if (ret) { - WARN_ON(1); - ret = reserve_metadata_bytes(trans, root, block_rsv, blocksize, - 0); - if (!ret) { - spin_lock(&block_rsv->lock); - block_rsv->size += blocksize; - spin_unlock(&block_rsv->lock); - return block_rsv; - } else if (ret && block_rsv != global_rsv) { - ret = block_rsv_use_bytes(global_rsv, blocksize); - if (!ret) - return global_rsv; - } - } return ERR_PTR(-ENOSPC); } @@ -6268,8 +6221,6 @@ int btrfs_drop_snapshot(struct btrfs_root *root, BUG_ON(!wc); trans = btrfs_start_transaction(tree_root, 0); - BUG_ON(IS_ERR(trans)); - if (block_rsv) trans->block_rsv = block_rsv; @@ -6367,7 +6318,6 @@ int btrfs_drop_snapshot(struct btrfs_root *root, btrfs_end_transaction_throttle(trans, tree_root); trans = btrfs_start_transaction(tree_root, 0); - BUG_ON(IS_ERR(trans)); if (block_rsv) trans->block_rsv = block_rsv; } @@ -6496,8 +6446,6 @@ static noinline int relocate_inode_pages(struct inode *inode, u64 start, int ret = 0; ra = kzalloc(sizeof(*ra), GFP_NOFS); - if (!ra) - return -ENOMEM; mutex_lock(&inode->i_mutex); first_index = start >> PAGE_CACHE_SHIFT; @@ -7529,7 +7477,7 @@ int btrfs_drop_dead_reloc_roots(struct btrfs_root *root) BUG_ON(reloc_root->commit_root != NULL); while (1) { trans = btrfs_join_transaction(root, 1); - BUG_ON(IS_ERR(trans)); + BUG_ON(!trans); mutex_lock(&root->fs_info->drop_mutex); ret = btrfs_drop_snapshot(trans, reloc_root); @@ -7587,7 +7535,7 @@ int btrfs_cleanup_reloc_trees(struct btrfs_root *root) if (found) { trans = btrfs_start_transaction(root, 1); - BUG_ON(IS_ERR(trans)); + BUG_ON(!trans); ret = btrfs_commit_transaction(trans, root); BUG_ON(ret); } @@ -7831,7 +7779,7 @@ static noinline int relocate_one_extent(struct btrfs_root *extent_root, trans = btrfs_start_transaction(extent_root, 1); - BUG_ON(IS_ERR(trans)); + BUG_ON(!trans); if (extent_key->objectid == 0) { ret = del_extent_zero(trans, extent_root, path, extent_key); @@ -8322,13 +8270,6 @@ int btrfs_free_block_groups(struct btrfs_fs_info *info) if (block_group->cached == BTRFS_CACHE_STARTED) wait_block_group_cache_done(block_group); - /* - * We haven't cached this block group, which means we could - * possibly have excluded extents on this block group. - */ - if (block_group->cached == BTRFS_CACHE_NO) - free_excluded_extents(info->extent_root, block_group); - btrfs_remove_free_space_cache(block_group); btrfs_put_block_group(block_group); @@ -8443,13 +8384,6 @@ int btrfs_read_block_groups(struct btrfs_root *root) cache->flags = btrfs_block_group_flags(&cache->item); cache->sectorsize = root->sectorsize; - /* - * We need to exclude the super stripes now so that the space - * info has super bytes accounted for, otherwise we'll think - * we have more space than we actually do. - */ - exclude_super_stripes(root, cache); - /* * check for two cases, either we are full, and therefore * don't need to bother with the caching work since we won't @@ -8458,10 +8392,12 @@ int btrfs_read_block_groups(struct btrfs_root *root) * time, particularly in the full case. */ if (found_key.offset == btrfs_block_group_used(&cache->item)) { + exclude_super_stripes(root, cache); cache->last_byte_to_unpin = (u64)-1; cache->cached = BTRFS_CACHE_FINISHED; free_excluded_extents(root, cache); } else if (btrfs_block_group_used(&cache->item) == 0) { + exclude_super_stripes(root, cache); cache->last_byte_to_unpin = (u64)-1; cache->cached = BTRFS_CACHE_FINISHED; add_new_free_space(cache, root->fs_info, diff --git a/trunk/fs/btrfs/extent_io.c b/trunk/fs/btrfs/extent_io.c index 5e76a474cb7e..2e993cf1766e 100644 --- a/trunk/fs/btrfs/extent_io.c +++ b/trunk/fs/btrfs/extent_io.c @@ -1865,7 +1865,7 @@ static int submit_one_bio(int rw, struct bio *bio, int mirror_num, bio_get(bio); if (tree->ops && tree->ops->submit_bio_hook) - ret = tree->ops->submit_bio_hook(page->mapping->host, rw, bio, + tree->ops->submit_bio_hook(page->mapping->host, rw, bio, mirror_num, bio_flags, start); else submit_bio(rw, bio); @@ -1920,8 +1920,6 @@ static int submit_extent_page(int rw, struct extent_io_tree *tree, nr = bio_get_nr_vecs(bdev); bio = btrfs_bio_alloc(bdev, sector, nr, GFP_NOFS | __GFP_HIGH); - if (!bio) - return -ENOMEM; bio_add_page(bio, page, page_size, offset); bio->bi_end_io = end_io_func; @@ -2128,7 +2126,7 @@ int extent_read_full_page(struct extent_io_tree *tree, struct page *page, ret = __extent_read_full_page(tree, page, get_extent, &bio, 0, &bio_flags); if (bio) - ret = submit_one_bio(READ, bio, 0, bio_flags); + submit_one_bio(READ, bio, 0, bio_flags); return ret; } diff --git a/trunk/fs/btrfs/file-item.c b/trunk/fs/btrfs/file-item.c index 4f19a3e1bf32..a562a250ae77 100644 --- a/trunk/fs/btrfs/file-item.c +++ b/trunk/fs/btrfs/file-item.c @@ -536,8 +536,6 @@ int btrfs_del_csums(struct btrfs_trans_handle *trans, root = root->fs_info->csum_root; path = btrfs_alloc_path(); - if (!path) - return -ENOMEM; while (1) { key.objectid = BTRFS_EXTENT_CSUM_OBJECTID; @@ -550,10 +548,7 @@ int btrfs_del_csums(struct btrfs_trans_handle *trans, if (path->slots[0] == 0) goto out; path->slots[0]--; - } else if (ret < 0) { - goto out; } - leaf = path->nodes[0]; btrfs_item_key_to_cpu(leaf, &key, path->slots[0]); diff --git a/trunk/fs/btrfs/file.c b/trunk/fs/btrfs/file.c index c1d3a818731a..c800d58f3013 100644 --- a/trunk/fs/btrfs/file.c +++ b/trunk/fs/btrfs/file.c @@ -793,12 +793,8 @@ static noinline int prepare_pages(struct btrfs_root *root, struct file *file, for (i = 0; i < num_pages; i++) { pages[i] = grab_cache_page(inode->i_mapping, index + i); if (!pages[i]) { - int c; - for (c = i - 1; c >= 0; c--) { - unlock_page(pages[c]); - page_cache_release(pages[c]); - } - return -ENOMEM; + err = -ENOMEM; + BUG_ON(1); } wait_on_page_writeback(pages[i]); } @@ -950,10 +946,6 @@ static ssize_t btrfs_file_aio_write(struct kiocb *iocb, PAGE_CACHE_SIZE, PAGE_CACHE_SIZE / (sizeof(struct page *))); pages = kmalloc(nrptrs * sizeof(struct page *), GFP_KERNEL); - if (!pages) { - ret = -ENOMEM; - goto out; - } /* generic_write_checks can change our pos */ start_pos = pos; @@ -992,8 +984,8 @@ static ssize_t btrfs_file_aio_write(struct kiocb *iocb, size_t write_bytes = min(iov_iter_count(&i), nrptrs * (size_t)PAGE_CACHE_SIZE - offset); - size_t num_pages = (write_bytes + offset + - PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT; + size_t num_pages = (write_bytes + PAGE_CACHE_SIZE - 1) >> + PAGE_CACHE_SHIFT; WARN_ON(num_pages > nrptrs); memset(pages, 0, sizeof(struct page *) * nrptrs); @@ -1023,8 +1015,8 @@ static ssize_t btrfs_file_aio_write(struct kiocb *iocb, copied = btrfs_copy_from_user(pos, num_pages, write_bytes, pages, &i); - dirty_pages = (copied + offset + PAGE_CACHE_SIZE - 1) >> - PAGE_CACHE_SHIFT; + dirty_pages = (copied + PAGE_CACHE_SIZE - 1) >> + PAGE_CACHE_SHIFT; if (num_pages > dirty_pages) { if (copied > 0) diff --git a/trunk/fs/btrfs/free-space-cache.c b/trunk/fs/btrfs/free-space-cache.c index a0390657451b..60d684266959 100644 --- a/trunk/fs/btrfs/free-space-cache.c +++ b/trunk/fs/btrfs/free-space-cache.c @@ -987,18 +987,11 @@ tree_search_offset(struct btrfs_block_group_cache *block_group, return entry; } -static inline void -__unlink_free_space(struct btrfs_block_group_cache *block_group, - struct btrfs_free_space *info) -{ - rb_erase(&info->offset_index, &block_group->free_space_offset); - block_group->free_extents--; -} - static void unlink_free_space(struct btrfs_block_group_cache *block_group, struct btrfs_free_space *info) { - __unlink_free_space(block_group, info); + rb_erase(&info->offset_index, &block_group->free_space_offset); + block_group->free_extents--; block_group->free_space -= info->bytes; } @@ -1023,18 +1016,14 @@ static void recalculate_thresholds(struct btrfs_block_group_cache *block_group) u64 max_bytes; u64 bitmap_bytes; u64 extent_bytes; - u64 size = block_group->key.offset; /* * The goal is to keep the total amount of memory used per 1gb of space * at or below 32k, so we need to adjust how much memory we allow to be * used by extent based free space tracking */ - if (size < 1024 * 1024 * 1024) - max_bytes = MAX_CACHE_BYTES_PER_GIG; - else - max_bytes = MAX_CACHE_BYTES_PER_GIG * - div64_u64(size, 1024 * 1024 * 1024); + max_bytes = MAX_CACHE_BYTES_PER_GIG * + (div64_u64(block_group->key.offset, 1024 * 1024 * 1024)); /* * we want to account for 1 more bitmap than what we have so we can make @@ -1182,16 +1171,6 @@ static void add_new_bitmap(struct btrfs_block_group_cache *block_group, recalculate_thresholds(block_group); } -static void free_bitmap(struct btrfs_block_group_cache *block_group, - struct btrfs_free_space *bitmap_info) -{ - unlink_free_space(block_group, bitmap_info); - kfree(bitmap_info->bitmap); - kfree(bitmap_info); - block_group->total_bitmaps--; - recalculate_thresholds(block_group); -} - static noinline int remove_from_bitmap(struct btrfs_block_group_cache *block_group, struct btrfs_free_space *bitmap_info, u64 *offset, u64 *bytes) @@ -1216,7 +1195,6 @@ static noinline int remove_from_bitmap(struct btrfs_block_group_cache *block_gro */ search_start = *offset; search_bytes = *bytes; - search_bytes = min(search_bytes, end - search_start + 1); ret = search_bitmap(block_group, bitmap_info, &search_start, &search_bytes); BUG_ON(ret < 0 || search_start != *offset); @@ -1233,8 +1211,13 @@ static noinline int remove_from_bitmap(struct btrfs_block_group_cache *block_gro if (*bytes) { struct rb_node *next = rb_next(&bitmap_info->offset_index); - if (!bitmap_info->bytes) - free_bitmap(block_group, bitmap_info); + if (!bitmap_info->bytes) { + unlink_free_space(block_group, bitmap_info); + kfree(bitmap_info->bitmap); + kfree(bitmap_info); + block_group->total_bitmaps--; + recalculate_thresholds(block_group); + } /* * no entry after this bitmap, but we still have bytes to @@ -1267,8 +1250,13 @@ static noinline int remove_from_bitmap(struct btrfs_block_group_cache *block_gro return -EAGAIN; goto again; - } else if (!bitmap_info->bytes) - free_bitmap(block_group, bitmap_info); + } else if (!bitmap_info->bytes) { + unlink_free_space(block_group, bitmap_info); + kfree(bitmap_info->bitmap); + kfree(bitmap_info); + block_group->total_bitmaps--; + recalculate_thresholds(block_group); + } return 0; } @@ -1371,14 +1359,22 @@ static int insert_into_bitmap(struct btrfs_block_group_cache *block_group, return ret; } -bool try_merge_free_space(struct btrfs_block_group_cache *block_group, - struct btrfs_free_space *info, bool update_stat) +int btrfs_add_free_space(struct btrfs_block_group_cache *block_group, + u64 offset, u64 bytes) { - struct btrfs_free_space *left_info; - struct btrfs_free_space *right_info; - bool merged = false; - u64 offset = info->offset; - u64 bytes = info->bytes; + struct btrfs_free_space *right_info = NULL; + struct btrfs_free_space *left_info = NULL; + struct btrfs_free_space *info = NULL; + int ret = 0; + + info = kzalloc(sizeof(struct btrfs_free_space), GFP_NOFS); + if (!info) + return -ENOMEM; + + info->offset = offset; + info->bytes = bytes; + + spin_lock(&block_group->tree_lock); /* * first we want to see if there is free space adjacent to the range we @@ -1392,62 +1388,37 @@ bool try_merge_free_space(struct btrfs_block_group_cache *block_group, else left_info = tree_search_offset(block_group, offset - 1, 0, 0); + /* + * If there was no extent directly to the left or right of this new + * extent then we know we're going to have to allocate a new extent, so + * before we do that see if we need to drop this into a bitmap + */ + if ((!left_info || left_info->bitmap) && + (!right_info || right_info->bitmap)) { + ret = insert_into_bitmap(block_group, info); + + if (ret < 0) { + goto out; + } else if (ret) { + ret = 0; + goto out; + } + } + if (right_info && !right_info->bitmap) { - if (update_stat) - unlink_free_space(block_group, right_info); - else - __unlink_free_space(block_group, right_info); + unlink_free_space(block_group, right_info); info->bytes += right_info->bytes; kfree(right_info); - merged = true; } if (left_info && !left_info->bitmap && left_info->offset + left_info->bytes == offset) { - if (update_stat) - unlink_free_space(block_group, left_info); - else - __unlink_free_space(block_group, left_info); + unlink_free_space(block_group, left_info); info->offset = left_info->offset; info->bytes += left_info->bytes; kfree(left_info); - merged = true; } - return merged; -} - -int btrfs_add_free_space(struct btrfs_block_group_cache *block_group, - u64 offset, u64 bytes) -{ - struct btrfs_free_space *info; - int ret = 0; - - info = kzalloc(sizeof(struct btrfs_free_space), GFP_NOFS); - if (!info) - return -ENOMEM; - - info->offset = offset; - info->bytes = bytes; - - spin_lock(&block_group->tree_lock); - - if (try_merge_free_space(block_group, info, true)) - goto link; - - /* - * There was no extent directly to the left or right of this new - * extent then we know we're going to have to allocate a new extent, so - * before we do that see if we need to drop this into a bitmap - */ - ret = insert_into_bitmap(block_group, info); - if (ret < 0) { - goto out; - } else if (ret) { - ret = 0; - goto out; - } -link: ret = link_free_space(block_group, info); if (ret) kfree(info); @@ -1650,7 +1621,6 @@ __btrfs_return_cluster_to_free_space( node = rb_next(&entry->offset_index); rb_erase(&entry->offset_index, &cluster->root); BUG_ON(entry->bitmap); - try_merge_free_space(block_group, entry, false); tree_insert_offset(&block_group->free_space_offset, entry->offset, &entry->offset_index, 0); } @@ -1715,8 +1685,13 @@ u64 btrfs_find_space_for_alloc(struct btrfs_block_group_cache *block_group, ret = offset; if (entry->bitmap) { bitmap_clear_bits(block_group, entry, offset, bytes); - if (!entry->bytes) - free_bitmap(block_group, entry); + if (!entry->bytes) { + unlink_free_space(block_group, entry); + kfree(entry->bitmap); + kfree(entry); + block_group->total_bitmaps--; + recalculate_thresholds(block_group); + } } else { unlink_free_space(block_group, entry); entry->offset += bytes; @@ -1814,8 +1789,6 @@ static u64 btrfs_alloc_from_bitmap(struct btrfs_block_group_cache *block_group, ret = search_start; bitmap_clear_bits(block_group, entry, ret, bytes); - if (entry->bytes == 0) - free_bitmap(block_group, entry); out: spin_unlock(&cluster->lock); spin_unlock(&block_group->tree_lock); @@ -1869,26 +1842,15 @@ u64 btrfs_alloc_from_cluster(struct btrfs_block_group_cache *block_group, entry->offset += bytes; entry->bytes -= bytes; - if (entry->bytes == 0) + if (entry->bytes == 0) { rb_erase(&entry->offset_index, &cluster->root); + kfree(entry); + } break; } out: spin_unlock(&cluster->lock); - if (!ret) - return 0; - - spin_lock(&block_group->tree_lock); - - block_group->free_space -= bytes; - if (entry->bytes == 0) { - block_group->free_extents--; - kfree(entry); - } - - spin_unlock(&block_group->tree_lock); - return ret; } diff --git a/trunk/fs/btrfs/inode.c b/trunk/fs/btrfs/inode.c index bcc461a9695f..160b55b3e132 100644 --- a/trunk/fs/btrfs/inode.c +++ b/trunk/fs/btrfs/inode.c @@ -416,7 +416,7 @@ static noinline int compress_file_range(struct inode *inode, } if (start == 0) { trans = btrfs_join_transaction(root, 1); - BUG_ON(IS_ERR(trans)); + BUG_ON(!trans); btrfs_set_trans_block_group(trans, inode); trans->block_rsv = &root->fs_info->delalloc_block_rsv; @@ -612,7 +612,6 @@ static noinline int submit_compressed_extents(struct inode *inode, GFP_NOFS); trans = btrfs_join_transaction(root, 1); - BUG_ON(IS_ERR(trans)); ret = btrfs_reserve_extent(trans, root, async_extent->compressed_size, async_extent->compressed_size, @@ -772,7 +771,7 @@ static noinline int cow_file_range(struct inode *inode, BUG_ON(root == root->fs_info->tree_root); trans = btrfs_join_transaction(root, 1); - BUG_ON(IS_ERR(trans)); + BUG_ON(!trans); btrfs_set_trans_block_group(trans, inode); trans->block_rsv = &root->fs_info->delalloc_block_rsv; @@ -1050,7 +1049,7 @@ static noinline int run_delalloc_nocow(struct inode *inode, } else { trans = btrfs_join_transaction(root, 1); } - BUG_ON(IS_ERR(trans)); + BUG_ON(!trans); cow_start = (u64)-1; cur_offset = start; @@ -1558,7 +1557,6 @@ static void btrfs_writepage_fixup_worker(struct btrfs_work *work) out_page: unlock_page(page); page_cache_release(page); - kfree(fixup); } /* @@ -1705,7 +1703,7 @@ static int btrfs_finish_ordered_io(struct inode *inode, u64 start, u64 end) trans = btrfs_join_transaction_nolock(root, 1); else trans = btrfs_join_transaction(root, 1); - BUG_ON(IS_ERR(trans)); + BUG_ON(!trans); btrfs_set_trans_block_group(trans, inode); trans->block_rsv = &root->fs_info->delalloc_block_rsv; ret = btrfs_update_inode(trans, root, inode); @@ -1722,7 +1720,6 @@ static int btrfs_finish_ordered_io(struct inode *inode, u64 start, u64 end) trans = btrfs_join_transaction_nolock(root, 1); else trans = btrfs_join_transaction(root, 1); - BUG_ON(IS_ERR(trans)); btrfs_set_trans_block_group(trans, inode); trans->block_rsv = &root->fs_info->delalloc_block_rsv; @@ -2357,7 +2354,6 @@ void btrfs_orphan_cleanup(struct btrfs_root *root) */ if (is_bad_inode(inode)) { trans = btrfs_start_transaction(root, 0); - BUG_ON(IS_ERR(trans)); btrfs_orphan_del(trans, inode); btrfs_end_transaction(trans, root); iput(inode); @@ -2385,7 +2381,6 @@ void btrfs_orphan_cleanup(struct btrfs_root *root) if (root->orphan_block_rsv || root->orphan_item_inserted) { trans = btrfs_join_transaction(root, 1); - BUG_ON(IS_ERR(trans)); btrfs_end_transaction(trans, root); } @@ -2646,7 +2641,7 @@ int btrfs_unlink_inode(struct btrfs_trans_handle *trans, path = btrfs_alloc_path(); if (!path) { ret = -ENOMEM; - goto out; + goto err; } path->leave_spinning = 1; @@ -2719,10 +2714,9 @@ static int check_path_shared(struct btrfs_root *root, struct extent_buffer *eb; int level; u64 refs = 1; + int uninitialized_var(ret); for (level = 0; level < BTRFS_MAX_LEVEL; level++) { - int ret; - if (!path->nodes[level]) break; eb = path->nodes[level]; @@ -2733,7 +2727,7 @@ static int check_path_shared(struct btrfs_root *root, if (refs > 1) return 1; } - return 0; + return ret; /* XXX callers? */ } /* @@ -4140,7 +4134,7 @@ struct inode *btrfs_lookup_dentry(struct inode *dir, struct dentry *dentry) } srcu_read_unlock(&root->fs_info->subvol_srcu, index); - if (!IS_ERR(inode) && root != sub_root) { + if (root != sub_root) { down_read(&root->fs_info->cleanup_work_sem); if (!(inode->i_sb->s_flags & MS_RDONLY)) btrfs_orphan_cleanup(sub_root); @@ -4353,8 +4347,6 @@ int btrfs_write_inode(struct inode *inode, struct writeback_control *wbc) trans = btrfs_join_transaction_nolock(root, 1); else trans = btrfs_join_transaction(root, 1); - if (IS_ERR(trans)) - return PTR_ERR(trans); btrfs_set_trans_block_group(trans, inode); if (nolock) ret = btrfs_end_transaction_nolock(trans, root); @@ -4380,7 +4372,6 @@ void btrfs_dirty_inode(struct inode *inode) return; trans = btrfs_join_transaction(root, 1); - BUG_ON(IS_ERR(trans)); btrfs_set_trans_block_group(trans, inode); ret = btrfs_update_inode(trans, root, inode); @@ -5185,8 +5176,6 @@ struct extent_map *btrfs_get_extent(struct inode *inode, struct page *page, em = NULL; btrfs_release_path(root, path); trans = btrfs_join_transaction(root, 1); - if (IS_ERR(trans)) - return ERR_CAST(trans); goto again; } map = kmap(page); @@ -5291,8 +5280,8 @@ static struct extent_map *btrfs_new_extent_direct(struct inode *inode, btrfs_drop_extent_cache(inode, start, start + len - 1, 0); trans = btrfs_join_transaction(root, 0); - if (IS_ERR(trans)) - return ERR_CAST(trans); + if (!trans) + return ERR_PTR(-ENOMEM); trans->block_rsv = &root->fs_info->delalloc_block_rsv; @@ -5516,7 +5505,7 @@ static int btrfs_get_blocks_direct(struct inode *inode, sector_t iblock, * while we look for nocow cross refs */ trans = btrfs_join_transaction(root, 0); - if (IS_ERR(trans)) + if (!trans) goto must_cow; if (can_nocow_odirect(trans, inode, start, len) == 1) { @@ -5651,7 +5640,7 @@ static void btrfs_endio_direct_write(struct bio *bio, int err) BUG_ON(!ordered); trans = btrfs_join_transaction(root, 1); - if (IS_ERR(trans)) { + if (!trans) { err = -ENOMEM; goto out; } diff --git a/trunk/fs/btrfs/ioctl.c b/trunk/fs/btrfs/ioctl.c index 02d224e8c83f..a506a22b522a 100644 --- a/trunk/fs/btrfs/ioctl.c +++ b/trunk/fs/btrfs/ioctl.c @@ -203,7 +203,7 @@ static int btrfs_ioctl_setflags(struct file *file, void __user *arg) trans = btrfs_join_transaction(root, 1); - BUG_ON(IS_ERR(trans)); + BUG_ON(!trans); ret = btrfs_update_inode(trans, root, inode); BUG_ON(ret); @@ -907,10 +907,6 @@ static noinline int btrfs_ioctl_resize(struct btrfs_root *root, if (new_size > old_size) { trans = btrfs_start_transaction(root, 0); - if (IS_ERR(trans)) { - ret = PTR_ERR(trans); - goto out_unlock; - } ret = btrfs_grow_device(trans, device, new_size); btrfs_commit_transaction(trans, root); } else { @@ -1902,10 +1898,7 @@ static noinline long btrfs_ioctl_clone(struct file *file, unsigned long srcfd, memcpy(&new_key, &key, sizeof(new_key)); new_key.objectid = inode->i_ino; - if (off <= key.offset) - new_key.offset = key.offset + destoff - off; - else - new_key.offset = destoff; + new_key.offset = key.offset + destoff - off; trans = btrfs_start_transaction(root, 1); if (IS_ERR(trans)) { @@ -2089,7 +2082,7 @@ static long btrfs_ioctl_trans_start(struct file *file) ret = -ENOMEM; trans = btrfs_start_ioctl_transaction(root, 0); - if (IS_ERR(trans)) + if (!trans) goto out_drop; file->private_data = trans; @@ -2145,9 +2138,9 @@ static long btrfs_ioctl_default_subvol(struct file *file, void __user *argp) path->leave_spinning = 1; trans = btrfs_start_transaction(root, 1); - if (IS_ERR(trans)) { + if (!trans) { btrfs_free_path(path); - return PTR_ERR(trans); + return -ENOMEM; } dir_id = btrfs_super_root_dir(&root->fs_info->super_copy); @@ -2341,8 +2334,6 @@ static noinline long btrfs_ioctl_start_sync(struct file *file, void __user *argp u64 transid; trans = btrfs_start_transaction(root, 0); - if (IS_ERR(trans)) - return PTR_ERR(trans); transid = trans->transid; btrfs_commit_transaction_async(trans, root, 0); diff --git a/trunk/fs/btrfs/ordered-data.c b/trunk/fs/btrfs/ordered-data.c index 083a55477375..2b61e1ddcd99 100644 --- a/trunk/fs/btrfs/ordered-data.c +++ b/trunk/fs/btrfs/ordered-data.c @@ -141,7 +141,7 @@ static inline struct rb_node *tree_search(struct btrfs_ordered_inode_tree *tree, u64 file_offset) { struct rb_root *root = &tree->tree; - struct rb_node *prev = NULL; + struct rb_node *prev; struct rb_node *ret; struct btrfs_ordered_extent *entry; diff --git a/trunk/fs/btrfs/print-tree.c b/trunk/fs/btrfs/print-tree.c index fb2605d998e9..0d126be22b63 100644 --- a/trunk/fs/btrfs/print-tree.c +++ b/trunk/fs/btrfs/print-tree.c @@ -260,7 +260,6 @@ void btrfs_print_leaf(struct btrfs_root *root, struct extent_buffer *l) #else BUG(); #endif - break; case BTRFS_BLOCK_GROUP_ITEM_KEY: bi = btrfs_item_ptr(l, i, struct btrfs_block_group_item); diff --git a/trunk/fs/btrfs/relocation.c b/trunk/fs/btrfs/relocation.c index 1f5556acb530..045c9c2b2d7e 100644 --- a/trunk/fs/btrfs/relocation.c +++ b/trunk/fs/btrfs/relocation.c @@ -2028,7 +2028,6 @@ static noinline_for_stack int merge_reloc_root(struct reloc_control *rc, while (1) { trans = btrfs_start_transaction(root, 0); - BUG_ON(IS_ERR(trans)); trans->block_rsv = rc->block_rsv; ret = btrfs_block_rsv_check(trans, root, rc->block_rsv, @@ -2148,12 +2147,6 @@ int prepare_to_merge(struct reloc_control *rc, int err) } trans = btrfs_join_transaction(rc->extent_root, 1); - if (IS_ERR(trans)) { - if (!err) - btrfs_block_rsv_release(rc->extent_root, - rc->block_rsv, num_bytes); - return PTR_ERR(trans); - } if (!err) { if (num_bytes != rc->merging_rsv_size) { @@ -3229,7 +3222,6 @@ static int delete_block_group_cache(struct btrfs_fs_info *fs_info, trans = btrfs_join_transaction(root, 0); if (IS_ERR(trans)) { btrfs_free_path(path); - ret = PTR_ERR(trans); goto out; } @@ -3636,7 +3628,6 @@ int prepare_to_relocate(struct reloc_control *rc) set_reloc_control(rc); trans = btrfs_join_transaction(rc->extent_root, 1); - BUG_ON(IS_ERR(trans)); btrfs_commit_transaction(trans, rc->extent_root); return 0; } @@ -3666,7 +3657,6 @@ static noinline_for_stack int relocate_block_group(struct reloc_control *rc) while (1) { trans = btrfs_start_transaction(rc->extent_root, 0); - BUG_ON(IS_ERR(trans)); if (update_backref_cache(trans, &rc->backref_cache)) { btrfs_end_transaction(trans, rc->extent_root); @@ -3814,10 +3804,7 @@ static noinline_for_stack int relocate_block_group(struct reloc_control *rc) /* get rid of pinned extents */ trans = btrfs_join_transaction(rc->extent_root, 1); - if (IS_ERR(trans)) - err = PTR_ERR(trans); - else - btrfs_commit_transaction(trans, rc->extent_root); + btrfs_commit_transaction(trans, rc->extent_root); out_free: btrfs_free_block_rsv(rc->extent_root, rc->block_rsv); btrfs_free_path(path); @@ -4035,7 +4022,6 @@ static noinline_for_stack int mark_garbage_root(struct btrfs_root *root) int ret; trans = btrfs_start_transaction(root->fs_info->tree_root, 0); - BUG_ON(IS_ERR(trans)); memset(&root->root_item.drop_progress, 0, sizeof(root->root_item.drop_progress)); @@ -4139,11 +4125,6 @@ int btrfs_recover_relocation(struct btrfs_root *root) set_reloc_control(rc); trans = btrfs_join_transaction(rc->extent_root, 1); - if (IS_ERR(trans)) { - unset_reloc_control(rc); - err = PTR_ERR(trans); - goto out_free; - } rc->merge_reloc_tree = 1; @@ -4173,13 +4154,9 @@ int btrfs_recover_relocation(struct btrfs_root *root) unset_reloc_control(rc); trans = btrfs_join_transaction(rc->extent_root, 1); - if (IS_ERR(trans)) - err = PTR_ERR(trans); - else - btrfs_commit_transaction(trans, rc->extent_root); -out_free: - kfree(rc); + btrfs_commit_transaction(trans, rc->extent_root); out: + kfree(rc); while (!list_empty(&reloc_roots)) { reloc_root = list_entry(reloc_roots.next, struct btrfs_root, root_list); diff --git a/trunk/fs/btrfs/super.c b/trunk/fs/btrfs/super.c index a004008f7d28..b2130c46fdb5 100644 --- a/trunk/fs/btrfs/super.c +++ b/trunk/fs/btrfs/super.c @@ -383,7 +383,7 @@ static int btrfs_parse_early_options(const char *options, fmode_t flags, struct btrfs_fs_devices **fs_devices) { substring_t args[MAX_OPT_ARGS]; - char *opts, *orig, *p; + char *opts, *p; int error = 0; int intarg; @@ -397,7 +397,6 @@ static int btrfs_parse_early_options(const char *options, fmode_t flags, opts = kstrdup(options, GFP_KERNEL); if (!opts) return -ENOMEM; - orig = opts; while ((p = strsep(&opts, ",")) != NULL) { int token; @@ -433,7 +432,7 @@ static int btrfs_parse_early_options(const char *options, fmode_t flags, } out_free_opts: - kfree(orig); + kfree(opts); out: /* * If no subvolume name is specified we use the default one. Allocate @@ -624,8 +623,6 @@ int btrfs_sync_fs(struct super_block *sb, int wait) btrfs_wait_ordered_extents(root, 0, 0); trans = btrfs_start_transaction(root, 0); - if (IS_ERR(trans)) - return PTR_ERR(trans); ret = btrfs_commit_transaction(trans, root); return ret; } @@ -764,8 +761,6 @@ static struct dentry *btrfs_mount(struct file_system_type *fs_type, int flags, } btrfs_close_devices(fs_devices); - kfree(fs_info); - kfree(tree_root); } else { char b[BDEVNAME_SIZE]; diff --git a/trunk/fs/btrfs/transaction.c b/trunk/fs/btrfs/transaction.c index 3d73c8d93bbb..bae5c7b8bbe2 100644 --- a/trunk/fs/btrfs/transaction.c +++ b/trunk/fs/btrfs/transaction.c @@ -1161,11 +1161,6 @@ int btrfs_commit_transaction_async(struct btrfs_trans_handle *trans, INIT_DELAYED_WORK(&ac->work, do_async_commit); ac->root = root; ac->newtrans = btrfs_join_transaction(root, 0); - if (IS_ERR(ac->newtrans)) { - int err = PTR_ERR(ac->newtrans); - kfree(ac); - return err; - } /* take transaction reference */ mutex_lock(&root->fs_info->trans_mutex); diff --git a/trunk/fs/btrfs/tree-log.c b/trunk/fs/btrfs/tree-log.c index a4bbb854dfd2..054744ac5719 100644 --- a/trunk/fs/btrfs/tree-log.c +++ b/trunk/fs/btrfs/tree-log.c @@ -338,12 +338,6 @@ static noinline int overwrite_item(struct btrfs_trans_handle *trans, } dst_copy = kmalloc(item_size, GFP_NOFS); src_copy = kmalloc(item_size, GFP_NOFS); - if (!dst_copy || !src_copy) { - btrfs_release_path(root, path); - kfree(dst_copy); - kfree(src_copy); - return -ENOMEM; - } read_extent_buffer(eb, src_copy, src_ptr, item_size); @@ -671,9 +665,6 @@ static noinline int drop_one_dir_item(struct btrfs_trans_handle *trans, btrfs_dir_item_key_to_cpu(leaf, di, &location); name_len = btrfs_dir_name_len(leaf, di); name = kmalloc(name_len, GFP_NOFS); - if (!name) - return -ENOMEM; - read_extent_buffer(leaf, name, (unsigned long)(di + 1), name_len); btrfs_release_path(root, path); @@ -753,9 +744,6 @@ static noinline int backref_in_log(struct btrfs_root *log, int match = 0; path = btrfs_alloc_path(); - if (!path) - return -ENOMEM; - ret = btrfs_search_slot(NULL, log, key, path, 0, 0); if (ret != 0) goto out; @@ -979,8 +967,6 @@ static noinline int fixup_inode_link_count(struct btrfs_trans_handle *trans, key.offset = (u64)-1; path = btrfs_alloc_path(); - if (!path) - return -ENOMEM; while (1) { ret = btrfs_search_slot(NULL, root, &key, path, 0, 0); @@ -1192,9 +1178,6 @@ static noinline int replay_one_name(struct btrfs_trans_handle *trans, name_len = btrfs_dir_name_len(eb, di); name = kmalloc(name_len, GFP_NOFS); - if (!name) - return -ENOMEM; - log_type = btrfs_dir_type(eb, di); read_extent_buffer(eb, name, (unsigned long)(di + 1), name_len); @@ -1709,8 +1692,6 @@ static noinline int walk_down_log_tree(struct btrfs_trans_handle *trans, root_owner = btrfs_header_owner(parent); next = btrfs_find_create_tree_block(root, bytenr, blocksize); - if (!next) - return -ENOMEM; if (*level == 1) { wc->process_func(root, next, wc, ptr_gen); @@ -2051,7 +2032,6 @@ int btrfs_sync_log(struct btrfs_trans_handle *trans, wait_log_commit(trans, log_root_tree, log_root_tree->log_transid); mutex_unlock(&log_root_tree->log_mutex); - ret = 0; goto out; } atomic_set(&log_root_tree->log_commit[index2], 1); @@ -2116,7 +2096,7 @@ int btrfs_sync_log(struct btrfs_trans_handle *trans, smp_mb(); if (waitqueue_active(&root->log_commit_wait[index1])) wake_up(&root->log_commit_wait[index1]); - return ret; + return 0; } static void free_log_tree(struct btrfs_trans_handle *trans, @@ -2214,9 +2194,6 @@ int btrfs_del_dir_entries_in_log(struct btrfs_trans_handle *trans, log = root->log_root; path = btrfs_alloc_path(); - if (!path) - return -ENOMEM; - di = btrfs_lookup_dir_item(trans, log, path, dir->i_ino, name, name_len, -1); if (IS_ERR(di)) { @@ -2617,9 +2594,6 @@ static noinline int copy_items(struct btrfs_trans_handle *trans, ins_data = kmalloc(nr * sizeof(struct btrfs_key) + nr * sizeof(u32), GFP_NOFS); - if (!ins_data) - return -ENOMEM; - ins_sizes = (u32 *)ins_data; ins_keys = (struct btrfs_key *)(ins_data + nr * sizeof(u32)); @@ -2751,13 +2725,7 @@ static int btrfs_log_inode(struct btrfs_trans_handle *trans, log = root->log_root; path = btrfs_alloc_path(); - if (!path) - return -ENOMEM; dst_path = btrfs_alloc_path(); - if (!dst_path) { - btrfs_free_path(path); - return -ENOMEM; - } min_key.objectid = inode->i_ino; min_key.type = BTRFS_INODE_ITEM_KEY; @@ -3112,7 +3080,6 @@ int btrfs_recover_log_trees(struct btrfs_root *log_root_tree) BUG_ON(!path); trans = btrfs_start_transaction(fs_info->tree_root, 0); - BUG_ON(IS_ERR(trans)); wc.trans = trans; wc.pin = 1; diff --git a/trunk/fs/btrfs/volumes.c b/trunk/fs/btrfs/volumes.c index 2636a051e4b2..d158530233b7 100644 --- a/trunk/fs/btrfs/volumes.c +++ b/trunk/fs/btrfs/volumes.c @@ -1213,10 +1213,6 @@ static int btrfs_rm_dev_item(struct btrfs_root *root, return -ENOMEM; trans = btrfs_start_transaction(root, 0); - if (IS_ERR(trans)) { - btrfs_free_path(path); - return PTR_ERR(trans); - } key.objectid = BTRFS_DEV_ITEMS_OBJECTID; key.type = BTRFS_DEV_ITEM_KEY; key.offset = device->devid; @@ -1610,12 +1606,6 @@ int btrfs_init_new_device(struct btrfs_root *root, char *device_path) } trans = btrfs_start_transaction(root, 0); - if (IS_ERR(trans)) { - kfree(device); - ret = PTR_ERR(trans); - goto error; - } - lock_chunks(root); device->writeable = 1; @@ -1883,7 +1873,7 @@ static int btrfs_relocate_chunk(struct btrfs_root *root, return ret; trans = btrfs_start_transaction(root, 0); - BUG_ON(IS_ERR(trans)); + BUG_ON(!trans); lock_chunks(root); @@ -2057,7 +2047,7 @@ int btrfs_balance(struct btrfs_root *dev_root) BUG_ON(ret); trans = btrfs_start_transaction(dev_root, 0); - BUG_ON(IS_ERR(trans)); + BUG_ON(!trans); ret = btrfs_grow_device(trans, device, old_size); BUG_ON(ret); @@ -2223,11 +2213,6 @@ int btrfs_shrink_device(struct btrfs_device *device, u64 new_size) /* Shrinking succeeded, else we would be at "done". */ trans = btrfs_start_transaction(root, 0); - if (IS_ERR(trans)) { - ret = PTR_ERR(trans); - goto done; - } - lock_chunks(root); device->disk_total_bytes = new_size; diff --git a/trunk/fs/cifs/cifsacl.c b/trunk/fs/cifs/cifsacl.c index beeebf194234..1e7636b145a8 100644 --- a/trunk/fs/cifs/cifsacl.c +++ b/trunk/fs/cifs/cifsacl.c @@ -372,10 +372,6 @@ static void parse_dacl(struct cifs_acl *pdacl, char *end_of_acl, ppace = kmalloc(num_aces * sizeof(struct cifs_ace *), GFP_KERNEL); - if (!ppace) { - cERROR(1, "DACL memory allocation error"); - return; - } for (i = 0; i < num_aces; ++i) { ppace[i] = (struct cifs_ace *) (acl_base + acl_size); diff --git a/trunk/fs/cifs/cifssmb.c b/trunk/fs/cifs/cifssmb.c index 904aa47e3515..46c66ed01af4 100644 --- a/trunk/fs/cifs/cifssmb.c +++ b/trunk/fs/cifs/cifssmb.c @@ -136,6 +136,9 @@ cifs_reconnect_tcon(struct cifsTconInfo *tcon, int smb_command) } } + if (ses->status == CifsExiting) + return -EIO; + /* * Give demultiplex thread up to 10 seconds to reconnect, should be * greater than cifs socket timeout which is 7 seconds @@ -153,7 +156,7 @@ cifs_reconnect_tcon(struct cifsTconInfo *tcon, int smb_command) * retrying until process is killed or server comes * back on-line */ - if (!tcon->retry) { + if (!tcon->retry || ses->status == CifsExiting) { cFYI(1, "gave up waiting on reconnect in smb_init"); return -EHOSTDOWN; } diff --git a/trunk/fs/cifs/connect.c b/trunk/fs/cifs/connect.c index 257b6d895e20..47d8ff623683 100644 --- a/trunk/fs/cifs/connect.c +++ b/trunk/fs/cifs/connect.c @@ -337,12 +337,8 @@ cifs_echo_request(struct work_struct *work) struct TCP_Server_Info *server = container_of(work, struct TCP_Server_Info, echo.work); - /* - * We cannot send an echo until the NEGOTIATE_PROTOCOL request is done. - * Also, no need to ping if we got a response recently - */ - if (server->tcpStatus != CifsGood || - time_before(jiffies, server->lstrp + SMB_ECHO_INTERVAL - HZ)) + /* no need to ping if we got a response recently */ + if (time_before(jiffies, server->lstrp + SMB_ECHO_INTERVAL - HZ)) goto requeue_echo; rc = CIFSSMBEcho(server); @@ -582,12 +578,12 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server) else if (reconnect == 1) continue; - total_read += 4; /* account for rfc1002 hdr */ + length += 4; /* account for rfc1002 hdr */ - dump_smb(smb_buffer, total_read); - if (checkSMB(smb_buffer, smb_buffer->Mid, total_read)) { - cifs_dump_mem("Bad SMB: ", smb_buffer, - total_read < 48 ? total_read : 48); + + dump_smb(smb_buffer, length); + if (checkSMB(smb_buffer, smb_buffer->Mid, total_read+4)) { + cifs_dump_mem("Bad SMB: ", smb_buffer, 48); continue; } @@ -637,11 +633,11 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server) mid_entry->largeBuf = isLargeBuf; multi_t2_fnd: mid_entry->midState = MID_RESPONSE_RECEIVED; + list_del_init(&mid_entry->qhead); + mid_entry->callback(mid_entry); #ifdef CONFIG_CIFS_STATS2 mid_entry->when_received = jiffies; #endif - list_del_init(&mid_entry->qhead); - mid_entry->callback(mid_entry); break; } mid_entry = NULL; diff --git a/trunk/fs/cifs/file.c b/trunk/fs/cifs/file.c index e964b1cd5dd0..74c0a282d012 100644 --- a/trunk/fs/cifs/file.c +++ b/trunk/fs/cifs/file.c @@ -1662,10 +1662,10 @@ static ssize_t cifs_iovec_write(struct file *file, const struct iovec *iov, unsigned long nr_segs, loff_t *poffset) { - unsigned int written; - unsigned long num_pages, npages, i; - size_t copied, len, cur_len; - ssize_t total_written = 0; + size_t total_written = 0; + unsigned int written = 0; + unsigned long num_pages, npages; + size_t copied, len, cur_len, i; struct kvec *to_send; struct page **pages; struct iov_iter it; @@ -1821,8 +1821,7 @@ cifs_iovec_read(struct file *file, const struct iovec *iov, { int rc; int xid; - ssize_t total_read; - unsigned int bytes_read = 0; + unsigned int total_read, bytes_read = 0; size_t len, cur_len; int iov_offset = 0; struct cifs_sb_info *cifs_sb; diff --git a/trunk/fs/cifs/transport.c b/trunk/fs/cifs/transport.c index fbc5aace54b1..b8c5e2eb43d0 100644 --- a/trunk/fs/cifs/transport.c +++ b/trunk/fs/cifs/transport.c @@ -359,10 +359,6 @@ cifs_call_async(struct TCP_Server_Info *server, struct smb_hdr *in_buf, if (rc) return rc; - /* enable signing if server requires it */ - if (server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED)) - in_buf->Flags2 |= SMBFLG2_SECURITY_SIGNATURE; - mutex_lock(&server->srv_mutex); mid = AllocMidQEntry(in_buf, server); if (mid == NULL) { diff --git a/trunk/fs/file_table.c b/trunk/fs/file_table.c index eb36b6b17e26..c3e89adf53c0 100644 --- a/trunk/fs/file_table.c +++ b/trunk/fs/file_table.c @@ -125,13 +125,13 @@ struct file *get_empty_filp(void) goto fail; percpu_counter_inc(&nr_files); - f->f_cred = get_cred(cred); if (security_file_alloc(f)) goto fail_sec; INIT_LIST_HEAD(&f->f_u.fu_list); atomic_long_set(&f->f_count, 1); rwlock_init(&f->f_owner.lock); + f->f_cred = get_cred(cred); spin_lock_init(&f->f_lock); eventpoll_init_file(f); /* f->f_version: 0 */ diff --git a/trunk/fs/hfsplus/extents.c b/trunk/fs/hfsplus/extents.c index b1991a2a08e0..52a0bcaa7b6d 100644 --- a/trunk/fs/hfsplus/extents.c +++ b/trunk/fs/hfsplus/extents.c @@ -397,8 +397,8 @@ int hfsplus_file_extend(struct inode *inode) u32 start, len, goal; int res; - if (sbi->alloc_file->i_size * 8 < - sbi->total_blocks - sbi->free_blocks + 8) { + if (sbi->total_blocks - sbi->free_blocks + 8 > + sbi->alloc_file->i_size * 8) { /* extend alloc file */ printk(KERN_ERR "hfs: extend alloc file! " "(%llu,%u,%u)\n", diff --git a/trunk/fs/hfsplus/part_tbl.c b/trunk/fs/hfsplus/part_tbl.c index 40ad88c12c64..d66ad113b1cc 100644 --- a/trunk/fs/hfsplus/part_tbl.c +++ b/trunk/fs/hfsplus/part_tbl.c @@ -134,7 +134,7 @@ int hfs_part_find(struct super_block *sb, res = hfsplus_submit_bio(sb->s_bdev, *part_start + HFS_PMAP_BLK, data, READ); if (res) - goto out; + return res; switch (be16_to_cpu(*((__be16 *)data))) { case HFS_OLD_PMAP_MAGIC: @@ -147,7 +147,7 @@ int hfs_part_find(struct super_block *sb, res = -ENOENT; break; } -out: + kfree(data); return res; } diff --git a/trunk/fs/hfsplus/super.c b/trunk/fs/hfsplus/super.c index b49b55584c84..9a3b4795f43c 100644 --- a/trunk/fs/hfsplus/super.c +++ b/trunk/fs/hfsplus/super.c @@ -338,22 +338,20 @@ static int hfsplus_fill_super(struct super_block *sb, void *data, int silent) struct inode *root, *inode; struct qstr str; struct nls_table *nls = NULL; - int err; + int err = -EINVAL; - err = -EINVAL; sbi = kzalloc(sizeof(*sbi), GFP_KERNEL); if (!sbi) - goto out; + return -ENOMEM; sb->s_fs_info = sbi; mutex_init(&sbi->alloc_mutex); mutex_init(&sbi->vh_mutex); hfsplus_fill_defaults(sbi); - - err = -EINVAL; if (!hfsplus_parse_options(data, sbi)) { printk(KERN_ERR "hfs: unable to parse mount options\n"); - goto out_unload_nls; + err = -EINVAL; + goto cleanup; } /* temporarily use utf8 to correctly find the hidden dir below */ @@ -361,14 +359,16 @@ static int hfsplus_fill_super(struct super_block *sb, void *data, int silent) sbi->nls = load_nls("utf8"); if (!sbi->nls) { printk(KERN_ERR "hfs: unable to load nls for utf8\n"); - goto out_unload_nls; + err = -EINVAL; + goto cleanup; } /* Grab the volume header */ if (hfsplus_read_wrapper(sb)) { if (!silent) printk(KERN_WARNING "hfs: unable to find HFS+ superblock\n"); - goto out_unload_nls; + err = -EINVAL; + goto cleanup; } vhdr = sbi->s_vhdr; @@ -377,7 +377,7 @@ static int hfsplus_fill_super(struct super_block *sb, void *data, int silent) if (be16_to_cpu(vhdr->version) < HFSPLUS_MIN_VERSION || be16_to_cpu(vhdr->version) > HFSPLUS_CURRENT_VERSION) { printk(KERN_ERR "hfs: wrong filesystem version\n"); - goto out_free_vhdr; + goto cleanup; } sbi->total_blocks = be32_to_cpu(vhdr->total_blocks); sbi->free_blocks = be32_to_cpu(vhdr->free_blocks); @@ -421,19 +421,19 @@ static int hfsplus_fill_super(struct super_block *sb, void *data, int silent) sbi->ext_tree = hfs_btree_open(sb, HFSPLUS_EXT_CNID); if (!sbi->ext_tree) { printk(KERN_ERR "hfs: failed to load extents file\n"); - goto out_free_vhdr; + goto cleanup; } sbi->cat_tree = hfs_btree_open(sb, HFSPLUS_CAT_CNID); if (!sbi->cat_tree) { printk(KERN_ERR "hfs: failed to load catalog file\n"); - goto out_close_ext_tree; + goto cleanup; } inode = hfsplus_iget(sb, HFSPLUS_ALLOC_CNID); if (IS_ERR(inode)) { printk(KERN_ERR "hfs: failed to load allocation file\n"); err = PTR_ERR(inode); - goto out_close_cat_tree; + goto cleanup; } sbi->alloc_file = inode; @@ -442,7 +442,14 @@ static int hfsplus_fill_super(struct super_block *sb, void *data, int silent) if (IS_ERR(root)) { printk(KERN_ERR "hfs: failed to load root directory\n"); err = PTR_ERR(root); - goto out_put_alloc_file; + goto cleanup; + } + sb->s_d_op = &hfsplus_dentry_operations; + sb->s_root = d_alloc_root(root); + if (!sb->s_root) { + iput(root); + err = -ENOMEM; + goto cleanup; } str.len = sizeof(HFSP_HIDDENDIR_NAME) - 1; @@ -452,69 +459,46 @@ static int hfsplus_fill_super(struct super_block *sb, void *data, int silent) if (!hfs_brec_read(&fd, &entry, sizeof(entry))) { hfs_find_exit(&fd); if (entry.type != cpu_to_be16(HFSPLUS_FOLDER)) - goto out_put_root; + goto cleanup; inode = hfsplus_iget(sb, be32_to_cpu(entry.folder.id)); if (IS_ERR(inode)) { err = PTR_ERR(inode); - goto out_put_root; + goto cleanup; } sbi->hidden_dir = inode; } else hfs_find_exit(&fd); - if (!(sb->s_flags & MS_RDONLY)) { - /* - * H+LX == hfsplusutils, H+Lx == this driver, H+lx is unused - * all three are registered with Apple for our use - */ - vhdr->last_mount_vers = cpu_to_be32(HFSP_MOUNT_VERSION); - vhdr->modify_date = hfsp_now2mt(); - be32_add_cpu(&vhdr->write_count, 1); - vhdr->attributes &= cpu_to_be32(~HFSPLUS_VOL_UNMNT); - vhdr->attributes |= cpu_to_be32(HFSPLUS_VOL_INCNSTNT); - hfsplus_sync_fs(sb, 1); - - if (!sbi->hidden_dir) { - mutex_lock(&sbi->vh_mutex); - sbi->hidden_dir = hfsplus_new_inode(sb, S_IFDIR); - hfsplus_create_cat(sbi->hidden_dir->i_ino, root, &str, - sbi->hidden_dir); - mutex_unlock(&sbi->vh_mutex); - - hfsplus_mark_inode_dirty(sbi->hidden_dir, - HFSPLUS_I_CAT_DIRTY); - } - } + if (sb->s_flags & MS_RDONLY) + goto out; - sb->s_d_op = &hfsplus_dentry_operations; - sb->s_root = d_alloc_root(root); - if (!sb->s_root) { - err = -ENOMEM; - goto out_put_hidden_dir; + /* H+LX == hfsplusutils, H+Lx == this driver, H+lx is unused + * all three are registered with Apple for our use + */ + vhdr->last_mount_vers = cpu_to_be32(HFSP_MOUNT_VERSION); + vhdr->modify_date = hfsp_now2mt(); + be32_add_cpu(&vhdr->write_count, 1); + vhdr->attributes &= cpu_to_be32(~HFSPLUS_VOL_UNMNT); + vhdr->attributes |= cpu_to_be32(HFSPLUS_VOL_INCNSTNT); + hfsplus_sync_fs(sb, 1); + + if (!sbi->hidden_dir) { + mutex_lock(&sbi->vh_mutex); + sbi->hidden_dir = hfsplus_new_inode(sb, S_IFDIR); + hfsplus_create_cat(sbi->hidden_dir->i_ino, sb->s_root->d_inode, + &str, sbi->hidden_dir); + mutex_unlock(&sbi->vh_mutex); + + hfsplus_mark_inode_dirty(sbi->hidden_dir, HFSPLUS_I_CAT_DIRTY); } - +out: unload_nls(sbi->nls); sbi->nls = nls; return 0; -out_put_hidden_dir: - iput(sbi->hidden_dir); -out_put_root: - iput(sbi->alloc_file); -out_put_alloc_file: - iput(sbi->alloc_file); -out_close_cat_tree: - hfs_btree_close(sbi->cat_tree); -out_close_ext_tree: - hfs_btree_close(sbi->ext_tree); -out_free_vhdr: - kfree(sbi->s_vhdr); - kfree(sbi->s_backup_vhdr); -out_unload_nls: - unload_nls(sbi->nls); +cleanup: + hfsplus_put_super(sb); unload_nls(nls); - kfree(sbi); -out: return err; } diff --git a/trunk/fs/hfsplus/wrapper.c b/trunk/fs/hfsplus/wrapper.c index 3031d81f5f0f..196231794f64 100644 --- a/trunk/fs/hfsplus/wrapper.c +++ b/trunk/fs/hfsplus/wrapper.c @@ -167,7 +167,7 @@ int hfsplus_read_wrapper(struct super_block *sb) break; case cpu_to_be16(HFSP_WRAP_MAGIC): if (!hfsplus_read_mdb(sbi->s_vhdr, &wd)) - goto out_free_backup_vhdr; + goto out; wd.ablk_size >>= HFSPLUS_SECTOR_SHIFT; part_start += wd.ablk_start + wd.embed_start * wd.ablk_size; part_size = wd.embed_count * wd.ablk_size; @@ -179,7 +179,7 @@ int hfsplus_read_wrapper(struct super_block *sb) * (should do this only for cdrom/loop though) */ if (hfs_part_find(sb, &part_start, &part_size)) - goto out_free_backup_vhdr; + goto out; goto reread; } diff --git a/trunk/include/drm/drmP.h b/trunk/include/drm/drmP.h index fe29aadb129d..a4694c610330 100644 --- a/trunk/include/drm/drmP.h +++ b/trunk/include/drm/drmP.h @@ -1367,7 +1367,7 @@ extern int drm_vblank_wait(struct drm_device *dev, unsigned int *vbl_seq); extern u32 drm_vblank_count(struct drm_device *dev, int crtc); extern u32 drm_vblank_count_and_time(struct drm_device *dev, int crtc, struct timeval *vblanktime); -extern bool drm_handle_vblank(struct drm_device *dev, int crtc); +extern void drm_handle_vblank(struct drm_device *dev, int crtc); extern int drm_vblank_get(struct drm_device *dev, int crtc); extern void drm_vblank_put(struct drm_device *dev, int crtc); extern void drm_vblank_off(struct drm_device *dev, int crtc); diff --git a/trunk/include/drm/drm_crtc.h b/trunk/include/drm/drm_crtc.h index 801be59f4f15..acd7fade160d 100644 --- a/trunk/include/drm/drm_crtc.h +++ b/trunk/include/drm/drm_crtc.h @@ -275,7 +275,6 @@ struct drm_pending_vblank_event; /** * drm_crtc_funcs - control CRTCs for a given device - * @reset: reset CRTC after state has been invalidate (e.g. resume) * @dpms: control display power levels * @save: save CRTC state * @resore: restore CRTC state @@ -303,8 +302,6 @@ struct drm_crtc_funcs { void (*save)(struct drm_crtc *crtc); /* suspend? */ /* Restore CRTC state */ void (*restore)(struct drm_crtc *crtc); /* resume? */ - /* Reset CRTC state */ - void (*reset)(struct drm_crtc *crtc); /* cursor controls */ int (*cursor_set)(struct drm_crtc *crtc, struct drm_file *file_priv, @@ -382,7 +379,6 @@ struct drm_crtc { * @dpms: set power state (see drm_crtc_funcs above) * @save: save connector state * @restore: restore connector state - * @reset: reset connector after state has been invalidate (e.g. resume) * @mode_valid: is this mode valid on the given connector? * @mode_fixup: try to fixup proposed mode for this connector * @mode_set: set this mode @@ -400,7 +396,6 @@ struct drm_connector_funcs { void (*dpms)(struct drm_connector *connector, int mode); void (*save)(struct drm_connector *connector); void (*restore)(struct drm_connector *connector); - void (*reset)(struct drm_connector *connector); /* Check to see if anything is attached to the connector. * @force is set to false whilst polling, true when checking the @@ -418,7 +413,6 @@ struct drm_connector_funcs { }; struct drm_encoder_funcs { - void (*reset)(struct drm_encoder *encoder); void (*destroy)(struct drm_encoder *encoder); }; @@ -662,7 +656,6 @@ extern struct drm_display_mode *drm_mode_duplicate(struct drm_device *dev, struct drm_display_mode *mode); extern void drm_mode_debug_printmodeline(struct drm_display_mode *mode); extern void drm_mode_config_init(struct drm_device *dev); -extern void drm_mode_config_reset(struct drm_device *dev); extern void drm_mode_config_cleanup(struct drm_device *dev); extern void drm_mode_set_name(struct drm_display_mode *mode); extern bool drm_mode_equal(struct drm_display_mode *mode1, struct drm_display_mode *mode2); diff --git a/trunk/include/drm/drm_pciids.h b/trunk/include/drm/drm_pciids.h index 5ff1194dc2ea..fe29ae328bd9 100644 --- a/trunk/include/drm/drm_pciids.h +++ b/trunk/include/drm/drm_pciids.h @@ -28,6 +28,7 @@ {0x1002, 0x4156, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV350}, \ {0x1002, 0x4237, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS200|RADEON_IS_IGP}, \ {0x1002, 0x4242, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R200}, \ + {0x1002, 0x4243, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R200}, \ {0x1002, 0x4336, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS100|RADEON_IS_IGP|RADEON_IS_MOBILITY}, \ {0x1002, 0x4337, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS200|RADEON_IS_IGP|RADEON_IS_MOBILITY}, \ {0x1002, 0x4437, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS200|RADEON_IS_IGP|RADEON_IS_MOBILITY}, \ diff --git a/trunk/include/linux/Kbuild b/trunk/include/linux/Kbuild index b0ada6f37dd6..2296d8b1931f 100644 --- a/trunk/include/linux/Kbuild +++ b/trunk/include/linux/Kbuild @@ -1,6 +1,5 @@ header-y += byteorder/ header-y += can/ -header-y += caif/ header-y += dvb/ header-y += hdlc/ header-y += isdn/ diff --git a/trunk/include/linux/caif/Kbuild b/trunk/include/linux/caif/Kbuild deleted file mode 100644 index a9cf250689dc..000000000000 --- a/trunk/include/linux/caif/Kbuild +++ /dev/null @@ -1,2 +0,0 @@ -header-y += caif_socket.h -header-y += if_caif.h diff --git a/trunk/include/linux/ftrace.h b/trunk/include/linux/ftrace.h index dcd6a7c3a435..ca29e03c1fac 100644 --- a/trunk/include/linux/ftrace.h +++ b/trunk/include/linux/ftrace.h @@ -428,6 +428,7 @@ extern void unregister_ftrace_graph(void); extern void ftrace_graph_init_task(struct task_struct *t); extern void ftrace_graph_exit_task(struct task_struct *t); +extern void ftrace_graph_init_idle_task(struct task_struct *t, int cpu); static inline int task_curr_ret_stack(struct task_struct *t) { @@ -451,6 +452,7 @@ static inline void unpause_graph_tracing(void) static inline void ftrace_graph_init_task(struct task_struct *t) { } static inline void ftrace_graph_exit_task(struct task_struct *t) { } +static inline void ftrace_graph_init_idle_task(struct task_struct *t, int cpu) { } static inline int register_ftrace_graph(trace_func_graph_ret_t retfunc, trace_func_graph_ent_t entryfunc) diff --git a/trunk/include/linux/irq.h b/trunk/include/linux/irq.h index 80fcb53057bc..abde2527c699 100644 --- a/trunk/include/linux/irq.h +++ b/trunk/include/linux/irq.h @@ -74,8 +74,7 @@ typedef void (*irq_flow_handler_t)(unsigned int irq, #define IRQF_MODIFY_MASK \ (IRQ_TYPE_SENSE_MASK | IRQ_NOPROBE | IRQ_NOREQUEST | \ - IRQ_NOAUTOEN | IRQ_MOVE_PCNTXT | IRQ_LEVEL | IRQ_NO_BALANCING | \ - IRQ_PER_CPU) + IRQ_NOAUTOEN | IRQ_MOVE_PCNTXT | IRQ_LEVEL) #ifdef CONFIG_IRQ_PER_CPU # define CHECK_IRQ_PER_CPU(var) ((var) & IRQ_PER_CPU) diff --git a/trunk/include/linux/mroute.h b/trunk/include/linux/mroute.h index b21d567692b2..0fa7a3a874c8 100644 --- a/trunk/include/linux/mroute.h +++ b/trunk/include/linux/mroute.h @@ -150,7 +150,6 @@ static inline int ip_mroute_opt(int opt) extern int ip_mroute_setsockopt(struct sock *, int, char __user *, unsigned int); extern int ip_mroute_getsockopt(struct sock *, int, char __user *, int __user *); extern int ipmr_ioctl(struct sock *sk, int cmd, void __user *arg); -extern int ipmr_compat_ioctl(struct sock *sk, unsigned int cmd, void __user *arg); extern int ip_mr_init(void); #else static inline diff --git a/trunk/include/linux/mroute6.h b/trunk/include/linux/mroute6.h index 9d2deb200f54..6091ab77f388 100644 --- a/trunk/include/linux/mroute6.h +++ b/trunk/include/linux/mroute6.h @@ -136,7 +136,6 @@ extern int ip6_mroute_setsockopt(struct sock *, int, char __user *, unsigned int extern int ip6_mroute_getsockopt(struct sock *, int, char __user *, int __user *); extern int ip6_mr_input(struct sk_buff *skb); extern int ip6mr_ioctl(struct sock *sk, int cmd, void __user *arg); -extern int ip6mr_compat_ioctl(struct sock *sk, unsigned int cmd, void __user *arg); extern int ip6_mr_init(void); extern void ip6_mr_cleanup(void); #else diff --git a/trunk/include/linux/sched.h b/trunk/include/linux/sched.h index 0b40ee3f6d7a..d747f948b34e 100644 --- a/trunk/include/linux/sched.h +++ b/trunk/include/linux/sched.h @@ -2578,6 +2578,13 @@ static inline void inc_syscw(struct task_struct *tsk) #define TASK_SIZE_OF(tsk) TASK_SIZE #endif +/* + * Call the function if the target task is executing on a CPU right now: + */ +extern void task_oncpu_function_call(struct task_struct *p, + void (*func) (void *info), void *info); + + #ifdef CONFIG_MM_OWNER extern void mm_update_next_owner(struct mm_struct *mm); extern void mm_init_owner(struct mm_struct *mm, struct task_struct *p); diff --git a/trunk/include/net/genetlink.h b/trunk/include/net/genetlink.h index b4c7c1cbcf40..8a64b811a39a 100644 --- a/trunk/include/net/genetlink.h +++ b/trunk/include/net/genetlink.h @@ -195,8 +195,7 @@ static inline int genlmsg_end(struct sk_buff *skb, void *hdr) */ static inline void genlmsg_cancel(struct sk_buff *skb, void *hdr) { - if (hdr) - nlmsg_cancel(skb, hdr - GENL_HDRLEN - NLMSG_HDRLEN); + nlmsg_cancel(skb, hdr - GENL_HDRLEN - NLMSG_HDRLEN); } /** diff --git a/trunk/include/net/netfilter/nf_conntrack_ecache.h b/trunk/include/net/netfilter/nf_conntrack_ecache.h index 349cefedc9f3..96ba5f7dcab6 100644 --- a/trunk/include/net/netfilter/nf_conntrack_ecache.h +++ b/trunk/include/net/netfilter/nf_conntrack_ecache.h @@ -77,6 +77,9 @@ nf_conntrack_event_cache(enum ip_conntrack_events event, struct nf_conn *ct) if (e == NULL) return; + if (!(e->ctmask & (1 << event))) + return; + set_bit(event, &e->cache); } diff --git a/trunk/include/net/sock.h b/trunk/include/net/sock.h index bc1cf7d88ccb..d884d268c704 100644 --- a/trunk/include/net/sock.h +++ b/trunk/include/net/sock.h @@ -753,8 +753,6 @@ struct proto { int level, int optname, char __user *optval, int __user *option); - int (*compat_ioctl)(struct sock *sk, - unsigned int cmd, unsigned long arg); #endif int (*sendmsg)(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, size_t len); diff --git a/trunk/include/scsi/scsi.h b/trunk/include/scsi/scsi.h index b76d4006e36d..648d23358038 100644 --- a/trunk/include/scsi/scsi.h +++ b/trunk/include/scsi/scsi.h @@ -9,7 +9,6 @@ #define _SCSI_SCSI_H #include -#include struct scsi_cmnd; diff --git a/trunk/kernel/cred.c b/trunk/kernel/cred.c index 3a9d6dd53a6c..6a1aa004e376 100644 --- a/trunk/kernel/cred.c +++ b/trunk/kernel/cred.c @@ -252,13 +252,13 @@ struct cred *cred_alloc_blank(void) #endif atomic_set(&new->usage, 1); -#ifdef CONFIG_DEBUG_CREDENTIALS - new->magic = CRED_MAGIC; -#endif if (security_cred_alloc_blank(new, GFP_KERNEL) < 0) goto error; +#ifdef CONFIG_DEBUG_CREDENTIALS + new->magic = CRED_MAGIC; +#endif return new; error: @@ -657,8 +657,6 @@ struct cred *prepare_kernel_cred(struct task_struct *daemon) validate_creds(old); *new = *old; - atomic_set(&new->usage, 1); - set_cred_subscribers(new, 0); get_uid(new->user); get_group_info(new->group_info); @@ -676,6 +674,8 @@ struct cred *prepare_kernel_cred(struct task_struct *daemon) if (security_prepare_creds(new, old, GFP_KERNEL) < 0) goto error; + atomic_set(&new->usage, 1); + set_cred_subscribers(new, 0); put_cred(old); validate_creds(new); return new; @@ -748,11 +748,7 @@ bool creds_are_invalid(const struct cred *cred) if (cred->magic != CRED_MAGIC) return true; #ifdef CONFIG_SECURITY_SELINUX - /* - * cred->security == NULL if security_cred_alloc_blank() or - * security_prepare_creds() returned an error. - */ - if (selinux_is_enabled() && cred->security) { + if (selinux_is_enabled()) { if ((unsigned long) cred->security < PAGE_SIZE) return true; if ((*(u32 *)cred->security & 0xffffff00) == diff --git a/trunk/kernel/perf_event.c b/trunk/kernel/perf_event.c index a353a4d6d00d..999835b6112b 100644 --- a/trunk/kernel/perf_event.c +++ b/trunk/kernel/perf_event.c @@ -38,79 +38,6 @@ #include -struct remote_function_call { - struct task_struct *p; - int (*func)(void *info); - void *info; - int ret; -}; - -static void remote_function(void *data) -{ - struct remote_function_call *tfc = data; - struct task_struct *p = tfc->p; - - if (p) { - tfc->ret = -EAGAIN; - if (task_cpu(p) != smp_processor_id() || !task_curr(p)) - return; - } - - tfc->ret = tfc->func(tfc->info); -} - -/** - * task_function_call - call a function on the cpu on which a task runs - * @p: the task to evaluate - * @func: the function to be called - * @info: the function call argument - * - * Calls the function @func when the task is currently running. This might - * be on the current CPU, which just calls the function directly - * - * returns: @func return value, or - * -ESRCH - when the process isn't running - * -EAGAIN - when the process moved away - */ -static int -task_function_call(struct task_struct *p, int (*func) (void *info), void *info) -{ - struct remote_function_call data = { - .p = p, - .func = func, - .info = info, - .ret = -ESRCH, /* No such (running) process */ - }; - - if (task_curr(p)) - smp_call_function_single(task_cpu(p), remote_function, &data, 1); - - return data.ret; -} - -/** - * cpu_function_call - call a function on the cpu - * @func: the function to be called - * @info: the function call argument - * - * Calls the function @func on the remote cpu. - * - * returns: @func return value or -ENXIO when the cpu is offline - */ -static int cpu_function_call(int cpu, int (*func) (void *info), void *info) -{ - struct remote_function_call data = { - .p = NULL, - .func = func, - .info = info, - .ret = -ENXIO, /* No such CPU */ - }; - - smp_call_function_single(cpu, remote_function, &data, 1); - - return data.ret; -} - enum event_type_t { EVENT_FLEXIBLE = 0x1, EVENT_PINNED = 0x2, @@ -327,6 +254,7 @@ static void perf_unpin_context(struct perf_event_context *ctx) raw_spin_lock_irqsave(&ctx->lock, flags); --ctx->pin_count; raw_spin_unlock_irqrestore(&ctx->lock, flags); + put_ctx(ctx); } /* @@ -690,24 +618,35 @@ __get_cpu_context(struct perf_event_context *ctx) * We disable the event on the hardware level first. After that we * remove it from the context list. */ -static int __perf_remove_from_context(void *info) +static void __perf_event_remove_from_context(void *info) { struct perf_event *event = info; struct perf_event_context *ctx = event->ctx; struct perf_cpu_context *cpuctx = __get_cpu_context(ctx); + /* + * If this is a task context, we need to check whether it is + * the current task context of this cpu. If not it has been + * scheduled out before the smp call arrived. + */ + if (ctx->task && cpuctx->task_ctx != ctx) + return; + raw_spin_lock(&ctx->lock); + event_sched_out(event, cpuctx, ctx); + list_del_event(event, ctx); - raw_spin_unlock(&ctx->lock); - return 0; + raw_spin_unlock(&ctx->lock); } /* * Remove the event from a task's (or a CPU's) list of events. * + * Must be called with ctx->mutex held. + * * CPU events are removed with a smp call. For task events we only * call when the task is on a CPU. * @@ -718,48 +657,49 @@ static int __perf_remove_from_context(void *info) * When called from perf_event_exit_task, it's OK because the * context has been detached from its task. */ -static void perf_remove_from_context(struct perf_event *event) +static void perf_event_remove_from_context(struct perf_event *event) { struct perf_event_context *ctx = event->ctx; struct task_struct *task = ctx->task; - lockdep_assert_held(&ctx->mutex); - if (!task) { /* * Per cpu events are removed via an smp call and * the removal is always successful. */ - cpu_function_call(event->cpu, __perf_remove_from_context, event); + smp_call_function_single(event->cpu, + __perf_event_remove_from_context, + event, 1); return; } retry: - if (!task_function_call(task, __perf_remove_from_context, event)) - return; + task_oncpu_function_call(task, __perf_event_remove_from_context, + event); raw_spin_lock_irq(&ctx->lock); /* - * If we failed to find a running task, but find the context active now - * that we've acquired the ctx->lock, retry. + * If the context is active we need to retry the smp call. */ - if (ctx->is_active) { + if (ctx->nr_active && !list_empty(&event->group_entry)) { raw_spin_unlock_irq(&ctx->lock); goto retry; } /* - * Since the task isn't running, its safe to remove the event, us - * holding the ctx->lock ensures the task won't get scheduled in. + * The lock prevents that this context is scheduled in so we + * can remove the event safely, if the call above did not + * succeed. */ - list_del_event(event, ctx); + if (!list_empty(&event->group_entry)) + list_del_event(event, ctx); raw_spin_unlock_irq(&ctx->lock); } /* * Cross CPU call to disable a performance event */ -static int __perf_event_disable(void *info) +static void __perf_event_disable(void *info) { struct perf_event *event = info; struct perf_event_context *ctx = event->ctx; @@ -768,12 +708,9 @@ static int __perf_event_disable(void *info) /* * If this is a per-task event, need to check whether this * event's task is the current task on this cpu. - * - * Can trigger due to concurrent perf_event_context_sched_out() - * flipping contexts around. */ if (ctx->task && cpuctx->task_ctx != ctx) - return -EINVAL; + return; raw_spin_lock(&ctx->lock); @@ -792,8 +729,6 @@ static int __perf_event_disable(void *info) } raw_spin_unlock(&ctx->lock); - - return 0; } /* @@ -818,13 +753,13 @@ void perf_event_disable(struct perf_event *event) /* * Disable the event on the cpu that it's on */ - cpu_function_call(event->cpu, __perf_event_disable, event); + smp_call_function_single(event->cpu, __perf_event_disable, + event, 1); return; } retry: - if (!task_function_call(task, __perf_event_disable, event)) - return; + task_oncpu_function_call(task, __perf_event_disable, event); raw_spin_lock_irq(&ctx->lock); /* @@ -832,11 +767,6 @@ void perf_event_disable(struct perf_event *event) */ if (event->state == PERF_EVENT_STATE_ACTIVE) { raw_spin_unlock_irq(&ctx->lock); - /* - * Reload the task pointer, it might have been changed by - * a concurrent perf_event_context_sched_out(). - */ - task = ctx->task; goto retry; } @@ -848,6 +778,7 @@ void perf_event_disable(struct perf_event *event) update_group_times(event); event->state = PERF_EVENT_STATE_OFF; } + raw_spin_unlock_irq(&ctx->lock); } @@ -997,14 +928,12 @@ static void add_event_to_ctx(struct perf_event *event, event->tstamp_stopped = tstamp; } -static void perf_event_context_sched_in(struct perf_event_context *ctx); - /* * Cross CPU call to install and enable a performance event * * Must be called with ctx->mutex held */ -static int __perf_install_in_context(void *info) +static void __perf_install_in_context(void *info) { struct perf_event *event = info; struct perf_event_context *ctx = event->ctx; @@ -1013,12 +942,17 @@ static int __perf_install_in_context(void *info) int err; /* - * In case we're installing a new context to an already running task, - * could also happen before perf_event_task_sched_in() on architectures - * which do context switches with IRQs enabled. + * If this is a task context, we need to check whether it is + * the current task context of this cpu. If not it has been + * scheduled out before the smp call arrived. + * Or possibly this is the right context but it isn't + * on this cpu because it had no events. */ - if (ctx->task && !cpuctx->task_ctx) - perf_event_context_sched_in(ctx); + if (ctx->task && cpuctx->task_ctx != ctx) { + if (cpuctx->task_ctx || ctx->task != current) + return; + cpuctx->task_ctx = ctx; + } raw_spin_lock(&ctx->lock); ctx->is_active = 1; @@ -1063,8 +997,6 @@ static int __perf_install_in_context(void *info) unlock: raw_spin_unlock(&ctx->lock); - - return 0; } /* @@ -1076,6 +1008,8 @@ static int __perf_install_in_context(void *info) * If the event is attached to a task which is on a CPU we use a smp * call to enable it in the task context. The task might have been * scheduled away, but we check this in the smp call again. + * + * Must be called with ctx->mutex held. */ static void perf_install_in_context(struct perf_event_context *ctx, @@ -1084,8 +1018,6 @@ perf_install_in_context(struct perf_event_context *ctx, { struct task_struct *task = ctx->task; - lockdep_assert_held(&ctx->mutex); - event->ctx = ctx; if (!task) { @@ -1093,29 +1025,31 @@ perf_install_in_context(struct perf_event_context *ctx, * Per cpu events are installed via an smp call and * the install is always successful. */ - cpu_function_call(cpu, __perf_install_in_context, event); + smp_call_function_single(cpu, __perf_install_in_context, + event, 1); return; } retry: - if (!task_function_call(task, __perf_install_in_context, event)) - return; + task_oncpu_function_call(task, __perf_install_in_context, + event); raw_spin_lock_irq(&ctx->lock); /* - * If we failed to find a running task, but find the context active now - * that we've acquired the ctx->lock, retry. + * we need to retry the smp call. */ - if (ctx->is_active) { + if (ctx->is_active && list_empty(&event->group_entry)) { raw_spin_unlock_irq(&ctx->lock); goto retry; } /* - * Since the task isn't running, its safe to add the event, us holding - * the ctx->lock ensures the task won't get scheduled in. + * The lock prevents that this context is scheduled in so we + * can add the event safely, if it the call above did not + * succeed. */ - add_event_to_ctx(event, ctx); + if (list_empty(&event->group_entry)) + add_event_to_ctx(event, ctx); raw_spin_unlock_irq(&ctx->lock); } @@ -1144,7 +1078,7 @@ static void __perf_event_mark_enabled(struct perf_event *event, /* * Cross CPU call to enable a performance event */ -static int __perf_event_enable(void *info) +static void __perf_event_enable(void *info) { struct perf_event *event = info; struct perf_event_context *ctx = event->ctx; @@ -1152,10 +1086,18 @@ static int __perf_event_enable(void *info) struct perf_cpu_context *cpuctx = __get_cpu_context(ctx); int err; - if (WARN_ON_ONCE(!ctx->is_active)) - return -EINVAL; + /* + * If this is a per-task event, need to check whether this + * event's task is the current task on this cpu. + */ + if (ctx->task && cpuctx->task_ctx != ctx) { + if (cpuctx->task_ctx || ctx->task != current) + return; + cpuctx->task_ctx = ctx; + } raw_spin_lock(&ctx->lock); + ctx->is_active = 1; update_context_time(ctx); if (event->state >= PERF_EVENT_STATE_INACTIVE) @@ -1196,8 +1138,6 @@ static int __perf_event_enable(void *info) unlock: raw_spin_unlock(&ctx->lock); - - return 0; } /* @@ -1218,7 +1158,8 @@ void perf_event_enable(struct perf_event *event) /* * Enable the event on the cpu that it's on */ - cpu_function_call(event->cpu, __perf_event_enable, event); + smp_call_function_single(event->cpu, __perf_event_enable, + event, 1); return; } @@ -1237,15 +1178,8 @@ void perf_event_enable(struct perf_event *event) event->state = PERF_EVENT_STATE_OFF; retry: - if (!ctx->is_active) { - __perf_event_mark_enabled(event, ctx); - goto out; - } - raw_spin_unlock_irq(&ctx->lock); - - if (!task_function_call(task, __perf_event_enable, event)) - return; + task_oncpu_function_call(task, __perf_event_enable, event); raw_spin_lock_irq(&ctx->lock); @@ -1253,14 +1187,15 @@ void perf_event_enable(struct perf_event *event) * If the context is active and the event is still off, * we need to retry the cross-call. */ - if (ctx->is_active && event->state == PERF_EVENT_STATE_OFF) { - /* - * task could have been flipped by a concurrent - * perf_event_context_sched_out() - */ - task = ctx->task; + if (ctx->is_active && event->state == PERF_EVENT_STATE_OFF) goto retry; - } + + /* + * Since we have the lock this context can't be scheduled + * in, so we can change the state safely. + */ + if (event->state == PERF_EVENT_STATE_OFF) + __perf_event_mark_enabled(event, ctx); out: raw_spin_unlock_irq(&ctx->lock); @@ -1404,8 +1339,8 @@ static void perf_event_sync_stat(struct perf_event_context *ctx, } } -static void perf_event_context_sched_out(struct task_struct *task, int ctxn, - struct task_struct *next) +void perf_event_context_sched_out(struct task_struct *task, int ctxn, + struct task_struct *next) { struct perf_event_context *ctx = task->perf_event_ctxp[ctxn]; struct perf_event_context *next_ctx; @@ -1598,7 +1533,7 @@ static void task_ctx_sched_in(struct perf_event_context *ctx, { struct perf_cpu_context *cpuctx; - cpuctx = __get_cpu_context(ctx); + cpuctx = __get_cpu_context(ctx); if (cpuctx->task_ctx == ctx) return; @@ -1606,7 +1541,7 @@ static void task_ctx_sched_in(struct perf_event_context *ctx, cpuctx->task_ctx = ctx; } -static void perf_event_context_sched_in(struct perf_event_context *ctx) +void perf_event_context_sched_in(struct perf_event_context *ctx) { struct perf_cpu_context *cpuctx; @@ -1692,7 +1627,7 @@ static u64 perf_calculate_period(struct perf_event *event, u64 nsec, u64 count) * Reduce accuracy by one bit such that @a and @b converge * to a similar magnitude. */ -#define REDUCE_FLS(a, b) \ +#define REDUCE_FLS(a, b) \ do { \ if (a##_fls > b##_fls) { \ a >>= 1; \ @@ -2278,9 +2213,6 @@ find_lively_task_by_vpid(pid_t vpid) } -/* - * Returns a matching context with refcount and pincount. - */ static struct perf_event_context * find_get_context(struct pmu *pmu, struct task_struct *task, int cpu) { @@ -2305,7 +2237,6 @@ find_get_context(struct pmu *pmu, struct task_struct *task, int cpu) cpuctx = per_cpu_ptr(pmu->pmu_cpu_context, cpu); ctx = &cpuctx->ctx; get_ctx(ctx); - ++ctx->pin_count; return ctx; } @@ -2319,7 +2250,6 @@ find_get_context(struct pmu *pmu, struct task_struct *task, int cpu) ctx = perf_lock_task_context(task, ctxn, &flags); if (ctx) { unclone_ctx(ctx); - ++ctx->pin_count; raw_spin_unlock_irqrestore(&ctx->lock, flags); } @@ -2341,10 +2271,8 @@ find_get_context(struct pmu *pmu, struct task_struct *task, int cpu) err = -ESRCH; else if (task->perf_event_ctxp[ctxn]) err = -EAGAIN; - else { - ++ctx->pin_count; + else rcu_assign_pointer(task->perf_event_ctxp[ctxn], ctx); - } mutex_unlock(&task->perf_event_mutex); if (unlikely(err)) { @@ -6022,10 +5950,10 @@ SYSCALL_DEFINE5(perf_event_open, struct perf_event_context *gctx = group_leader->ctx; mutex_lock(&gctx->mutex); - perf_remove_from_context(group_leader); + perf_event_remove_from_context(group_leader); list_for_each_entry(sibling, &group_leader->sibling_list, group_entry) { - perf_remove_from_context(sibling); + perf_event_remove_from_context(sibling); put_ctx(gctx); } mutex_unlock(&gctx->mutex); @@ -6048,7 +5976,6 @@ SYSCALL_DEFINE5(perf_event_open, perf_install_in_context(ctx, event, cpu); ++ctx->generation; - perf_unpin_context(ctx); mutex_unlock(&ctx->mutex); event->owner = current; @@ -6074,7 +6001,6 @@ SYSCALL_DEFINE5(perf_event_open, return event_fd; err_context: - perf_unpin_context(ctx); put_ctx(ctx); err_alloc: free_event(event); @@ -6125,7 +6051,6 @@ perf_event_create_kernel_counter(struct perf_event_attr *attr, int cpu, mutex_lock(&ctx->mutex); perf_install_in_context(ctx, event, cpu); ++ctx->generation; - perf_unpin_context(ctx); mutex_unlock(&ctx->mutex); return event; @@ -6179,7 +6104,7 @@ __perf_event_exit_task(struct perf_event *child_event, { struct perf_event *parent_event; - perf_remove_from_context(child_event); + perf_event_remove_from_context(child_event); parent_event = child_event->parent; /* @@ -6486,7 +6411,7 @@ inherit_task_group(struct perf_event *event, struct task_struct *parent, return 0; } - child_ctx = child->perf_event_ctxp[ctxn]; + child_ctx = child->perf_event_ctxp[ctxn]; if (!child_ctx) { /* * This is executed from the parent task context, so @@ -6601,7 +6526,6 @@ int perf_event_init_context(struct task_struct *child, int ctxn) mutex_unlock(&parent_ctx->mutex); perf_unpin_context(parent_ctx); - put_ctx(parent_ctx); return ret; } @@ -6671,9 +6595,9 @@ static void __perf_event_exit_context(void *__info) perf_pmu_rotate_stop(ctx->pmu); list_for_each_entry_safe(event, tmp, &ctx->pinned_groups, group_entry) - __perf_remove_from_context(event); + __perf_event_remove_from_context(event); list_for_each_entry_safe(event, tmp, &ctx->flexible_groups, group_entry) - __perf_remove_from_context(event); + __perf_event_remove_from_context(event); } static void perf_event_exit_cpu_context(int cpu) diff --git a/trunk/kernel/sched.c b/trunk/kernel/sched.c index 31cb5d5e1aac..fbe86cb04b61 100644 --- a/trunk/kernel/sched.c +++ b/trunk/kernel/sched.c @@ -2265,6 +2265,27 @@ void kick_process(struct task_struct *p) EXPORT_SYMBOL_GPL(kick_process); #endif /* CONFIG_SMP */ +/** + * task_oncpu_function_call - call a function on the cpu on which a task runs + * @p: the task to evaluate + * @func: the function to be called + * @info: the function call argument + * + * Calls the function @func when the task is currently running. This might + * be on the current CPU, which just calls the function directly + */ +void task_oncpu_function_call(struct task_struct *p, + void (*func) (void *info), void *info) +{ + int cpu; + + preempt_disable(); + cpu = task_cpu(p); + if (task_curr(p)) + smp_call_function_single(cpu, func, info, 1); + preempt_enable(); +} + #ifdef CONFIG_SMP /* * ->cpus_allowed is protected by either TASK_WAKING or rq->lock held. @@ -2755,12 +2776,9 @@ static inline void prepare_task_switch(struct rq *rq, struct task_struct *prev, struct task_struct *next) { - sched_info_switch(prev, next); - perf_event_task_sched_out(prev, next); fire_sched_out_preempt_notifiers(prev, next); prepare_lock_switch(rq, next); prepare_arch_switch(next); - trace_sched_switch(prev, next); } /** @@ -2893,7 +2911,7 @@ context_switch(struct rq *rq, struct task_struct *prev, struct mm_struct *mm, *oldmm; prepare_task_switch(rq, prev, next); - + trace_sched_switch(prev, next); mm = next->mm; oldmm = prev->active_mm; /* @@ -3971,6 +3989,9 @@ asmlinkage void __sched schedule(void) rq->skip_clock_update = 0; if (likely(prev != next)) { + sched_info_switch(prev, next); + perf_event_task_sched_out(prev, next); + rq->nr_switches++; rq->curr = next; ++*switch_count; @@ -5550,7 +5571,7 @@ void __cpuinit init_idle(struct task_struct *idle, int cpu) * The idle tasks have their own, simple scheduling class: */ idle->sched_class = &idle_sched_class; - ftrace_graph_init_task(idle); + ftrace_graph_init_idle_task(idle, cpu); } /* diff --git a/trunk/kernel/timer.c b/trunk/kernel/timer.c index d53ce66daea0..43ca9936f2d0 100644 --- a/trunk/kernel/timer.c +++ b/trunk/kernel/timer.c @@ -969,14 +969,10 @@ EXPORT_SYMBOL(try_to_del_timer_sync); int del_timer_sync(struct timer_list *timer) { #ifdef CONFIG_LOCKDEP - unsigned long flags; - - raw_local_irq_save(flags); local_bh_disable(); lock_map_acquire(&timer->lockdep_map); lock_map_release(&timer->lockdep_map); - _local_bh_enable(); - raw_local_irq_restore(flags); + local_bh_enable(); #endif /* * don't use it in hardirq context, because it diff --git a/trunk/kernel/trace/ftrace.c b/trunk/kernel/trace/ftrace.c index f3dadae83883..888b611897d3 100644 --- a/trunk/kernel/trace/ftrace.c +++ b/trunk/kernel/trace/ftrace.c @@ -3328,7 +3328,7 @@ static int start_graph_tracing(void) /* The cpu_boot init_task->ret_stack will never be freed */ for_each_online_cpu(cpu) { if (!idle_task(cpu)->ret_stack) - ftrace_graph_init_task(idle_task(cpu)); + ftrace_graph_init_idle_task(idle_task(cpu), cpu); } do { @@ -3418,6 +3418,49 @@ void unregister_ftrace_graph(void) mutex_unlock(&ftrace_lock); } +static DEFINE_PER_CPU(struct ftrace_ret_stack *, idle_ret_stack); + +static void +graph_init_task(struct task_struct *t, struct ftrace_ret_stack *ret_stack) +{ + atomic_set(&t->tracing_graph_pause, 0); + atomic_set(&t->trace_overrun, 0); + t->ftrace_timestamp = 0; + /* make curr_ret_stack visable before we add the ret_stack */ + smp_wmb(); + t->ret_stack = ret_stack; +} + +/* + * Allocate a return stack for the idle task. May be the first + * time through, or it may be done by CPU hotplug online. + */ +void ftrace_graph_init_idle_task(struct task_struct *t, int cpu) +{ + t->curr_ret_stack = -1; + /* + * The idle task has no parent, it either has its own + * stack or no stack at all. + */ + if (t->ret_stack) + WARN_ON(t->ret_stack != per_cpu(idle_ret_stack, cpu)); + + if (ftrace_graph_active) { + struct ftrace_ret_stack *ret_stack; + + ret_stack = per_cpu(idle_ret_stack, cpu); + if (!ret_stack) { + ret_stack = kmalloc(FTRACE_RETFUNC_DEPTH + * sizeof(struct ftrace_ret_stack), + GFP_KERNEL); + if (!ret_stack) + return; + per_cpu(idle_ret_stack, cpu) = ret_stack; + } + graph_init_task(t, ret_stack); + } +} + /* Allocate a return stack for newly created task */ void ftrace_graph_init_task(struct task_struct *t) { @@ -3433,12 +3476,7 @@ void ftrace_graph_init_task(struct task_struct *t) GFP_KERNEL); if (!ret_stack) return; - atomic_set(&t->tracing_graph_pause, 0); - atomic_set(&t->trace_overrun, 0); - t->ftrace_timestamp = 0; - /* make curr_ret_stack visable before we add the ret_stack */ - smp_wmb(); - t->ret_stack = ret_stack; + graph_init_task(t, ret_stack); } } diff --git a/trunk/kernel/trace/trace_kprobe.c b/trunk/kernel/trace/trace_kprobe.c index 8435b43b1782..2dec9bcde8b4 100644 --- a/trunk/kernel/trace/trace_kprobe.c +++ b/trunk/kernel/trace/trace_kprobe.c @@ -353,43 +353,6 @@ static __kprobes void free_deref_fetch_param(struct deref_fetch_param *data) kfree(data); } -/* Bitfield fetch function */ -struct bitfield_fetch_param { - struct fetch_param orig; - unsigned char hi_shift; - unsigned char low_shift; -}; - -#define DEFINE_FETCH_bitfield(type) \ -static __kprobes void FETCH_FUNC_NAME(bitfield, type)(struct pt_regs *regs,\ - void *data, void *dest) \ -{ \ - struct bitfield_fetch_param *bprm = data; \ - type buf = 0; \ - call_fetch(&bprm->orig, regs, &buf); \ - if (buf) { \ - buf <<= bprm->hi_shift; \ - buf >>= bprm->low_shift; \ - } \ - *(type *)dest = buf; \ -} -DEFINE_BASIC_FETCH_FUNCS(bitfield) -#define fetch_bitfield_string NULL -#define fetch_bitfield_string_size NULL - -static __kprobes void -free_bitfield_fetch_param(struct bitfield_fetch_param *data) -{ - /* - * Don't check the bitfield itself, because this must be the - * last fetch function. - */ - if (CHECK_FETCH_FUNCS(deref, data->orig.fn)) - free_deref_fetch_param(data->orig.data); - else if (CHECK_FETCH_FUNCS(symbol, data->orig.fn)) - free_symbol_cache(data->orig.data); - kfree(data); -} /* Default (unsigned long) fetch type */ #define __DEFAULT_FETCH_TYPE(t) u##t #define _DEFAULT_FETCH_TYPE(t) __DEFAULT_FETCH_TYPE(t) @@ -404,7 +367,6 @@ enum { FETCH_MTD_memory, FETCH_MTD_symbol, FETCH_MTD_deref, - FETCH_MTD_bitfield, FETCH_MTD_END, }; @@ -425,7 +387,6 @@ ASSIGN_FETCH_FUNC(retval, ftype), \ ASSIGN_FETCH_FUNC(memory, ftype), \ ASSIGN_FETCH_FUNC(symbol, ftype), \ ASSIGN_FETCH_FUNC(deref, ftype), \ -ASSIGN_FETCH_FUNC(bitfield, ftype), \ } \ } @@ -469,33 +430,9 @@ static const struct fetch_type *find_fetch_type(const char *type) if (!type) type = DEFAULT_FETCH_TYPE_STR; - /* Special case: bitfield */ - if (*type == 'b') { - unsigned long bs; - type = strchr(type, '/'); - if (!type) - goto fail; - type++; - if (strict_strtoul(type, 0, &bs)) - goto fail; - switch (bs) { - case 8: - return find_fetch_type("u8"); - case 16: - return find_fetch_type("u16"); - case 32: - return find_fetch_type("u32"); - case 64: - return find_fetch_type("u64"); - default: - goto fail; - } - } - for (i = 0; i < ARRAY_SIZE(fetch_type_table); i++) if (strcmp(type, fetch_type_table[i].name) == 0) return &fetch_type_table[i]; -fail: return NULL; } @@ -649,9 +586,7 @@ static struct trace_probe *alloc_trace_probe(const char *group, static void free_probe_arg(struct probe_arg *arg) { - if (CHECK_FETCH_FUNCS(bitfield, arg->fetch.fn)) - free_bitfield_fetch_param(arg->fetch.data); - else if (CHECK_FETCH_FUNCS(deref, arg->fetch.fn)) + if (CHECK_FETCH_FUNCS(deref, arg->fetch.fn)) free_deref_fetch_param(arg->fetch.data); else if (CHECK_FETCH_FUNCS(symbol, arg->fetch.fn)) free_symbol_cache(arg->fetch.data); @@ -832,15 +767,16 @@ static int __parse_probe_arg(char *arg, const struct fetch_type *t, } break; case '+': /* deref memory */ - arg++; /* Skip '+', because strict_strtol() rejects it. */ case '-': tmp = strchr(arg, '('); if (!tmp) break; *tmp = '\0'; - ret = strict_strtol(arg, 0, &offset); + ret = strict_strtol(arg + 1, 0, &offset); if (ret) break; + if (arg[0] == '-') + offset = -offset; arg = tmp + 1; tmp = strrchr(arg, ')'); if (tmp) { @@ -871,41 +807,6 @@ static int __parse_probe_arg(char *arg, const struct fetch_type *t, return ret; } -#define BYTES_TO_BITS(nb) ((BITS_PER_LONG * (nb)) / sizeof(long)) - -/* Bitfield type needs to be parsed into a fetch function */ -static int __parse_bitfield_probe_arg(const char *bf, - const struct fetch_type *t, - struct fetch_param *f) -{ - struct bitfield_fetch_param *bprm; - unsigned long bw, bo; - char *tail; - - if (*bf != 'b') - return 0; - - bprm = kzalloc(sizeof(*bprm), GFP_KERNEL); - if (!bprm) - return -ENOMEM; - bprm->orig = *f; - f->fn = t->fetch[FETCH_MTD_bitfield]; - f->data = (void *)bprm; - - bw = simple_strtoul(bf + 1, &tail, 0); /* Use simple one */ - if (bw == 0 || *tail != '@') - return -EINVAL; - - bf = tail + 1; - bo = simple_strtoul(bf, &tail, 0); - if (tail == bf || *tail != '/') - return -EINVAL; - - bprm->hi_shift = BYTES_TO_BITS(t->size) - (bw + bo); - bprm->low_shift = bprm->hi_shift + bo; - return (BYTES_TO_BITS(t->size) < (bw + bo)) ? -EINVAL : 0; -} - /* String length checking wrapper */ static int parse_probe_arg(char *arg, struct trace_probe *tp, struct probe_arg *parg, int is_return) @@ -935,8 +836,6 @@ static int parse_probe_arg(char *arg, struct trace_probe *tp, parg->offset = tp->size; tp->size += parg->type->size; ret = __parse_probe_arg(arg, parg->type, &parg->fetch, is_return); - if (ret >= 0 && t != NULL) - ret = __parse_bitfield_probe_arg(t, parg->type, &parg->fetch); if (ret >= 0) { parg->fetch_size.fn = get_fetch_size_function(parg->type, parg->fetch.fn); @@ -1231,7 +1130,7 @@ static int command_trace_probe(const char *buf) return ret; } -#define WRITE_BUFSIZE 4096 +#define WRITE_BUFSIZE 128 static ssize_t probes_write(struct file *file, const char __user *buffer, size_t count, loff_t *ppos) diff --git a/trunk/kernel/watchdog.c b/trunk/kernel/watchdog.c index 18bb15776c57..f37f974aa81b 100644 --- a/trunk/kernel/watchdog.c +++ b/trunk/kernel/watchdog.c @@ -363,14 +363,8 @@ static int watchdog_nmi_enable(int cpu) goto out_save; } - - /* vary the KERN level based on the returned errno */ - if (PTR_ERR(event) == -EOPNOTSUPP) - printk(KERN_INFO "NMI watchdog disabled (cpu%i): not supported (no LAPIC?)\n", cpu); - else if (PTR_ERR(event) == -ENOENT) - printk(KERN_WARNING "NMI watchdog disabled (cpu%i): hardware events not enabled\n", cpu); - else - printk(KERN_ERR "NMI watchdog disabled (cpu%i): unable to create perf event: %ld\n", cpu, PTR_ERR(event)); + printk(KERN_ERR "NMI watchdog disabled for cpu%i: unable to create perf event: %ld\n", + cpu, PTR_ERR(event)); return PTR_ERR(event); /* success path */ diff --git a/trunk/net/batman-adv/vis.c b/trunk/net/batman-adv/vis.c index de1022cacaf7..cd4c4231fa48 100644 --- a/trunk/net/batman-adv/vis.c +++ b/trunk/net/batman-adv/vis.c @@ -64,7 +64,6 @@ static void free_info(struct kref *ref) spin_unlock_bh(&bat_priv->vis_list_lock); kfree_skb(info->skb_packet); - kfree(info); } /* Compare two vis packets, used by the hashing algorithm */ @@ -269,10 +268,10 @@ int vis_seq_print_text(struct seq_file *seq, void *offset) buff_pos += sprintf(buff + buff_pos, "%pM,", entry->addr); - for (j = 0; j < packet->entries; j++) + for (i = 0; i < packet->entries; i++) buff_pos += vis_data_read_entry( buff + buff_pos, - &entries[j], + &entries[i], entry->addr, entry->primary); @@ -445,7 +444,7 @@ static struct vis_info *add_packet(struct bat_priv *bat_priv, info); if (hash_added < 0) { /* did not work (for some reason) */ - kref_put(&info->refcount, free_info); + kref_put(&old_info->refcount, free_info); info = NULL; } @@ -816,7 +815,7 @@ static void send_vis_packets(struct work_struct *work) container_of(work, struct delayed_work, work); struct bat_priv *bat_priv = container_of(delayed_work, struct bat_priv, vis_work); - struct vis_info *info; + struct vis_info *info, *temp; spin_lock_bh(&bat_priv->vis_hash_lock); purge_vis_packets(bat_priv); @@ -826,9 +825,8 @@ static void send_vis_packets(struct work_struct *work) send_list_add(bat_priv, bat_priv->my_vis_info); } - while (!list_empty(&bat_priv->vis_send_list)) { - info = list_first_entry(&bat_priv->vis_send_list, - typeof(*info), send_list); + list_for_each_entry_safe(info, temp, &bat_priv->vis_send_list, + send_list) { kref_get(&info->refcount); spin_unlock_bh(&bat_priv->vis_hash_lock); diff --git a/trunk/net/bridge/br_fdb.c b/trunk/net/bridge/br_fdb.c index 88485cc74dc3..2872393b2939 100644 --- a/trunk/net/bridge/br_fdb.c +++ b/trunk/net/bridge/br_fdb.c @@ -328,12 +328,12 @@ static struct net_bridge_fdb_entry *fdb_create(struct hlist_head *head, fdb = kmem_cache_alloc(br_fdb_cache, GFP_ATOMIC); if (fdb) { memcpy(fdb->addr.addr, addr, ETH_ALEN); + hlist_add_head_rcu(&fdb->hlist, head); + fdb->dst = source; fdb->is_local = is_local; fdb->is_static = is_local; fdb->ageing_timer = jiffies; - - hlist_add_head_rcu(&fdb->hlist, head); } return fdb; } diff --git a/trunk/net/core/dev.c b/trunk/net/core/dev.c index b6d0bf875a8e..24ea2d71e7ea 100644 --- a/trunk/net/core/dev.c +++ b/trunk/net/core/dev.c @@ -2563,8 +2563,7 @@ static int get_rps_cpu(struct net_device *dev, struct sk_buff *skb, map = rcu_dereference(rxqueue->rps_map); if (map) { - if (map->len == 1 && - !rcu_dereference_raw(rxqueue->rps_flow_table)) { + if (map->len == 1) { tcpu = map->cpus[0]; if (cpu_online(tcpu)) cpu = tcpu; @@ -3425,8 +3424,6 @@ static void napi_reuse_skb(struct napi_struct *napi, struct sk_buff *skb) __skb_pull(skb, skb_headlen(skb)); skb_reserve(skb, NET_IP_ALIGN - skb_headroom(skb)); skb->vlan_tci = 0; - skb->dev = napi->dev; - skb->skb_iif = 0; napi->skb = skb; } diff --git a/trunk/net/core/rtnetlink.c b/trunk/net/core/rtnetlink.c index 2d65c6bb24c1..750db57f3bb3 100644 --- a/trunk/net/core/rtnetlink.c +++ b/trunk/net/core/rtnetlink.c @@ -1121,7 +1121,8 @@ static int validate_linkmsg(struct net_device *dev, struct nlattr *tb[]) return -EOPNOTSUPP; if (af_ops->validate_link_af) { - err = af_ops->validate_link_af(dev, af); + err = af_ops->validate_link_af(dev, + tb[IFLA_AF_SPEC]); if (err < 0) return err; } @@ -1671,9 +1672,6 @@ static int rtnl_newlink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) snprintf(ifname, IFNAMSIZ, "%s%%d", ops->kind); dest_net = rtnl_link_get_net(net, tb); - if (IS_ERR(dest_net)) - return PTR_ERR(dest_net); - dev = rtnl_create_link(net, dest_net, ifname, ops, tb); if (IS_ERR(dev)) diff --git a/trunk/net/core/skbuff.c b/trunk/net/core/skbuff.c index d883dcc78b6b..7cd1bc86d591 100644 --- a/trunk/net/core/skbuff.c +++ b/trunk/net/core/skbuff.c @@ -210,7 +210,6 @@ struct sk_buff *__alloc_skb(unsigned int size, gfp_t gfp_mask, shinfo = skb_shinfo(skb); memset(shinfo, 0, offsetof(struct skb_shared_info, dataref)); atomic_set(&shinfo->dataref, 1); - kmemcheck_annotate_variable(shinfo->destructor_arg); if (fclone) { struct sk_buff *child = skb + 1; diff --git a/trunk/net/econet/af_econet.c b/trunk/net/econet/af_econet.c index 0c2826337919..15dcc1a586b4 100644 --- a/trunk/net/econet/af_econet.c +++ b/trunk/net/econet/af_econet.c @@ -265,13 +265,13 @@ static void ec_tx_done(struct sk_buff *skb, int result) static int econet_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, size_t len) { + struct sock *sk = sock->sk; struct sockaddr_ec *saddr=(struct sockaddr_ec *)msg->msg_name; struct net_device *dev; struct ec_addr addr; int err; unsigned char port, cb; #if defined(CONFIG_ECONET_AUNUDP) || defined(CONFIG_ECONET_NATIVE) - struct sock *sk = sock->sk; struct sk_buff *skb; struct ec_cb *eb; #endif @@ -488,10 +488,10 @@ static int econet_sendmsg(struct kiocb *iocb, struct socket *sock, error_free_buf: vfree(userbuf); -error: #else err = -EPROTOTYPE; #endif + error: mutex_unlock(&econet_mutex); return err; diff --git a/trunk/net/ipv4/af_inet.c b/trunk/net/ipv4/af_inet.c index 45b89d7bda5a..f2b61107df6c 100644 --- a/trunk/net/ipv4/af_inet.c +++ b/trunk/net/ipv4/af_inet.c @@ -880,19 +880,6 @@ int inet_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) } EXPORT_SYMBOL(inet_ioctl); -#ifdef CONFIG_COMPAT -int inet_compat_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) -{ - struct sock *sk = sock->sk; - int err = -ENOIOCTLCMD; - - if (sk->sk_prot->compat_ioctl) - err = sk->sk_prot->compat_ioctl(sk, cmd, arg); - - return err; -} -#endif - const struct proto_ops inet_stream_ops = { .family = PF_INET, .owner = THIS_MODULE, @@ -916,7 +903,6 @@ const struct proto_ops inet_stream_ops = { #ifdef CONFIG_COMPAT .compat_setsockopt = compat_sock_common_setsockopt, .compat_getsockopt = compat_sock_common_getsockopt, - .compat_ioctl = inet_compat_ioctl, #endif }; EXPORT_SYMBOL(inet_stream_ops); @@ -943,7 +929,6 @@ const struct proto_ops inet_dgram_ops = { #ifdef CONFIG_COMPAT .compat_setsockopt = compat_sock_common_setsockopt, .compat_getsockopt = compat_sock_common_getsockopt, - .compat_ioctl = inet_compat_ioctl, #endif }; EXPORT_SYMBOL(inet_dgram_ops); @@ -974,7 +959,6 @@ static const struct proto_ops inet_sockraw_ops = { #ifdef CONFIG_COMPAT .compat_setsockopt = compat_sock_common_setsockopt, .compat_getsockopt = compat_sock_common_getsockopt, - .compat_ioctl = inet_compat_ioctl, #endif }; diff --git a/trunk/net/ipv4/ipmr.c b/trunk/net/ipv4/ipmr.c index 8b65a12654e7..3f3a9afd73e0 100644 --- a/trunk/net/ipv4/ipmr.c +++ b/trunk/net/ipv4/ipmr.c @@ -60,7 +60,6 @@ #include #include #include -#include #include #include #include @@ -1435,81 +1434,6 @@ int ipmr_ioctl(struct sock *sk, int cmd, void __user *arg) } } -#ifdef CONFIG_COMPAT -struct compat_sioc_sg_req { - struct in_addr src; - struct in_addr grp; - compat_ulong_t pktcnt; - compat_ulong_t bytecnt; - compat_ulong_t wrong_if; -}; - -struct compat_sioc_vif_req { - vifi_t vifi; /* Which iface */ - compat_ulong_t icount; - compat_ulong_t ocount; - compat_ulong_t ibytes; - compat_ulong_t obytes; -}; - -int ipmr_compat_ioctl(struct sock *sk, unsigned int cmd, void __user *arg) -{ - struct compat_sioc_sg_req sr; - struct compat_sioc_vif_req vr; - struct vif_device *vif; - struct mfc_cache *c; - struct net *net = sock_net(sk); - struct mr_table *mrt; - - mrt = ipmr_get_table(net, raw_sk(sk)->ipmr_table ? : RT_TABLE_DEFAULT); - if (mrt == NULL) - return -ENOENT; - - switch (cmd) { - case SIOCGETVIFCNT: - if (copy_from_user(&vr, arg, sizeof(vr))) - return -EFAULT; - if (vr.vifi >= mrt->maxvif) - return -EINVAL; - read_lock(&mrt_lock); - vif = &mrt->vif_table[vr.vifi]; - if (VIF_EXISTS(mrt, vr.vifi)) { - vr.icount = vif->pkt_in; - vr.ocount = vif->pkt_out; - vr.ibytes = vif->bytes_in; - vr.obytes = vif->bytes_out; - read_unlock(&mrt_lock); - - if (copy_to_user(arg, &vr, sizeof(vr))) - return -EFAULT; - return 0; - } - read_unlock(&mrt_lock); - return -EADDRNOTAVAIL; - case SIOCGETSGCNT: - if (copy_from_user(&sr, arg, sizeof(sr))) - return -EFAULT; - - rcu_read_lock(); - c = ipmr_cache_find(mrt, sr.src.s_addr, sr.grp.s_addr); - if (c) { - sr.pktcnt = c->mfc_un.res.pkt; - sr.bytecnt = c->mfc_un.res.bytes; - sr.wrong_if = c->mfc_un.res.wrong_if; - rcu_read_unlock(); - - if (copy_to_user(arg, &sr, sizeof(sr))) - return -EFAULT; - return 0; - } - rcu_read_unlock(); - return -EADDRNOTAVAIL; - default: - return -ENOIOCTLCMD; - } -} -#endif - static int ipmr_device_event(struct notifier_block *this, unsigned long event, void *ptr) { diff --git a/trunk/net/ipv4/netfilter/arpt_mangle.c b/trunk/net/ipv4/netfilter/arpt_mangle.c index a5e52a9f0a12..b8ddcc480ed9 100644 --- a/trunk/net/ipv4/netfilter/arpt_mangle.c +++ b/trunk/net/ipv4/netfilter/arpt_mangle.c @@ -60,12 +60,12 @@ static int checkentry(const struct xt_tgchk_param *par) if (mangle->flags & ~ARPT_MANGLE_MASK || !(mangle->flags & ARPT_MANGLE_MASK)) - return -EINVAL; + return false; if (mangle->target != NF_DROP && mangle->target != NF_ACCEPT && mangle->target != XT_CONTINUE) - return -EINVAL; - return 0; + return false; + return true; } static struct xt_target arpt_mangle_reg __read_mostly = { diff --git a/trunk/net/ipv4/raw.c b/trunk/net/ipv4/raw.c index 6390ba299b3d..a3d5ab786e81 100644 --- a/trunk/net/ipv4/raw.c +++ b/trunk/net/ipv4/raw.c @@ -76,7 +76,6 @@ #include #include #include -#include static struct raw_hashinfo raw_v4_hashinfo = { .lock = __RW_LOCK_UNLOCKED(raw_v4_hashinfo.lock), @@ -839,23 +838,6 @@ static int raw_ioctl(struct sock *sk, int cmd, unsigned long arg) } } -#ifdef CONFIG_COMPAT -static int compat_raw_ioctl(struct sock *sk, unsigned int cmd, unsigned long arg) -{ - switch (cmd) { - case SIOCOUTQ: - case SIOCINQ: - return -ENOIOCTLCMD; - default: -#ifdef CONFIG_IP_MROUTE - return ipmr_compat_ioctl(sk, cmd, compat_ptr(arg)); -#else - return -ENOIOCTLCMD; -#endif - } -} -#endif - struct proto raw_prot = { .name = "RAW", .owner = THIS_MODULE, @@ -878,7 +860,6 @@ struct proto raw_prot = { #ifdef CONFIG_COMPAT .compat_setsockopt = compat_raw_setsockopt, .compat_getsockopt = compat_raw_getsockopt, - .compat_ioctl = compat_raw_ioctl, #endif }; diff --git a/trunk/net/ipv4/route.c b/trunk/net/ipv4/route.c index 788a3e74834e..351dc4e85242 100644 --- a/trunk/net/ipv4/route.c +++ b/trunk/net/ipv4/route.c @@ -2707,11 +2707,6 @@ static struct dst_entry *ipv4_blackhole_dst_check(struct dst_entry *dst, u32 coo return NULL; } -static unsigned int ipv4_blackhole_default_mtu(const struct dst_entry *dst) -{ - return 0; -} - static void ipv4_rt_blackhole_update_pmtu(struct dst_entry *dst, u32 mtu) { } @@ -2721,7 +2716,6 @@ static struct dst_ops ipv4_dst_blackhole_ops = { .protocol = cpu_to_be16(ETH_P_IP), .destroy = ipv4_dst_destroy, .check = ipv4_blackhole_dst_check, - .default_mtu = ipv4_blackhole_default_mtu, .update_pmtu = ipv4_rt_blackhole_update_pmtu, }; diff --git a/trunk/net/ipv6/ip6mr.c b/trunk/net/ipv6/ip6mr.c index 0e1d53bcf1e0..9fab274019c0 100644 --- a/trunk/net/ipv6/ip6mr.c +++ b/trunk/net/ipv6/ip6mr.c @@ -34,7 +34,6 @@ #include #include #include -#include #include #include #include @@ -1805,80 +1804,6 @@ int ip6mr_ioctl(struct sock *sk, int cmd, void __user *arg) } } -#ifdef CONFIG_COMPAT -struct compat_sioc_sg_req6 { - struct sockaddr_in6 src; - struct sockaddr_in6 grp; - compat_ulong_t pktcnt; - compat_ulong_t bytecnt; - compat_ulong_t wrong_if; -}; - -struct compat_sioc_mif_req6 { - mifi_t mifi; - compat_ulong_t icount; - compat_ulong_t ocount; - compat_ulong_t ibytes; - compat_ulong_t obytes; -}; - -int ip6mr_compat_ioctl(struct sock *sk, unsigned int cmd, void __user *arg) -{ - struct compat_sioc_sg_req6 sr; - struct compat_sioc_mif_req6 vr; - struct mif_device *vif; - struct mfc6_cache *c; - struct net *net = sock_net(sk); - struct mr6_table *mrt; - - mrt = ip6mr_get_table(net, raw6_sk(sk)->ip6mr_table ? : RT6_TABLE_DFLT); - if (mrt == NULL) - return -ENOENT; - - switch (cmd) { - case SIOCGETMIFCNT_IN6: - if (copy_from_user(&vr, arg, sizeof(vr))) - return -EFAULT; - if (vr.mifi >= mrt->maxvif) - return -EINVAL; - read_lock(&mrt_lock); - vif = &mrt->vif6_table[vr.mifi]; - if (MIF_EXISTS(mrt, vr.mifi)) { - vr.icount = vif->pkt_in; - vr.ocount = vif->pkt_out; - vr.ibytes = vif->bytes_in; - vr.obytes = vif->bytes_out; - read_unlock(&mrt_lock); - - if (copy_to_user(arg, &vr, sizeof(vr))) - return -EFAULT; - return 0; - } - read_unlock(&mrt_lock); - return -EADDRNOTAVAIL; - case SIOCGETSGCNT_IN6: - if (copy_from_user(&sr, arg, sizeof(sr))) - return -EFAULT; - - read_lock(&mrt_lock); - c = ip6mr_cache_find(mrt, &sr.src.sin6_addr, &sr.grp.sin6_addr); - if (c) { - sr.pktcnt = c->mfc_un.res.pkt; - sr.bytecnt = c->mfc_un.res.bytes; - sr.wrong_if = c->mfc_un.res.wrong_if; - read_unlock(&mrt_lock); - - if (copy_to_user(arg, &sr, sizeof(sr))) - return -EFAULT; - return 0; - } - read_unlock(&mrt_lock); - return -EADDRNOTAVAIL; - default: - return -ENOIOCTLCMD; - } -} -#endif static inline int ip6mr_forward2_finish(struct sk_buff *skb) { diff --git a/trunk/net/ipv6/raw.c b/trunk/net/ipv6/raw.c index c5b0915d106b..86c39526ba5e 100644 --- a/trunk/net/ipv6/raw.c +++ b/trunk/net/ipv6/raw.c @@ -31,7 +31,6 @@ #include #include #include -#include #include #include @@ -1158,23 +1157,6 @@ static int rawv6_ioctl(struct sock *sk, int cmd, unsigned long arg) } } -#ifdef CONFIG_COMPAT -static int compat_rawv6_ioctl(struct sock *sk, unsigned int cmd, unsigned long arg) -{ - switch (cmd) { - case SIOCOUTQ: - case SIOCINQ: - return -ENOIOCTLCMD; - default: -#ifdef CONFIG_IPV6_MROUTE - return ip6mr_compat_ioctl(sk, cmd, compat_ptr(arg)); -#else - return -ENOIOCTLCMD; -#endif - } -} -#endif - static void rawv6_close(struct sock *sk, long timeout) { if (inet_sk(sk)->inet_num == IPPROTO_RAW) @@ -1233,7 +1215,6 @@ struct proto rawv6_prot = { #ifdef CONFIG_COMPAT .compat_setsockopt = compat_rawv6_setsockopt, .compat_getsockopt = compat_rawv6_getsockopt, - .compat_ioctl = compat_rawv6_ioctl, #endif }; diff --git a/trunk/net/ipv6/route.c b/trunk/net/ipv6/route.c index 1c29f95695de..1534508f6c68 100644 --- a/trunk/net/ipv6/route.c +++ b/trunk/net/ipv6/route.c @@ -113,11 +113,6 @@ static struct dst_ops ip6_dst_ops_template = { .local_out = __ip6_local_out, }; -static unsigned int ip6_blackhole_default_mtu(const struct dst_entry *dst) -{ - return 0; -} - static void ip6_rt_blackhole_update_pmtu(struct dst_entry *dst, u32 mtu) { } @@ -127,7 +122,6 @@ static struct dst_ops ip6_dst_blackhole_ops = { .protocol = cpu_to_be16(ETH_P_IPV6), .destroy = ip6_dst_destroy, .check = ip6_dst_check, - .default_mtu = ip6_blackhole_default_mtu, .update_pmtu = ip6_rt_blackhole_update_pmtu, }; @@ -200,6 +194,7 @@ static void ip6_dst_destroy(struct dst_entry *dst) in6_dev_put(idev); } if (peer) { + BUG_ON(!(rt->rt6i_flags & RTF_CACHE)); rt->rt6i_peer = NULL; inet_putpeer(peer); } @@ -209,6 +204,9 @@ void rt6_bind_peer(struct rt6_info *rt, int create) { struct inet_peer *peer; + if (WARN_ON(!(rt->rt6i_flags & RTF_CACHE))) + return; + peer = inet_getpeer_v6(&rt->rt6i_dst.addr, create); if (peer && cmpxchg(&rt->rt6i_peer, NULL, peer) != NULL) inet_putpeer(peer); diff --git a/trunk/net/ipv6/sysctl_net_ipv6.c b/trunk/net/ipv6/sysctl_net_ipv6.c index 7cb65ef79f9c..fa1d8f4e0051 100644 --- a/trunk/net/ipv6/sysctl_net_ipv6.c +++ b/trunk/net/ipv6/sysctl_net_ipv6.c @@ -15,8 +15,6 @@ #include #include -static struct ctl_table empty[1]; - static ctl_table ipv6_table_template[] = { { .procname = "route", @@ -37,12 +35,6 @@ static ctl_table ipv6_table_template[] = { .mode = 0644, .proc_handler = proc_dointvec }, - { - .procname = "neigh", - .maxlen = 0, - .mode = 0555, - .child = empty, - }, { } }; @@ -160,6 +152,7 @@ static struct ctl_table_header *ip6_base; int ipv6_static_sysctl_register(void) { + static struct ctl_table empty[1]; ip6_base = register_sysctl_paths(net_ipv6_ctl_path, empty); if (ip6_base == NULL) return -ENOMEM; diff --git a/trunk/net/netfilter/nf_conntrack_ecache.c b/trunk/net/netfilter/nf_conntrack_ecache.c index 63a1b915a7e4..5702de35e2bb 100644 --- a/trunk/net/netfilter/nf_conntrack_ecache.c +++ b/trunk/net/netfilter/nf_conntrack_ecache.c @@ -63,9 +63,6 @@ void nf_ct_deliver_cached_events(struct nf_conn *ct) * this does not harm and it happens very rarely. */ unsigned long missed = e->missed; - if (!((events | missed) & e->ctmask)) - goto out_unlock; - ret = notify->fcn(events | missed, &item); if (unlikely(ret < 0 || missed)) { spin_lock_bh(&ct->lock); diff --git a/trunk/net/netfilter/nf_conntrack_netlink.c b/trunk/net/netfilter/nf_conntrack_netlink.c index eead9db6f899..93297aaceb2b 100644 --- a/trunk/net/netfilter/nf_conntrack_netlink.c +++ b/trunk/net/netfilter/nf_conntrack_netlink.c @@ -667,7 +667,6 @@ ctnetlink_dump_table(struct sk_buff *skb, struct netlink_callback *cb) if (ctnetlink_fill_info(skb, NETLINK_CB(cb->skb).pid, cb->nlh->nlmsg_seq, IPCTNL_MSG_CT_NEW, ct) < 0) { - nf_conntrack_get(&ct->ct_general); cb->args[1] = (unsigned long)ct; goto out; } diff --git a/trunk/net/netfilter/xt_iprange.c b/trunk/net/netfilter/xt_iprange.c index 73c33a42f87f..88f7c3511c72 100644 --- a/trunk/net/netfilter/xt_iprange.c +++ b/trunk/net/netfilter/xt_iprange.c @@ -53,13 +53,15 @@ iprange_mt4(const struct sk_buff *skb, struct xt_action_param *par) } static inline int -iprange_ipv6_lt(const struct in6_addr *a, const struct in6_addr *b) +iprange_ipv6_sub(const struct in6_addr *a, const struct in6_addr *b) { unsigned int i; + int r; for (i = 0; i < 4; ++i) { - if (a->s6_addr32[i] != b->s6_addr32[i]) - return ntohl(a->s6_addr32[i]) < ntohl(b->s6_addr32[i]); + r = ntohl(a->s6_addr32[i]) - ntohl(b->s6_addr32[i]); + if (r != 0) + return r; } return 0; @@ -73,15 +75,15 @@ iprange_mt6(const struct sk_buff *skb, struct xt_action_param *par) bool m; if (info->flags & IPRANGE_SRC) { - m = iprange_ipv6_lt(&iph->saddr, &info->src_min.in6); - m |= iprange_ipv6_lt(&info->src_max.in6, &iph->saddr); + m = iprange_ipv6_sub(&iph->saddr, &info->src_min.in6) < 0; + m |= iprange_ipv6_sub(&iph->saddr, &info->src_max.in6) > 0; m ^= !!(info->flags & IPRANGE_SRC_INV); if (m) return false; } if (info->flags & IPRANGE_DST) { - m = iprange_ipv6_lt(&iph->daddr, &info->dst_min.in6); - m |= iprange_ipv6_lt(&info->dst_max.in6, &iph->daddr); + m = iprange_ipv6_sub(&iph->daddr, &info->dst_min.in6) < 0; + m |= iprange_ipv6_sub(&iph->daddr, &info->dst_max.in6) > 0; m ^= !!(info->flags & IPRANGE_DST_INV); if (m) return false; diff --git a/trunk/security/selinux/hooks.c b/trunk/security/selinux/hooks.c index c8d699270687..e276eb468536 100644 --- a/trunk/security/selinux/hooks.c +++ b/trunk/security/selinux/hooks.c @@ -3198,11 +3198,7 @@ static void selinux_cred_free(struct cred *cred) { struct task_security_struct *tsec = cred->security; - /* - * cred->security == NULL if security_cred_alloc_blank() or - * security_prepare_creds() returned an error. - */ - BUG_ON(cred->security && (unsigned long) cred->security < PAGE_SIZE); + BUG_ON((unsigned long) cred->security < PAGE_SIZE); cred->security = (void *) 0x7UL; kfree(tsec); } diff --git a/trunk/sound/arm/aaci.c b/trunk/sound/arm/aaci.c index 7c1fc64cb53d..24d3013c0231 100644 --- a/trunk/sound/arm/aaci.c +++ b/trunk/sound/arm/aaci.c @@ -50,11 +50,7 @@ static void aaci_ac97_select_codec(struct aaci *aaci, struct snd_ac97 *ac97) if (v & SLFR_1RXV) readl(aaci->base + AACI_SL1RX); - if (maincr != readl(aaci->base + AACI_MAINCR)) { - writel(maincr, aaci->base + AACI_MAINCR); - readl(aaci->base + AACI_MAINCR); - udelay(1); - } + writel(maincr, aaci->base + AACI_MAINCR); } /* @@ -997,8 +993,6 @@ static unsigned int __devinit aaci_size_fifo(struct aaci *aaci) * disabling the channel doesn't clear the FIFO. */ writel(aaci->maincr & ~MAINCR_IE, aaci->base + AACI_MAINCR); - readl(aaci->base + AACI_MAINCR); - udelay(1); writel(aaci->maincr, aaci->base + AACI_MAINCR); /* diff --git a/trunk/sound/drivers/mtpav.c b/trunk/sound/drivers/mtpav.c index 5c426df87678..da03597fc893 100644 --- a/trunk/sound/drivers/mtpav.c +++ b/trunk/sound/drivers/mtpav.c @@ -55,13 +55,14 @@ #include #include #include -#include #include #include #include #include #include +#include + /* * globals */ diff --git a/trunk/sound/oss/Makefile b/trunk/sound/oss/Makefile index 90ffb99c6b17..96f14dcd0cd1 100644 --- a/trunk/sound/oss/Makefile +++ b/trunk/sound/oss/Makefile @@ -87,7 +87,7 @@ ifeq ($(CONFIG_PSS_HAVE_BOOT),y) $(obj)/bin2hex pss_synth < $< > $@ else $(obj)/pss_boot.h: - $(Q)( \ + ( \ echo 'static unsigned char * pss_synth = NULL;'; \ echo 'static int pss_synthLen = 0;'; \ ) > $@ @@ -102,7 +102,7 @@ ifeq ($(CONFIG_TRIX_HAVE_BOOT),y) $(obj)/hex2hex -i trix_boot < $< > $@ else $(obj)/trix_boot.h: - $(Q)( \ + ( \ echo 'static unsigned char * trix_boot = NULL;'; \ echo 'static int trix_boot_len = 0;'; \ ) > $@ diff --git a/trunk/sound/pci/hda/patch_conexant.c b/trunk/sound/pci/hda/patch_conexant.c index fbe97d32140d..9bb030a469cd 100644 --- a/trunk/sound/pci/hda/patch_conexant.c +++ b/trunk/sound/pci/hda/patch_conexant.c @@ -85,7 +85,6 @@ struct conexant_spec { unsigned int auto_mic; int auto_mic_ext; /* autocfg.inputs[] index for ext mic */ unsigned int need_dac_fix; - hda_nid_t slave_dig_outs[2]; /* capture */ unsigned int num_adc_nids; @@ -128,7 +127,6 @@ struct conexant_spec { unsigned int ideapad:1; unsigned int thinkpad:1; unsigned int hp_laptop:1; - unsigned int asus:1; unsigned int ext_mic_present; unsigned int recording; @@ -354,8 +352,6 @@ static int conexant_build_pcms(struct hda_codec *codec) info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->dig_in_nid; } - if (spec->slave_dig_outs[0]) - codec->slave_dig_outs = spec->slave_dig_outs; } return 0; @@ -407,16 +403,10 @@ static int conexant_add_jack(struct hda_codec *codec, struct conexant_spec *spec; struct conexant_jack *jack; const char *name; - int i, err; + int err; spec = codec->spec; snd_array_init(&spec->jacks, sizeof(*jack), 32); - - jack = spec->jacks.list; - for (i = 0; i < spec->jacks.used; i++, jack++) - if (jack->nid == nid) - return 0 ; /* already present */ - jack = snd_array_new(&spec->jacks); name = (type == SND_JACK_HEADPHONE) ? "Headphone" : "Mic" ; @@ -2110,7 +2100,7 @@ static int patch_cxt5051(struct hda_codec *codec) static hda_nid_t cxt5066_dac_nids[1] = { 0x10 }; static hda_nid_t cxt5066_adc_nids[3] = { 0x14, 0x15, 0x16 }; static hda_nid_t cxt5066_capsrc_nids[1] = { 0x17 }; -static hda_nid_t cxt5066_digout_pin_nids[2] = { 0x20, 0x22 }; +#define CXT5066_SPDIF_OUT 0x21 /* OLPC's microphone port is DC coupled for use with external sensors, * therefore we use a 50% mic bias in order to center the input signal with @@ -2322,19 +2312,6 @@ static void cxt5066_ideapad_automic(struct hda_codec *codec) } } - -/* toggle input of built-in digital mic and mic jack appropriately */ -static void cxt5066_asus_automic(struct hda_codec *codec) -{ - unsigned int present; - - present = snd_hda_jack_detect(codec, 0x1b); - snd_printdd("CXT5066: external microphone present=%d\n", present); - snd_hda_codec_write(codec, 0x17, 0, AC_VERB_SET_CONNECT_SEL, - present ? 1 : 0); -} - - /* toggle input of built-in digital mic and mic jack appropriately */ static void cxt5066_hp_laptop_automic(struct hda_codec *codec) { @@ -2410,23 +2387,6 @@ static void cxt5066_hp_automute(struct hda_codec *codec) cxt5066_update_speaker(codec); } -/* Dispatch the right mic autoswitch function */ -static void cxt5066_automic(struct hda_codec *codec) -{ - struct conexant_spec *spec = codec->spec; - - if (spec->dell_vostro) - cxt5066_vostro_automic(codec); - else if (spec->ideapad) - cxt5066_ideapad_automic(codec); - else if (spec->thinkpad) - cxt5066_thinkpad_automic(codec); - else if (spec->hp_laptop) - cxt5066_hp_laptop_automic(codec); - else if (spec->asus) - cxt5066_asus_automic(codec); -} - /* unsolicited event for jack sensing */ static void cxt5066_olpc_unsol_event(struct hda_codec *codec, unsigned int res) { @@ -2445,19 +2405,60 @@ static void cxt5066_olpc_unsol_event(struct hda_codec *codec, unsigned int res) } /* unsolicited event for jack sensing */ -static void cxt5066_unsol_event(struct hda_codec *codec, unsigned int res) +static void cxt5066_vostro_event(struct hda_codec *codec, unsigned int res) { - snd_printdd("CXT5066: unsol event %x (%x)\n", res, res >> 26); + snd_printdd("CXT5066_vostro: unsol event %x (%x)\n", res, res >> 26); switch (res >> 26) { case CONEXANT_HP_EVENT: cxt5066_hp_automute(codec); break; case CONEXANT_MIC_EVENT: - cxt5066_automic(codec); + cxt5066_vostro_automic(codec); break; } } +/* unsolicited event for jack sensing */ +static void cxt5066_ideapad_event(struct hda_codec *codec, unsigned int res) +{ + snd_printdd("CXT5066_ideapad: unsol event %x (%x)\n", res, res >> 26); + switch (res >> 26) { + case CONEXANT_HP_EVENT: + cxt5066_hp_automute(codec); + break; + case CONEXANT_MIC_EVENT: + cxt5066_ideapad_automic(codec); + break; + } +} + +/* unsolicited event for jack sensing */ +static void cxt5066_hp_laptop_event(struct hda_codec *codec, unsigned int res) +{ + snd_printdd("CXT5066_hp_laptop: unsol event %x (%x)\n", res, res >> 26); + switch (res >> 26) { + case CONEXANT_HP_EVENT: + cxt5066_hp_automute(codec); + break; + case CONEXANT_MIC_EVENT: + cxt5066_hp_laptop_automic(codec); + break; + } +} + +/* unsolicited event for jack sensing */ +static void cxt5066_thinkpad_event(struct hda_codec *codec, unsigned int res) +{ + snd_printdd("CXT5066_thinkpad: unsol event %x (%x)\n", res, res >> 26); + switch (res >> 26) { + case CONEXANT_HP_EVENT: + cxt5066_hp_automute(codec); + break; + case CONEXANT_MIC_EVENT: + cxt5066_thinkpad_automic(codec); + break; + } +} static const struct hda_input_mux cxt5066_analog_mic_boost = { .num_items = 5, @@ -2632,27 +2633,6 @@ static void cxt5066_olpc_capture_cleanup(struct hda_codec *codec) spec->recording = 0; } -static void conexant_check_dig_outs(struct hda_codec *codec, - hda_nid_t *dig_pins, - int num_pins) -{ - struct conexant_spec *spec = codec->spec; - hda_nid_t *nid_loc = &spec->multiout.dig_out_nid; - int i; - - for (i = 0; i < num_pins; i++, dig_pins++) { - unsigned int cfg = snd_hda_codec_get_pincfg(codec, *dig_pins); - if (get_defcfg_connect(cfg) == AC_JACK_PORT_NONE) - continue; - if (snd_hda_get_connections(codec, *dig_pins, nid_loc, 1) != 1) - continue; - if (spec->slave_dig_outs[0]) - nid_loc++; - else - nid_loc = spec->slave_dig_outs; - } -} - static struct hda_input_mux cxt5066_capture_source = { .num_items = 4, .items = { @@ -3059,11 +3039,20 @@ static struct hda_verb cxt5066_init_verbs_hp_laptop[] = { /* initialize jack-sensing, too */ static int cxt5066_init(struct hda_codec *codec) { + struct conexant_spec *spec = codec->spec; + snd_printdd("CXT5066: init\n"); conexant_init(codec); if (codec->patch_ops.unsol_event) { cxt5066_hp_automute(codec); - cxt5066_automic(codec); + if (spec->dell_vostro) + cxt5066_vostro_automic(codec); + else if (spec->ideapad) + cxt5066_ideapad_automic(codec); + else if (spec->thinkpad) + cxt5066_thinkpad_automic(codec); + else if (spec->hp_laptop) + cxt5066_hp_laptop_automic(codec); } cxt5066_set_mic_boost(codec); return 0; @@ -3091,7 +3080,6 @@ enum { CXT5066_DELL_VOSTRO, /* Dell Vostro 1015i */ CXT5066_IDEAPAD, /* Lenovo IdeaPad U150 */ CXT5066_THINKPAD, /* Lenovo ThinkPad T410s, others? */ - CXT5066_ASUS, /* Asus K52JU, Lenovo G560 - Int mic at 0x1a and Ext mic at 0x1b */ CXT5066_HP_LAPTOP, /* HP Laptop */ CXT5066_MODELS }; @@ -3103,7 +3091,6 @@ static const char * const cxt5066_models[CXT5066_MODELS] = { [CXT5066_DELL_VOSTRO] = "dell-vostro", [CXT5066_IDEAPAD] = "ideapad", [CXT5066_THINKPAD] = "thinkpad", - [CXT5066_ASUS] = "asus", [CXT5066_HP_LAPTOP] = "hp-laptop", }; @@ -3115,9 +3102,7 @@ static struct snd_pci_quirk cxt5066_cfg_tbl[] = { SND_PCI_QUIRK(0x1028, 0x0402, "Dell Vostro", CXT5066_DELL_VOSTRO), SND_PCI_QUIRK(0x1028, 0x0408, "Dell Inspiron One 19T", CXT5066_IDEAPAD), SND_PCI_QUIRK(0x103c, 0x360b, "HP G60", CXT5066_HP_LAPTOP), - SND_PCI_QUIRK(0x1043, 0x13f3, "Asus A52J", CXT5066_ASUS), - SND_PCI_QUIRK(0x1043, 0x1643, "Asus K52JU", CXT5066_ASUS), - SND_PCI_QUIRK(0x1043, 0x1993, "Asus U50F", CXT5066_ASUS), + SND_PCI_QUIRK(0x1043, 0x13f3, "Asus A52J", CXT5066_HP_LAPTOP), SND_PCI_QUIRK(0x1179, 0xff1e, "Toshiba Satellite C650D", CXT5066_IDEAPAD), SND_PCI_QUIRK(0x1179, 0xff50, "Toshiba Satellite P500-PSPGSC-01800T", CXT5066_OLPC_XO_1_5), SND_PCI_QUIRK(0x1179, 0xffe0, "Toshiba Satellite Pro T130-15F", CXT5066_OLPC_XO_1_5), @@ -3126,9 +3111,7 @@ static struct snd_pci_quirk cxt5066_cfg_tbl[] = { SND_PCI_QUIRK(0x152d, 0x0833, "OLPC XO-1.5", CXT5066_OLPC_XO_1_5), SND_PCI_QUIRK(0x17aa, 0x20f2, "Lenovo T400s", CXT5066_THINKPAD), SND_PCI_QUIRK(0x17aa, 0x21c5, "Thinkpad Edge 13", CXT5066_THINKPAD), - SND_PCI_QUIRK(0x17aa, 0x21c6, "Thinkpad Edge 13", CXT5066_ASUS), SND_PCI_QUIRK(0x17aa, 0x215e, "Lenovo Thinkpad", CXT5066_THINKPAD), - SND_PCI_QUIRK(0x17aa, 0x38af, "Lenovo G560", CXT5066_ASUS), SND_PCI_QUIRK_VENDOR(0x17aa, "Lenovo", CXT5066_IDEAPAD), /* Fallback for Lenovos without dock mic */ {} }; @@ -3150,8 +3133,7 @@ static int patch_cxt5066(struct hda_codec *codec) spec->multiout.max_channels = 2; spec->multiout.num_dacs = ARRAY_SIZE(cxt5066_dac_nids); spec->multiout.dac_nids = cxt5066_dac_nids; - conexant_check_dig_outs(codec, cxt5066_digout_pin_nids, - ARRAY_SIZE(cxt5066_digout_pin_nids)); + spec->multiout.dig_out_nid = CXT5066_SPDIF_OUT; spec->num_adc_nids = 1; spec->adc_nids = cxt5066_adc_nids; spec->capsrc_nids = cxt5066_capsrc_nids; @@ -3185,20 +3167,17 @@ static int patch_cxt5066(struct hda_codec *codec) spec->num_init_verbs++; spec->dell_automute = 1; break; - case CXT5066_ASUS: case CXT5066_HP_LAPTOP: codec->patch_ops.init = cxt5066_init; - codec->patch_ops.unsol_event = cxt5066_unsol_event; + codec->patch_ops.unsol_event = cxt5066_hp_laptop_event; spec->init_verbs[spec->num_init_verbs] = cxt5066_init_verbs_hp_laptop; spec->num_init_verbs++; - spec->hp_laptop = board_config == CXT5066_HP_LAPTOP; - spec->asus = board_config == CXT5066_ASUS; + spec->hp_laptop = 1; spec->mixers[spec->num_mixers++] = cxt5066_mixer_master; spec->mixers[spec->num_mixers++] = cxt5066_mixers; /* no S/PDIF out */ - if (board_config == CXT5066_HP_LAPTOP) - spec->multiout.dig_out_nid = 0; + spec->multiout.dig_out_nid = 0; /* input source automatically selected */ spec->input_mux = NULL; spec->port_d_mode = 0; @@ -3228,7 +3207,7 @@ static int patch_cxt5066(struct hda_codec *codec) break; case CXT5066_DELL_VOSTRO: codec->patch_ops.init = cxt5066_init; - codec->patch_ops.unsol_event = cxt5066_unsol_event; + codec->patch_ops.unsol_event = cxt5066_vostro_event; spec->init_verbs[0] = cxt5066_init_verbs_vostro; spec->mixers[spec->num_mixers++] = cxt5066_mixer_master_olpc; spec->mixers[spec->num_mixers++] = cxt5066_mixers; @@ -3245,7 +3224,7 @@ static int patch_cxt5066(struct hda_codec *codec) break; case CXT5066_IDEAPAD: codec->patch_ops.init = cxt5066_init; - codec->patch_ops.unsol_event = cxt5066_unsol_event; + codec->patch_ops.unsol_event = cxt5066_ideapad_event; spec->mixers[spec->num_mixers++] = cxt5066_mixer_master; spec->mixers[spec->num_mixers++] = cxt5066_mixers; spec->init_verbs[0] = cxt5066_init_verbs_ideapad; @@ -3261,7 +3240,7 @@ static int patch_cxt5066(struct hda_codec *codec) break; case CXT5066_THINKPAD: codec->patch_ops.init = cxt5066_init; - codec->patch_ops.unsol_event = cxt5066_unsol_event; + codec->patch_ops.unsol_event = cxt5066_thinkpad_event; spec->mixers[spec->num_mixers++] = cxt5066_mixer_master; spec->mixers[spec->num_mixers++] = cxt5066_mixers; spec->init_verbs[0] = cxt5066_init_verbs_thinkpad; diff --git a/trunk/sound/pci/oxygen/oxygen.h b/trunk/sound/pci/oxygen/oxygen.h index f53897a708b4..c2ae63d17cd2 100644 --- a/trunk/sound/pci/oxygen/oxygen.h +++ b/trunk/sound/pci/oxygen/oxygen.h @@ -92,8 +92,6 @@ struct oxygen_model { void (*update_dac_volume)(struct oxygen *chip); void (*update_dac_mute)(struct oxygen *chip); void (*update_center_lfe_mix)(struct oxygen *chip, bool mixed); - unsigned int (*adjust_dac_routing)(struct oxygen *chip, - unsigned int play_routing); void (*gpio_changed)(struct oxygen *chip); void (*uart_input)(struct oxygen *chip); void (*ac97_switch)(struct oxygen *chip, diff --git a/trunk/sound/pci/oxygen/oxygen_mixer.c b/trunk/sound/pci/oxygen/oxygen_mixer.c index 26c7e8bcb229..9bff14d5895d 100644 --- a/trunk/sound/pci/oxygen/oxygen_mixer.c +++ b/trunk/sound/pci/oxygen/oxygen_mixer.c @@ -180,8 +180,6 @@ void oxygen_update_dac_routing(struct oxygen *chip) (1 << OXYGEN_PLAY_DAC1_SOURCE_SHIFT) | (2 << OXYGEN_PLAY_DAC2_SOURCE_SHIFT) | (3 << OXYGEN_PLAY_DAC3_SOURCE_SHIFT); - if (chip->model.adjust_dac_routing) - reg_value = chip->model.adjust_dac_routing(chip, reg_value); oxygen_write16_masked(chip, OXYGEN_PLAY_ROUTING, reg_value, OXYGEN_PLAY_DAC0_SOURCE_MASK | OXYGEN_PLAY_DAC1_SOURCE_MASK | diff --git a/trunk/sound/pci/oxygen/xonar_dg.c b/trunk/sound/pci/oxygen/xonar_dg.c index bc6eb58be380..e1fa602eba79 100644 --- a/trunk/sound/pci/oxygen/xonar_dg.c +++ b/trunk/sound/pci/oxygen/xonar_dg.c @@ -24,11 +24,6 @@ * * SPI 0 -> CS4245 * - * I²S 1 -> CS4245 - * I²S 2 -> CS4361 (center/LFE) - * I²S 3 -> CS4361 (surround) - * I²S 4 -> CS4361 (front) - * * GPIO 3 <- ? * GPIO 4 <- headphone detect * GPIO 5 -> route input jack to line-in (0) or mic-in (1) @@ -41,7 +36,6 @@ * input 1 <- aux * input 2 <- front mic * input 4 <- line/mic - * DAC out -> headphones * aux out -> front panel headphones */ @@ -213,35 +207,6 @@ static void set_cs4245_adc_params(struct oxygen *chip, cs4245_write_cached(chip, CS4245_ADC_CTRL, value); } -static inline unsigned int shift_bits(unsigned int value, - unsigned int shift_from, - unsigned int shift_to, - unsigned int mask) -{ - if (shift_from < shift_to) - return (value << (shift_to - shift_from)) & mask; - else - return (value >> (shift_from - shift_to)) & mask; -} - -static unsigned int adjust_dg_dac_routing(struct oxygen *chip, - unsigned int play_routing) -{ - return (play_routing & OXYGEN_PLAY_DAC0_SOURCE_MASK) | - shift_bits(play_routing, - OXYGEN_PLAY_DAC2_SOURCE_SHIFT, - OXYGEN_PLAY_DAC1_SOURCE_SHIFT, - OXYGEN_PLAY_DAC1_SOURCE_MASK) | - shift_bits(play_routing, - OXYGEN_PLAY_DAC1_SOURCE_SHIFT, - OXYGEN_PLAY_DAC2_SOURCE_SHIFT, - OXYGEN_PLAY_DAC2_SOURCE_MASK) | - shift_bits(play_routing, - OXYGEN_PLAY_DAC0_SOURCE_SHIFT, - OXYGEN_PLAY_DAC3_SOURCE_SHIFT, - OXYGEN_PLAY_DAC3_SOURCE_MASK); -} - static int output_switch_info(struct snd_kcontrol *ctl, struct snd_ctl_elem_info *info) { @@ -592,7 +557,6 @@ struct oxygen_model model_xonar_dg = { .resume = dg_resume, .set_dac_params = set_cs4245_dac_params, .set_adc_params = set_cs4245_adc_params, - .adjust_dac_routing = adjust_dg_dac_routing, .dump_registers = dump_cs4245_registers, .model_data_size = sizeof(struct dg), .device_config = PLAYBACK_0_TO_I2S | diff --git a/trunk/sound/pcmcia/pdaudiocf/pdaudiocf.h b/trunk/sound/pcmcia/pdaudiocf/pdaudiocf.h index 6ce9ad700290..bd26e092aead 100644 --- a/trunk/sound/pcmcia/pdaudiocf/pdaudiocf.h +++ b/trunk/sound/pcmcia/pdaudiocf/pdaudiocf.h @@ -22,7 +22,7 @@ #define __PDAUDIOCF_H #include -#include +#include #include #include #include diff --git a/trunk/sound/pcmcia/vx/vxp_ops.c b/trunk/sound/pcmcia/vx/vxp_ops.c index fe33e122e372..989e04abb520 100644 --- a/trunk/sound/pcmcia/vx/vxp_ops.c +++ b/trunk/sound/pcmcia/vx/vxp_ops.c @@ -23,8 +23,8 @@ #include #include #include -#include #include +#include #include "vxpocket.h" diff --git a/trunk/sound/soc/codecs/cq93vc.c b/trunk/sound/soc/codecs/cq93vc.c index 347a567b01e1..46dbfd067f79 100644 --- a/trunk/sound/soc/codecs/cq93vc.c +++ b/trunk/sound/soc/codecs/cq93vc.c @@ -153,7 +153,7 @@ static int cq93vc_resume(struct snd_soc_codec *codec) static int cq93vc_probe(struct snd_soc_codec *codec) { - struct davinci_vc *davinci_vc = snd_soc_codec_get_drvdata(codec); + struct davinci_vc *davinci_vc = codec->dev->platform_data; davinci_vc->cq93vc.codec = codec; codec->control_data = davinci_vc; diff --git a/trunk/sound/soc/codecs/cx20442.c b/trunk/sound/soc/codecs/cx20442.c index bb4bf65b9e7e..03d1e860d229 100644 --- a/trunk/sound/soc/codecs/cx20442.c +++ b/trunk/sound/soc/codecs/cx20442.c @@ -367,12 +367,9 @@ static int cx20442_codec_remove(struct snd_soc_codec *codec) return 0; } -static const u8 cx20442_reg = CX20442_TELOUT | CX20442_MIC; - static struct snd_soc_codec_driver cx20442_codec_dev = { .probe = cx20442_codec_probe, .remove = cx20442_codec_remove, - .reg_cache_default = &cx20442_reg, .reg_cache_size = 1, .reg_word_size = sizeof(u8), .read = cx20442_read_reg_cache, diff --git a/trunk/sound/soc/omap/ams-delta.c b/trunk/sound/soc/omap/ams-delta.c index 3167be689621..2101bdcee21f 100644 --- a/trunk/sound/soc/omap/ams-delta.c +++ b/trunk/sound/soc/omap/ams-delta.c @@ -507,6 +507,8 @@ static int ams_delta_cx20442_init(struct snd_soc_pcm_runtime *rtd) /* Set up digital mute if not provided by the codec */ if (!codec_dai->driver->ops) { codec_dai->driver->ops = &ams_delta_dai_ops; + } else if (!codec_dai->driver->ops->digital_mute) { + codec_dai->driver->ops->digital_mute = ams_delta_digital_mute; } else { ams_delta_ops.startup = ams_delta_startup; ams_delta_ops.shutdown = ams_delta_shutdown; diff --git a/trunk/sound/soc/soc-core.c b/trunk/sound/soc/soc-core.c index c4b60610beb0..bac7291b6ff6 100644 --- a/trunk/sound/soc/soc-core.c +++ b/trunk/sound/soc/soc-core.c @@ -1664,6 +1664,9 @@ static int soc_probe_aux_dev(struct snd_soc_card *card, int num) goto out; found: + if (!try_module_get(codec->dev->driver->owner)) + return -ENODEV; + ret = soc_probe_codec(card, codec); if (ret < 0) return ret; diff --git a/trunk/sound/soc/soc-dapm.c b/trunk/sound/soc/soc-dapm.c index 8194f150bab7..499730ab5638 100644 --- a/trunk/sound/soc/soc-dapm.c +++ b/trunk/sound/soc/soc-dapm.c @@ -1742,7 +1742,7 @@ int snd_soc_dapm_put_volsw(struct snd_kcontrol *kcontrol, int max = mc->max; unsigned int mask = (1 << fls(max)) - 1; unsigned int invert = mc->invert; - unsigned int val; + unsigned int val, val_mask; int connect, change; struct snd_soc_dapm_update update; @@ -1750,13 +1750,13 @@ int snd_soc_dapm_put_volsw(struct snd_kcontrol *kcontrol, if (invert) val = max - val; - mask = mask << shift; + val_mask = mask << shift; val = val << shift; mutex_lock(&widget->codec->mutex); widget->value = val; - change = snd_soc_test_bits(widget->codec, reg, mask, val); + change = snd_soc_test_bits(widget->codec, reg, val_mask, val); if (change) { if (val) /* new connection */ diff --git a/trunk/tools/perf/Documentation/perf-probe.txt b/trunk/tools/perf/Documentation/perf-probe.txt index 81c3220e04f3..86b797a35aa6 100644 --- a/trunk/tools/perf/Documentation/perf-probe.txt +++ b/trunk/tools/perf/Documentation/perf-probe.txt @@ -73,17 +73,6 @@ OPTIONS (Only for --vars) Show external defined variables in addition to local variables. --F:: ---funcs:: - Show available functions in given module or kernel. - ---filter=FILTER:: - (Only for --vars and --funcs) Set filter. FILTER is a combination of glob - pattern, see FILTER PATTERN for detail. - Default FILTER is "!__k???tab_* & !__crc_*" for --vars, and "!_*" - for --funcs. - If several filters are specified, only the last filter is used. - -f:: --force:: Forcibly add events with existing name. @@ -146,14 +135,6 @@ e.g. This provides some sort of flexibility and robustness to probe point definitions against minor code changes. For example, actual 10th line of schedule() can be moved easily by modifying schedule(), but the same line matching 'rq=cpu_rq*' may still exist in the function.) -FILTER PATTERN --------------- - The filter pattern is a glob matching pattern(s) to filter variables. - In addition, you can use "!" for specifying filter-out rule. You also can give several rules combined with "&" or "|", and fold those rules as one rule by using "(" ")". - -e.g. - With --filter "foo* | bar*", perf probe -V shows variables which start with "foo" or "bar". - With --filter "!foo* & *bar", perf probe -V shows variables which don't start with "foo" and end with "bar", like "fizzbar". But "foobar" is filtered out. EXAMPLES -------- diff --git a/trunk/tools/perf/Makefile b/trunk/tools/perf/Makefile index 94f73abdc56a..7141c42e1469 100644 --- a/trunk/tools/perf/Makefile +++ b/trunk/tools/perf/Makefile @@ -315,7 +315,6 @@ COMPAT_CFLAGS = COMPAT_OBJS = LIB_H = LIB_OBJS = -PYRF_OBJS = SCRIPT_PERL = SCRIPT_SH = TEST_PROGRAMS = @@ -325,9 +324,6 @@ SCRIPT_SH += perf-archive.sh grep-libs = $(filter -l%,$(1)) strip-libs = $(filter-out -l%,$(1)) -$(OUTPUT)python/perf.so: $(PYRF_OBJS) - $(QUIET_GEN)python util/setup.py --quiet build_ext --build-lib='$(OUTPUT)python' \ - --build-temp='$(OUTPUT)python/temp' # # No Perl scripts right now: # @@ -348,8 +344,6 @@ PROGRAMS += $(EXTRA_PROGRAMS) # PROGRAMS += $(OUTPUT)perf -LANG_BINDINGS = - # List built-in command $C whose implementation cmd_$C() is not in # builtin-$C.o but is linked in as part of some other command. # @@ -401,7 +395,6 @@ LIB_H += util/include/dwarf-regs.h LIB_H += util/include/asm/dwarf2.h LIB_H += util/include/asm/cpufeature.h LIB_H += perf.h -LIB_H += util/annotate.h LIB_H += util/cache.h LIB_H += util/callchain.h LIB_H += util/build-id.h @@ -409,7 +402,6 @@ LIB_H += util/debug.h LIB_H += util/debugfs.h LIB_H += util/event.h LIB_H += util/evsel.h -LIB_H += util/evlist.h LIB_H += util/exec_cmd.h LIB_H += util/types.h LIB_H += util/levenshtein.h @@ -424,7 +416,6 @@ LIB_H += util/help.h LIB_H += util/session.h LIB_H += util/strbuf.h LIB_H += util/strlist.h -LIB_H += util/strfilter.h LIB_H += util/svghelper.h LIB_H += util/run-command.h LIB_H += util/sigchain.h @@ -434,25 +425,21 @@ LIB_H += util/values.h LIB_H += util/sort.h LIB_H += util/hist.h LIB_H += util/thread.h -LIB_H += util/thread_map.h LIB_H += util/trace-event.h LIB_H += util/probe-finder.h LIB_H += util/probe-event.h LIB_H += util/pstack.h LIB_H += util/cpumap.h -LIB_H += util/top.h LIB_H += $(ARCH_INCLUDE) LIB_OBJS += $(OUTPUT)util/abspath.o LIB_OBJS += $(OUTPUT)util/alias.o -LIB_OBJS += $(OUTPUT)util/annotate.o LIB_OBJS += $(OUTPUT)util/build-id.o LIB_OBJS += $(OUTPUT)util/config.o LIB_OBJS += $(OUTPUT)util/ctype.o LIB_OBJS += $(OUTPUT)util/debugfs.o LIB_OBJS += $(OUTPUT)util/environment.o LIB_OBJS += $(OUTPUT)util/event.o -LIB_OBJS += $(OUTPUT)util/evlist.o LIB_OBJS += $(OUTPUT)util/evsel.o LIB_OBJS += $(OUTPUT)util/exec_cmd.o LIB_OBJS += $(OUTPUT)util/help.o @@ -468,8 +455,6 @@ LIB_OBJS += $(OUTPUT)util/quote.o LIB_OBJS += $(OUTPUT)util/strbuf.o LIB_OBJS += $(OUTPUT)util/string.o LIB_OBJS += $(OUTPUT)util/strlist.o -LIB_OBJS += $(OUTPUT)util/strfilter.o -LIB_OBJS += $(OUTPUT)util/top.o LIB_OBJS += $(OUTPUT)util/usage.o LIB_OBJS += $(OUTPUT)util/wrapper.o LIB_OBJS += $(OUTPUT)util/sigchain.o @@ -484,7 +469,6 @@ LIB_OBJS += $(OUTPUT)util/map.o LIB_OBJS += $(OUTPUT)util/pstack.o LIB_OBJS += $(OUTPUT)util/session.o LIB_OBJS += $(OUTPUT)util/thread.o -LIB_OBJS += $(OUTPUT)util/thread_map.o LIB_OBJS += $(OUTPUT)util/trace-event-parse.o LIB_OBJS += $(OUTPUT)util/trace-event-read.o LIB_OBJS += $(OUTPUT)util/trace-event-info.o @@ -530,20 +514,6 @@ BUILTIN_OBJS += $(OUTPUT)builtin-inject.o PERFLIBS = $(LIB_FILE) -# Files needed for the python binding, perf.so -# pyrf is just an internal name needed for all those wrappers. -# This has to be in sync with what is in the 'sources' variable in -# tools/perf/util/setup.py - -PYRF_OBJS += $(OUTPUT)util/cpumap.o -PYRF_OBJS += $(OUTPUT)util/ctype.o -PYRF_OBJS += $(OUTPUT)util/evlist.o -PYRF_OBJS += $(OUTPUT)util/evsel.o -PYRF_OBJS += $(OUTPUT)util/python.o -PYRF_OBJS += $(OUTPUT)util/thread_map.o -PYRF_OBJS += $(OUTPUT)util/util.o -PYRF_OBJS += $(OUTPUT)util/xyarray.o - # # Platform specific tweaks # @@ -625,7 +595,6 @@ else LIB_OBJS += $(OUTPUT)util/ui/browsers/annotate.o LIB_OBJS += $(OUTPUT)util/ui/browsers/hists.o LIB_OBJS += $(OUTPUT)util/ui/browsers/map.o - LIB_OBJS += $(OUTPUT)util/ui/browsers/top.o LIB_OBJS += $(OUTPUT)util/ui/helpline.o LIB_OBJS += $(OUTPUT)util/ui/progress.o LIB_OBJS += $(OUTPUT)util/ui/util.o @@ -666,14 +635,12 @@ else PYTHON_EMBED_CCOPTS = `python-config --cflags 2>/dev/null` FLAGS_PYTHON_EMBED=$(PYTHON_EMBED_CCOPTS) $(PYTHON_EMBED_LDOPTS) ifneq ($(call try-cc,$(SOURCE_PYTHON_EMBED),$(FLAGS_PYTHON_EMBED)),y) - msg := $(warning No Python.h found, install python-dev[el] to have python support in 'perf script' and to build the python bindings) BASIC_CFLAGS += -DNO_LIBPYTHON else ALL_LDFLAGS += $(PYTHON_EMBED_LDFLAGS) EXTLIBS += $(PYTHON_EMBED_LIBADD) LIB_OBJS += $(OUTPUT)util/scripting-engines/trace-event-python.o LIB_OBJS += $(OUTPUT)scripts/python/Perf-Trace-Util/Context.o - LANG_BINDINGS += $(OUTPUT)python/perf.so endif endif @@ -960,7 +927,7 @@ export TAR INSTALL DESTDIR SHELL_PATH SHELL = $(SHELL_PATH) -all:: shell_compatibility_test $(ALL_PROGRAMS) $(LANG_BINDINGS) $(BUILT_INS) $(OTHER_PROGRAMS) $(OUTPUT)PERF-BUILD-OPTIONS +all:: shell_compatibility_test $(ALL_PROGRAMS) $(BUILT_INS) $(OTHER_PROGRAMS) $(OUTPUT)PERF-BUILD-OPTIONS ifneq (,$X) $(foreach p,$(patsubst %$X,%,$(filter %$X,$(ALL_PROGRAMS) $(BUILT_INS) perf$X)), test '$p' -ef '$p$X' || $(RM) '$p';) endif @@ -1057,9 +1024,6 @@ $(OUTPUT)util/ui/browser.o: util/ui/browser.c $(OUTPUT)PERF-CFLAGS $(OUTPUT)util/ui/browsers/annotate.o: util/ui/browsers/annotate.c $(OUTPUT)PERF-CFLAGS $(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) -DENABLE_SLFUTURE_CONST $< -$(OUTPUT)util/ui/browsers/top.o: util/ui/browsers/top.c $(OUTPUT)PERF-CFLAGS - $(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) -DENABLE_SLFUTURE_CONST $< - $(OUTPUT)util/ui/browsers/hists.o: util/ui/browsers/hists.c $(OUTPUT)PERF-CFLAGS $(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) -DENABLE_SLFUTURE_CONST $< @@ -1293,17 +1257,17 @@ distclean: clean # $(RM) configure clean: - $(RM) $(OUTPUT){*.o,*/*.o,*/*/*.o,*/*/*/*.o,$(LIB_FILE),perf-archive} + $(RM) *.o */*.o */*/*.o */*/*/*.o $(LIB_FILE) $(RM) $(ALL_PROGRAMS) $(BUILT_INS) perf$X $(RM) $(TEST_PROGRAMS) $(RM) *.spec *.pyc *.pyo */*.pyc */*.pyo $(OUTPUT)common-cmds.h TAGS tags cscope* + $(RM) -r autom4te.cache + $(RM) config.log config.mak.autogen config.mak.append config.status config.cache $(RM) -r $(PERF_TARNAME) .doc-tmp-dir $(RM) $(PERF_TARNAME).tar.gz perf-core_$(PERF_VERSION)-*.tar.gz $(RM) $(htmldocs).tar.gz $(manpages).tar.gz $(MAKE) -C Documentation/ clean $(RM) $(OUTPUT)PERF-VERSION-FILE $(OUTPUT)PERF-CFLAGS $(OUTPUT)PERF-BUILD-OPTIONS - @python util/setup.py clean --build-lib='$(OUTPUT)python' \ - --build-temp='$(OUTPUT)python/temp' .PHONY: all install clean strip .PHONY: shell_compatibility_test please_set_SHELL_PATH_to_a_more_modern_shell diff --git a/trunk/tools/perf/bench/sched-pipe.c b/trunk/tools/perf/bench/sched-pipe.c index 0c7454f8b8a9..d9ab3ce446ac 100644 --- a/trunk/tools/perf/bench/sched-pipe.c +++ b/trunk/tools/perf/bench/sched-pipe.c @@ -55,7 +55,7 @@ int bench_sched_pipe(int argc, const char **argv, * discarding returned value of read(), write() * causes error in building environment for perf */ - int __used ret, wait_stat; + int ret, wait_stat; pid_t pid, retpid; argc = parse_options(argc, argv, options, diff --git a/trunk/tools/perf/builtin-annotate.c b/trunk/tools/perf/builtin-annotate.c index 427182953fd7..8879463807e4 100644 --- a/trunk/tools/perf/builtin-annotate.c +++ b/trunk/tools/perf/builtin-annotate.c @@ -9,7 +9,6 @@ #include "util/util.h" -#include "util/util.h" #include "util/color.h" #include #include "util/cache.h" @@ -19,7 +18,6 @@ #include "perf.h" #include "util/debug.h" -#include "util/annotate.h" #include "util/event.h" #include "util/parse-options.h" #include "util/parse-events.h" @@ -57,29 +55,15 @@ static int hists__add_entry(struct hists *self, struct addr_location *al) if (he == NULL) return -ENOMEM; - if (he->ms.sym != NULL) { - /* - * All aggregated on the first sym_hist. - */ - struct annotation *notes = symbol__annotation(he->ms.sym); - if (notes->src == NULL && - symbol__alloc_hist(he->ms.sym, 1) < 0) - return -ENOMEM; - - return hist_entry__inc_addr_samples(he, 0, al->addr); - } - - return 0; + return hist_entry__inc_addr_samples(he, al->addr); } -static int process_sample_event(union perf_event *event, - struct perf_sample *sample, +static int process_sample_event(event_t *event, struct sample_data *sample, struct perf_session *session) { struct addr_location al; - if (perf_event__preprocess_sample(event, session, &al, sample, - symbol__annotate_init) < 0) { + if (event__preprocess_sample(event, session, &al, sample, NULL) < 0) { pr_warning("problem processing %d event, skipping it.\n", event->header.type); return -1; @@ -94,10 +78,245 @@ static int process_sample_event(union perf_event *event, return 0; } -static int hist_entry__tty_annotate(struct hist_entry *he, int evidx) +static int objdump_line__print(struct objdump_line *self, + struct list_head *head, + struct hist_entry *he, u64 len) +{ + struct symbol *sym = he->ms.sym; + static const char *prev_line; + static const char *prev_color; + + if (self->offset != -1) { + const char *path = NULL; + unsigned int hits = 0; + double percent = 0.0; + const char *color; + struct sym_priv *priv = symbol__priv(sym); + struct sym_ext *sym_ext = priv->ext; + struct sym_hist *h = priv->hist; + s64 offset = self->offset; + struct objdump_line *next = objdump__get_next_ip_line(head, self); + + while (offset < (s64)len && + (next == NULL || offset < next->offset)) { + if (sym_ext) { + if (path == NULL) + path = sym_ext[offset].path; + percent += sym_ext[offset].percent; + } else + hits += h->ip[offset]; + + ++offset; + } + + if (sym_ext == NULL && h->sum) + percent = 100.0 * hits / h->sum; + + color = get_percent_color(percent); + + /* + * Also color the filename and line if needed, with + * the same color than the percentage. Don't print it + * twice for close colored ip with the same filename:line + */ + if (path) { + if (!prev_line || strcmp(prev_line, path) + || color != prev_color) { + color_fprintf(stdout, color, " %s", path); + prev_line = path; + prev_color = color; + } + } + + color_fprintf(stdout, color, " %7.2f", percent); + printf(" : "); + color_fprintf(stdout, PERF_COLOR_BLUE, "%s\n", self->line); + } else { + if (!*self->line) + printf(" :\n"); + else + printf(" : %s\n", self->line); + } + + return 0; +} + +static struct rb_root root_sym_ext; + +static void insert_source_line(struct sym_ext *sym_ext) +{ + struct sym_ext *iter; + struct rb_node **p = &root_sym_ext.rb_node; + struct rb_node *parent = NULL; + + while (*p != NULL) { + parent = *p; + iter = rb_entry(parent, struct sym_ext, node); + + if (sym_ext->percent > iter->percent) + p = &(*p)->rb_left; + else + p = &(*p)->rb_right; + } + + rb_link_node(&sym_ext->node, parent, p); + rb_insert_color(&sym_ext->node, &root_sym_ext); +} + +static void free_source_line(struct hist_entry *he, int len) +{ + struct sym_priv *priv = symbol__priv(he->ms.sym); + struct sym_ext *sym_ext = priv->ext; + int i; + + if (!sym_ext) + return; + + for (i = 0; i < len; i++) + free(sym_ext[i].path); + free(sym_ext); + + priv->ext = NULL; + root_sym_ext = RB_ROOT; +} + +/* Get the filename:line for the colored entries */ +static void +get_source_line(struct hist_entry *he, int len, const char *filename) +{ + struct symbol *sym = he->ms.sym; + u64 start; + int i; + char cmd[PATH_MAX * 2]; + struct sym_ext *sym_ext; + struct sym_priv *priv = symbol__priv(sym); + struct sym_hist *h = priv->hist; + + if (!h->sum) + return; + + sym_ext = priv->ext = calloc(len, sizeof(struct sym_ext)); + if (!priv->ext) + return; + + start = he->ms.map->unmap_ip(he->ms.map, sym->start); + + for (i = 0; i < len; i++) { + char *path = NULL; + size_t line_len; + u64 offset; + FILE *fp; + + sym_ext[i].percent = 100.0 * h->ip[i] / h->sum; + if (sym_ext[i].percent <= 0.5) + continue; + + offset = start + i; + sprintf(cmd, "addr2line -e %s %016" PRIx64, filename, offset); + fp = popen(cmd, "r"); + if (!fp) + continue; + + if (getline(&path, &line_len, fp) < 0 || !line_len) + goto next; + + sym_ext[i].path = malloc(sizeof(char) * line_len + 1); + if (!sym_ext[i].path) + goto next; + + strcpy(sym_ext[i].path, path); + insert_source_line(&sym_ext[i]); + + next: + pclose(fp); + } +} + +static void print_summary(const char *filename) { - return symbol__tty_annotate(he->ms.sym, he->ms.map, evidx, - print_line, full_paths, 0, 0); + struct sym_ext *sym_ext; + struct rb_node *node; + + printf("\nSorted summary for file %s\n", filename); + printf("----------------------------------------------\n\n"); + + if (RB_EMPTY_ROOT(&root_sym_ext)) { + printf(" Nothing higher than %1.1f%%\n", MIN_GREEN); + return; + } + + node = rb_first(&root_sym_ext); + while (node) { + double percent; + const char *color; + char *path; + + sym_ext = rb_entry(node, struct sym_ext, node); + percent = sym_ext->percent; + color = get_percent_color(percent); + path = sym_ext->path; + + color_fprintf(stdout, color, " %7.2f %s", percent, path); + node = rb_next(node); + } +} + +static void hist_entry__print_hits(struct hist_entry *self) +{ + struct symbol *sym = self->ms.sym; + struct sym_priv *priv = symbol__priv(sym); + struct sym_hist *h = priv->hist; + u64 len = sym->end - sym->start, offset; + + for (offset = 0; offset < len; ++offset) + if (h->ip[offset] != 0) + printf("%*" PRIx64 ": %" PRIu64 "\n", BITS_PER_LONG / 2, + sym->start + offset, h->ip[offset]); + printf("%*s: %" PRIu64 "\n", BITS_PER_LONG / 2, "h->sum", h->sum); +} + +static int hist_entry__tty_annotate(struct hist_entry *he) +{ + struct map *map = he->ms.map; + struct dso *dso = map->dso; + struct symbol *sym = he->ms.sym; + const char *filename = dso->long_name, *d_filename; + u64 len; + LIST_HEAD(head); + struct objdump_line *pos, *n; + + if (hist_entry__annotate(he, &head, 0) < 0) + return -1; + + if (full_paths) + d_filename = filename; + else + d_filename = basename(filename); + + len = sym->end - sym->start; + + if (print_line) { + get_source_line(he, len, filename); + print_summary(filename); + } + + printf("\n\n------------------------------------------------\n"); + printf(" Percent | Source code & Disassembly of %s\n", d_filename); + printf("------------------------------------------------\n"); + + if (verbose) + hist_entry__print_hits(he); + + list_for_each_entry_safe(pos, n, &head, node) { + objdump_line__print(pos, &head, he, len); + list_del(&pos->node); + objdump_line__free(pos); + } + + if (print_line) + free_source_line(he, len); + + return 0; } static void hists__find_annotations(struct hists *self) @@ -107,13 +326,13 @@ static void hists__find_annotations(struct hists *self) while (nd) { struct hist_entry *he = rb_entry(nd, struct hist_entry, rb_node); - struct annotation *notes; + struct sym_priv *priv; if (he->ms.sym == NULL || he->ms.map->dso->annotate_warned) goto find_next; - notes = symbol__annotation(he->ms.sym); - if (notes->src == NULL) { + priv = symbol__priv(he->ms.sym); + if (priv->hist == NULL) { find_next: if (key == KEY_LEFT) nd = rb_prev(nd); @@ -123,8 +342,7 @@ static void hists__find_annotations(struct hists *self) } if (use_browser > 0) { - /* For now all is aggregated on the first */ - key = hist_entry__tui_annotate(he, 0); + key = hist_entry__tui_annotate(he); switch (key) { case KEY_RIGHT: next = rb_next(nd); @@ -139,25 +357,24 @@ static void hists__find_annotations(struct hists *self) if (next != NULL) nd = next; } else { - /* For now all is aggregated on the first */ - hist_entry__tty_annotate(he, 0); + hist_entry__tty_annotate(he); nd = rb_next(nd); /* * Since we have a hist_entry per IP for the same - * symbol, free he->ms.sym->src to signal we already + * symbol, free he->ms.sym->hist to signal we already * processed this symbol. */ - free(notes->src); - notes->src = NULL; + free(priv->hist); + priv->hist = NULL; } } } static struct perf_event_ops event_ops = { .sample = process_sample_event, - .mmap = perf_event__process_mmap, - .comm = perf_event__process_comm, - .fork = perf_event__process_task, + .mmap = event__process_mmap, + .comm = event__process_comm, + .fork = event__process_task, .ordered_samples = true, .ordering_requires_timestamps = true, }; @@ -234,9 +451,9 @@ int cmd_annotate(int argc, const char **argv, const char *prefix __used) else if (use_tui) use_browser = 1; - setup_browser(true); + setup_browser(); - symbol_conf.priv_size = sizeof(struct annotation); + symbol_conf.priv_size = sizeof(struct sym_priv); symbol_conf.try_vmlinux_path = true; if (symbol__init() < 0) diff --git a/trunk/tools/perf/builtin-diff.c b/trunk/tools/perf/builtin-diff.c index 6b7d91160ecb..3153e492dbcc 100644 --- a/trunk/tools/perf/builtin-diff.c +++ b/trunk/tools/perf/builtin-diff.c @@ -30,13 +30,13 @@ static int hists__add_entry(struct hists *self, return -ENOMEM; } -static int diff__process_sample_event(union perf_event *event, - struct perf_sample *sample, +static int diff__process_sample_event(event_t *event, + struct sample_data *sample, struct perf_session *session) { struct addr_location al; - if (perf_event__preprocess_sample(event, session, &al, sample, NULL) < 0) { + if (event__preprocess_sample(event, session, &al, sample, NULL) < 0) { pr_warning("problem processing %d event, skipping it.\n", event->header.type); return -1; @@ -56,11 +56,11 @@ static int diff__process_sample_event(union perf_event *event, static struct perf_event_ops event_ops = { .sample = diff__process_sample_event, - .mmap = perf_event__process_mmap, - .comm = perf_event__process_comm, - .exit = perf_event__process_task, - .fork = perf_event__process_task, - .lost = perf_event__process_lost, + .mmap = event__process_mmap, + .comm = event__process_comm, + .exit = event__process_task, + .fork = event__process_task, + .lost = event__process_lost, .ordered_samples = true, .ordering_requires_timestamps = true, }; diff --git a/trunk/tools/perf/builtin-inject.c b/trunk/tools/perf/builtin-inject.c index e29f04ed3396..0c78ffa7bf67 100644 --- a/trunk/tools/perf/builtin-inject.c +++ b/trunk/tools/perf/builtin-inject.c @@ -16,8 +16,8 @@ static char const *input_name = "-"; static bool inject_build_ids; -static int perf_event__repipe_synth(union perf_event *event, - struct perf_session *session __used) +static int event__repipe_synth(event_t *event, + struct perf_session *session __used) { uint32_t size; void *buf = event; @@ -36,44 +36,41 @@ static int perf_event__repipe_synth(union perf_event *event, return 0; } -static int perf_event__repipe(union perf_event *event, - struct perf_sample *sample __used, - struct perf_session *session) +static int event__repipe(event_t *event, struct sample_data *sample __used, + struct perf_session *session) { - return perf_event__repipe_synth(event, session); + return event__repipe_synth(event, session); } -static int perf_event__repipe_mmap(union perf_event *event, - struct perf_sample *sample, - struct perf_session *session) +static int event__repipe_mmap(event_t *self, struct sample_data *sample, + struct perf_session *session) { int err; - err = perf_event__process_mmap(event, sample, session); - perf_event__repipe(event, sample, session); + err = event__process_mmap(self, sample, session); + event__repipe(self, sample, session); return err; } -static int perf_event__repipe_task(union perf_event *event, - struct perf_sample *sample, - struct perf_session *session) +static int event__repipe_task(event_t *self, struct sample_data *sample, + struct perf_session *session) { int err; - err = perf_event__process_task(event, sample, session); - perf_event__repipe(event, sample, session); + err = event__process_task(self, sample, session); + event__repipe(self, sample, session); return err; } -static int perf_event__repipe_tracing_data(union perf_event *event, - struct perf_session *session) +static int event__repipe_tracing_data(event_t *self, + struct perf_session *session) { int err; - perf_event__repipe_synth(event, session); - err = perf_event__process_tracing_data(event, session); + event__repipe_synth(self, session); + err = event__process_tracing_data(self, session); return err; } @@ -112,8 +109,8 @@ static int dso__inject_build_id(struct dso *self, struct perf_session *session) if (self->kernel) misc = PERF_RECORD_MISC_KERNEL; - err = perf_event__synthesize_build_id(self, misc, perf_event__repipe, - machine, session); + err = event__synthesize_build_id(self, misc, event__repipe, + machine, session); if (err) { pr_err("Can't synthesize build_id event for %s\n", self->long_name); return -1; @@ -122,9 +119,8 @@ static int dso__inject_build_id(struct dso *self, struct perf_session *session) return 0; } -static int perf_event__inject_buildid(union perf_event *event, - struct perf_sample *sample, - struct perf_session *session) +static int event__inject_buildid(event_t *event, struct sample_data *sample, + struct perf_session *session) { struct addr_location al; struct thread *thread; @@ -159,24 +155,24 @@ static int perf_event__inject_buildid(union perf_event *event, } repipe: - perf_event__repipe(event, sample, session); + event__repipe(event, sample, session); return 0; } struct perf_event_ops inject_ops = { - .sample = perf_event__repipe, - .mmap = perf_event__repipe, - .comm = perf_event__repipe, - .fork = perf_event__repipe, - .exit = perf_event__repipe, - .lost = perf_event__repipe, - .read = perf_event__repipe, - .throttle = perf_event__repipe, - .unthrottle = perf_event__repipe, - .attr = perf_event__repipe_synth, - .event_type = perf_event__repipe_synth, - .tracing_data = perf_event__repipe_synth, - .build_id = perf_event__repipe_synth, + .sample = event__repipe, + .mmap = event__repipe, + .comm = event__repipe, + .fork = event__repipe, + .exit = event__repipe, + .lost = event__repipe, + .read = event__repipe, + .throttle = event__repipe, + .unthrottle = event__repipe, + .attr = event__repipe_synth, + .event_type = event__repipe_synth, + .tracing_data = event__repipe_synth, + .build_id = event__repipe_synth, }; extern volatile int session_done; @@ -194,10 +190,10 @@ static int __cmd_inject(void) signal(SIGINT, sig_handler); if (inject_build_ids) { - inject_ops.sample = perf_event__inject_buildid; - inject_ops.mmap = perf_event__repipe_mmap; - inject_ops.fork = perf_event__repipe_task; - inject_ops.tracing_data = perf_event__repipe_tracing_data; + inject_ops.sample = event__inject_buildid; + inject_ops.mmap = event__repipe_mmap; + inject_ops.fork = event__repipe_task; + inject_ops.tracing_data = event__repipe_tracing_data; } session = perf_session__new(input_name, O_RDONLY, false, true, &inject_ops); diff --git a/trunk/tools/perf/builtin-kmem.c b/trunk/tools/perf/builtin-kmem.c index 7f618f4e7b79..d97256d65980 100644 --- a/trunk/tools/perf/builtin-kmem.c +++ b/trunk/tools/perf/builtin-kmem.c @@ -275,8 +275,9 @@ static void process_free_event(void *data, s_alloc->alloc_cpu = -1; } -static void process_raw_event(union perf_event *raw_event __used, void *data, - int cpu, u64 timestamp, struct thread *thread) +static void +process_raw_event(event_t *raw_event __used, void *data, + int cpu, u64 timestamp, struct thread *thread) { struct event *event; int type; @@ -303,8 +304,7 @@ static void process_raw_event(union perf_event *raw_event __used, void *data, } } -static int process_sample_event(union perf_event *event, - struct perf_sample *sample, +static int process_sample_event(event_t *event, struct sample_data *sample, struct perf_session *session) { struct thread *thread = perf_session__findnew(session, event->ip.pid); @@ -325,7 +325,7 @@ static int process_sample_event(union perf_event *event, static struct perf_event_ops event_ops = { .sample = process_sample_event, - .comm = perf_event__process_comm, + .comm = event__process_comm, .ordered_samples = true, }; diff --git a/trunk/tools/perf/builtin-lock.c b/trunk/tools/perf/builtin-lock.c index e00d93847c44..2b36defc5d73 100644 --- a/trunk/tools/perf/builtin-lock.c +++ b/trunk/tools/perf/builtin-lock.c @@ -834,14 +834,14 @@ static void dump_info(void) die("Unknown type of information\n"); } -static int process_sample_event(union perf_event *event, struct perf_sample *sample, +static int process_sample_event(event_t *self, struct sample_data *sample, struct perf_session *s) { struct thread *thread = perf_session__findnew(s, sample->tid); if (thread == NULL) { pr_debug("problem processing %d event, skipping it.\n", - event->header.type); + self->header.type); return -1; } @@ -852,7 +852,7 @@ static int process_sample_event(union perf_event *event, struct perf_sample *sam static struct perf_event_ops eops = { .sample = process_sample_event, - .comm = perf_event__process_comm, + .comm = event__process_comm, .ordered_samples = true, }; diff --git a/trunk/tools/perf/builtin-probe.c b/trunk/tools/perf/builtin-probe.c index 2c0e64d0b4aa..add163c9f0e7 100644 --- a/trunk/tools/perf/builtin-probe.c +++ b/trunk/tools/perf/builtin-probe.c @@ -36,7 +36,6 @@ #include "builtin.h" #include "util/util.h" #include "util/strlist.h" -#include "util/strfilter.h" #include "util/symbol.h" #include "util/debug.h" #include "util/debugfs.h" @@ -44,8 +43,6 @@ #include "util/probe-finder.h" #include "util/probe-event.h" -#define DEFAULT_VAR_FILTER "!__k???tab_* & !__crc_*" -#define DEFAULT_FUNC_FILTER "!_*" #define MAX_PATH_LEN 256 /* Session management structure */ @@ -55,7 +52,6 @@ static struct { bool show_lines; bool show_vars; bool show_ext_vars; - bool show_funcs; bool mod_events; int nevents; struct perf_probe_event events[MAX_PROBES]; @@ -63,7 +59,6 @@ static struct { struct line_range line_range; const char *target_module; int max_probe_points; - struct strfilter *filter; } params; /* Parse an event definition. Note that any error must die. */ @@ -162,27 +157,6 @@ static int opt_show_vars(const struct option *opt __used, } #endif -static int opt_set_filter(const struct option *opt __used, - const char *str, int unset __used) -{ - const char *err; - - if (str) { - pr_debug2("Set filter: %s\n", str); - if (params.filter) - strfilter__delete(params.filter); - params.filter = strfilter__new(str, &err); - if (!params.filter) { - pr_err("Filter parse error at %td.\n", err - str + 1); - pr_err("Source: \"%s\"\n", str); - pr_err(" %*c\n", (int)(err - str + 1), '^'); - return -EINVAL; - } - } - - return 0; -} - static const char * const probe_usage[] = { "perf probe [] 'PROBEDEF' ['PROBEDEF' ...]", "perf probe [] --add 'PROBEDEF' [--add 'PROBEDEF' ...]", @@ -247,13 +221,6 @@ static const struct option options[] = { OPT__DRY_RUN(&probe_event_dry_run), OPT_INTEGER('\0', "max-probes", ¶ms.max_probe_points, "Set how many probe points can be found for a probe."), - OPT_BOOLEAN('F', "funcs", ¶ms.show_funcs, - "Show potential probe-able functions."), - OPT_CALLBACK('\0', "filter", NULL, - "[!]FILTER", "Set a filter (with --vars/funcs only)\n" - "\t\t\t(default: \"" DEFAULT_VAR_FILTER "\" for --vars,\n" - "\t\t\t \"" DEFAULT_FUNC_FILTER "\" for --funcs)", - opt_set_filter), OPT_END() }; @@ -279,7 +246,7 @@ int cmd_probe(int argc, const char **argv, const char *prefix __used) params.max_probe_points = MAX_PROBES; if ((!params.nevents && !params.dellist && !params.list_events && - !params.show_lines && !params.show_funcs)) + !params.show_lines)) usage_with_options(probe_usage, options); /* @@ -300,41 +267,12 @@ int cmd_probe(int argc, const char **argv, const char *prefix __used) pr_err(" Error: Don't use --list with --vars.\n"); usage_with_options(probe_usage, options); } - if (params.show_funcs) { - pr_err(" Error: Don't use --list with --funcs.\n"); - usage_with_options(probe_usage, options); - } ret = show_perf_probe_events(); if (ret < 0) pr_err(" Error: Failed to show event list. (%d)\n", ret); return ret; } - if (params.show_funcs) { - if (params.nevents != 0 || params.dellist) { - pr_err(" Error: Don't use --funcs with" - " --add/--del.\n"); - usage_with_options(probe_usage, options); - } - if (params.show_lines) { - pr_err(" Error: Don't use --funcs with --line.\n"); - usage_with_options(probe_usage, options); - } - if (params.show_vars) { - pr_err(" Error: Don't use --funcs with --vars.\n"); - usage_with_options(probe_usage, options); - } - if (!params.filter) - params.filter = strfilter__new(DEFAULT_FUNC_FILTER, - NULL); - ret = show_available_funcs(params.target_module, - params.filter); - strfilter__delete(params.filter); - if (ret < 0) - pr_err(" Error: Failed to show functions." - " (%d)\n", ret); - return ret; - } #ifdef DWARF_SUPPORT if (params.show_lines) { @@ -359,16 +297,10 @@ int cmd_probe(int argc, const char **argv, const char *prefix __used) " --add/--del.\n"); usage_with_options(probe_usage, options); } - if (!params.filter) - params.filter = strfilter__new(DEFAULT_VAR_FILTER, - NULL); - ret = show_available_vars(params.events, params.nevents, params.max_probe_points, params.target_module, - params.filter, params.show_ext_vars); - strfilter__delete(params.filter); if (ret < 0) pr_err(" Error: Failed to show vars. (%d)\n", ret); return ret; diff --git a/trunk/tools/perf/builtin-record.c b/trunk/tools/perf/builtin-record.c index 12e0e41696d9..b2f729fdb317 100644 --- a/trunk/tools/perf/builtin-record.c +++ b/trunk/tools/perf/builtin-record.c @@ -18,20 +18,17 @@ #include "util/header.h" #include "util/event.h" -#include "util/evlist.h" #include "util/evsel.h" #include "util/debug.h" #include "util/session.h" #include "util/symbol.h" #include "util/cpumap.h" -#include "util/thread_map.h" #include #include #include #define FD(e, x, y) (*(int *)xyarray__entry(e->fd, x, y)) -#define SID(e, x, y) xyarray__entry(e->id, x, y) enum write_mode_t { WRITE_FORCE, @@ -42,13 +39,14 @@ static u64 user_interval = ULLONG_MAX; static u64 default_interval = 0; static u64 sample_type; +static struct cpu_map *cpus; static unsigned int page_size; static unsigned int mmap_pages = 128; static unsigned int user_freq = UINT_MAX; static int freq = 1000; static int output; static int pipe_output = 0; -static const char *output_name = NULL; +static const char *output_name = "perf.data"; static int group = 0; static int realtime_prio = 0; static bool nodelay = false; @@ -57,6 +55,7 @@ static bool sample_id_all_avail = true; static bool system_wide = false; static pid_t target_pid = -1; static pid_t target_tid = -1; +static struct thread_map *threads; static pid_t child_pid = -1; static bool no_inherit = false; static enum write_mode_t write_mode = WRITE_FORCE; @@ -67,17 +66,51 @@ static bool sample_address = false; static bool sample_time = false; static bool no_buildid = false; static bool no_buildid_cache = false; -static struct perf_evlist *evsel_list; static long samples = 0; static u64 bytes_written = 0; +static struct pollfd *event_array; + +static int nr_poll = 0; +static int nr_cpu = 0; + static int file_new = 1; static off_t post_processing_offset; static struct perf_session *session; static const char *cpu_list; +struct mmap_data { + void *base; + unsigned int mask; + unsigned int prev; +}; + +static struct mmap_data mmap_array[MAX_NR_CPUS]; + +static unsigned long mmap_read_head(struct mmap_data *md) +{ + struct perf_event_mmap_page *pc = md->base; + long head; + + head = pc->data_head; + rmb(); + + return head; +} + +static void mmap_write_tail(struct mmap_data *md, unsigned long tail) +{ + struct perf_event_mmap_page *pc = md->base; + + /* + * ensure all reads are done before we write the tail out. + */ + /* mb(); */ + pc->data_tail = tail; +} + static void advance_output(size_t size) { bytes_written += size; @@ -98,26 +131,42 @@ static void write_output(void *buf, size_t size) } } -static int process_synthesized_event(union perf_event *event, - struct perf_sample *sample __used, +static int process_synthesized_event(event_t *event, + struct sample_data *sample __used, struct perf_session *self __used) { write_output(event, event->header.size); return 0; } -static void mmap_read(struct perf_mmap *md) +static void mmap_read(struct mmap_data *md) { - unsigned int head = perf_mmap__read_head(md); + unsigned int head = mmap_read_head(md); unsigned int old = md->prev; unsigned char *data = md->base + page_size; unsigned long size; void *buf; + int diff; - if (old == head) - return; + /* + * If we're further behind than half the buffer, there's a chance + * the writer will bite our tail and mess up the samples under us. + * + * If we somehow ended up ahead of the head, we got messed up. + * + * In either case, truncate and restart at head. + */ + diff = head - old; + if (diff < 0) { + fprintf(stderr, "WARNING: failed to keep up with mmap data\n"); + /* + * head points to a known good entry, start there. + */ + old = head; + } - samples++; + if (old != head) + samples++; size = head - old; @@ -136,7 +185,7 @@ static void mmap_read(struct perf_mmap *md) write_output(buf, size); md->prev = old; - perf_mmap__write_tail(md, old); + mmap_write_tail(md, old); } static volatile int done = 0; @@ -160,6 +209,8 @@ static void sig_atexit(void) kill(getpid(), signr); } +static int group_fd; + static struct perf_header_attr *get_header_attr(struct perf_event_attr *a, int nr) { struct perf_header_attr *h_attr; @@ -183,47 +234,28 @@ static void create_counter(struct perf_evsel *evsel, int cpu) char *filter = evsel->filter; struct perf_event_attr *attr = &evsel->attr; struct perf_header_attr *h_attr; - struct perf_sample_id *sid; + int track = !evsel->idx; /* only the first counter needs these */ int thread_index; int ret; - - for (thread_index = 0; thread_index < evsel_list->threads->nr; thread_index++) { - h_attr = get_header_attr(attr, evsel->idx); - if (h_attr == NULL) - die("nomem\n"); - - if (!file_new) { - if (memcmp(&h_attr->attr, attr, sizeof(*attr))) { - fprintf(stderr, "incompatible append\n"); - exit(-1); - } - } - - sid = SID(evsel, cpu, thread_index); - if (perf_header_attr__add_id(h_attr, sid->id) < 0) { - pr_warning("Not enough memory to add id\n"); - exit(-1); - } - - if (filter != NULL) { - ret = ioctl(FD(evsel, cpu, thread_index), - PERF_EVENT_IOC_SET_FILTER, filter); - if (ret) { - error("failed to set filter with %d (%s)\n", errno, - strerror(errno)); - exit(-1); - } - } - } - - if (!sample_type) - sample_type = attr->sample_type; -} - -static void config_attr(struct perf_evsel *evsel, struct perf_evlist *evlist) -{ - struct perf_event_attr *attr = &evsel->attr; - int track = !evsel->idx; /* only the first counter needs these */ + struct { + u64 count; + u64 time_enabled; + u64 time_running; + u64 id; + } read_data; + /* + * Check if parse_single_tracepoint_event has already asked for + * PERF_SAMPLE_TIME. + * + * XXX this is kludgy but short term fix for problems introduced by + * eac23d1c that broke 'perf script' by having different sample_types + * when using multiple tracepoint events when we use a perf binary + * that tries to use sample_id_all on an older kernel. + * + * We need to move counter creation to perf_session, support + * different sample_types, etc. + */ + bool time_needed = attr->sample_type & PERF_SAMPLE_TIME; attr->read_format = PERF_FORMAT_TOTAL_TIME_ENABLED | PERF_FORMAT_TOTAL_TIME_RUNNING | @@ -231,7 +263,7 @@ static void config_attr(struct perf_evsel *evsel, struct perf_evlist *evlist) attr->sample_type |= PERF_SAMPLE_IP | PERF_SAMPLE_TID; - if (evlist->nr_entries > 1) + if (nr_counters > 1) attr->sample_type |= PERF_SAMPLE_ID; /* @@ -283,40 +315,19 @@ static void config_attr(struct perf_evsel *evsel, struct perf_evlist *evlist) attr->mmap = track; attr->comm = track; - + attr->inherit = !no_inherit; if (target_pid == -1 && target_tid == -1 && !system_wide) { attr->disabled = 1; attr->enable_on_exec = 1; } -} - -static void open_counters(struct perf_evlist *evlist) -{ - struct perf_evsel *pos; - int cpu; - - list_for_each_entry(pos, &evlist->entries, node) { - struct perf_event_attr *attr = &pos->attr; - /* - * Check if parse_single_tracepoint_event has already asked for - * PERF_SAMPLE_TIME. - * - * XXX this is kludgy but short term fix for problems introduced by - * eac23d1c that broke 'perf script' by having different sample_types - * when using multiple tracepoint events when we use a perf binary - * that tries to use sample_id_all on an older kernel. - * - * We need to move counter creation to perf_session, support - * different sample_types, etc. - */ - bool time_needed = attr->sample_type & PERF_SAMPLE_TIME; - - config_attr(pos, evlist); retry_sample_id: - attr->sample_id_all = sample_id_all_avail ? 1 : 0; + attr->sample_id_all = sample_id_all_avail ? 1 : 0; + + for (thread_index = 0; thread_index < threads->nr; thread_index++) { try_again: - if (perf_evsel__open(pos, evlist->cpus, evlist->threads, group, - !no_inherit) < 0) { + FD(evsel, nr_cpu, thread_index) = sys_perf_event_open(attr, threads->map[thread_index], cpu, group_fd, 0); + + if (FD(evsel, nr_cpu, thread_index) < 0) { int err = errno; if (err == EPERM || err == EACCES) @@ -353,7 +364,7 @@ static void open_counters(struct perf_evlist *evlist) } printf("\n"); error("sys_perf_event_open() syscall returned with %d (%s). /bin/dmesg may provide additional information.\n", - err, strerror(err)); + FD(evsel, nr_cpu, thread_index), strerror(err)); #if defined(__i386__) || defined(__x86_64__) if (attr->type == PERF_TYPE_HARDWARE && err == EOPNOTSUPP) @@ -364,16 +375,90 @@ static void open_counters(struct perf_evlist *evlist) #endif die("No CONFIG_PERF_EVENTS=y kernel support configured?\n"); + exit(-1); } - } - if (perf_evlist__mmap(evlist, mmap_pages, false) < 0) - die("failed to mmap with %d (%s)\n", errno, strerror(errno)); + h_attr = get_header_attr(attr, evsel->idx); + if (h_attr == NULL) + die("nomem\n"); + + if (!file_new) { + if (memcmp(&h_attr->attr, attr, sizeof(*attr))) { + fprintf(stderr, "incompatible append\n"); + exit(-1); + } + } + + if (read(FD(evsel, nr_cpu, thread_index), &read_data, sizeof(read_data)) == -1) { + perror("Unable to read perf file descriptor"); + exit(-1); + } + + if (perf_header_attr__add_id(h_attr, read_data.id) < 0) { + pr_warning("Not enough memory to add id\n"); + exit(-1); + } + + assert(FD(evsel, nr_cpu, thread_index) >= 0); + fcntl(FD(evsel, nr_cpu, thread_index), F_SETFL, O_NONBLOCK); + + /* + * First counter acts as the group leader: + */ + if (group && group_fd == -1) + group_fd = FD(evsel, nr_cpu, thread_index); + + if (evsel->idx || thread_index) { + struct perf_evsel *first; + first = list_entry(evsel_list.next, struct perf_evsel, node); + ret = ioctl(FD(evsel, nr_cpu, thread_index), + PERF_EVENT_IOC_SET_OUTPUT, + FD(first, nr_cpu, 0)); + if (ret) { + error("failed to set output: %d (%s)\n", errno, + strerror(errno)); + exit(-1); + } + } else { + mmap_array[nr_cpu].prev = 0; + mmap_array[nr_cpu].mask = mmap_pages*page_size - 1; + mmap_array[nr_cpu].base = mmap(NULL, (mmap_pages+1)*page_size, + PROT_READ | PROT_WRITE, MAP_SHARED, FD(evsel, nr_cpu, thread_index), 0); + if (mmap_array[nr_cpu].base == MAP_FAILED) { + error("failed to mmap with %d (%s)\n", errno, strerror(errno)); + exit(-1); + } + + event_array[nr_poll].fd = FD(evsel, nr_cpu, thread_index); + event_array[nr_poll].events = POLLIN; + nr_poll++; + } - for (cpu = 0; cpu < evsel_list->cpus->nr; ++cpu) { - list_for_each_entry(pos, &evlist->entries, node) - create_counter(pos, cpu); + if (filter != NULL) { + ret = ioctl(FD(evsel, nr_cpu, thread_index), + PERF_EVENT_IOC_SET_FILTER, filter); + if (ret) { + error("failed to set filter with %d (%s)\n", errno, + strerror(errno)); + exit(-1); + } + } } + + if (!sample_type) + sample_type = attr->sample_type; +} + +static void open_counters(int cpu) +{ + struct perf_evsel *pos; + + group_fd = -1; + + list_for_each_entry(pos, &evsel_list, node) + create_counter(pos, cpu); + + nr_cpu++; } static int process_buildids(void) @@ -396,14 +481,14 @@ static void atexit_header(void) if (!no_buildid) process_buildids(); - perf_header__write(&session->header, evsel_list, output, true); + perf_header__write(&session->header, output, true); perf_session__delete(session); - perf_evlist__delete(evsel_list); + perf_evsel_list__delete(); symbol__exit(); } } -static void perf_event__synthesize_guest_os(struct machine *machine, void *data) +static void event__synthesize_guest_os(struct machine *machine, void *data) { int err; struct perf_session *psession = data; @@ -419,8 +504,8 @@ static void perf_event__synthesize_guest_os(struct machine *machine, void *data) *method is used to avoid symbol missing when the first addr is *in module instead of in guest kernel. */ - err = perf_event__synthesize_modules(process_synthesized_event, - psession, machine); + err = event__synthesize_modules(process_synthesized_event, + psession, machine); if (err < 0) pr_err("Couldn't record guest kernel [%d]'s reference" " relocation symbol.\n", machine->pid); @@ -429,12 +514,11 @@ static void perf_event__synthesize_guest_os(struct machine *machine, void *data) * We use _stext for guest kernel because guest kernel's /proc/kallsyms * have no _text sometimes. */ - err = perf_event__synthesize_kernel_mmap(process_synthesized_event, - psession, machine, "_text"); + err = event__synthesize_kernel_mmap(process_synthesized_event, + psession, machine, "_text"); if (err < 0) - err = perf_event__synthesize_kernel_mmap(process_synthesized_event, - psession, machine, - "_stext"); + err = event__synthesize_kernel_mmap(process_synthesized_event, + psession, machine, "_stext"); if (err < 0) pr_err("Couldn't record guest kernel [%d]'s reference" " relocation symbol.\n", machine->pid); @@ -449,9 +533,9 @@ static void mmap_read_all(void) { int i; - for (i = 0; i < evsel_list->cpus->nr; i++) { - if (evsel_list->mmap[i].base) - mmap_read(&evsel_list->mmap[i]); + for (i = 0; i < nr_cpu; i++) { + if (mmap_array[i].base) + mmap_read(&mmap_array[i]); } if (perf_header__has_feat(&session->header, HEADER_TRACE_INFO)) @@ -482,26 +566,18 @@ static int __cmd_record(int argc, const char **argv) exit(-1); } - if (!output_name) { - if (!fstat(STDOUT_FILENO, &st) && S_ISFIFO(st.st_mode)) - pipe_output = 1; - else - output_name = "perf.data"; - } - if (output_name) { - if (!strcmp(output_name, "-")) - pipe_output = 1; - else if (!stat(output_name, &st) && st.st_size) { - if (write_mode == WRITE_FORCE) { - char oldname[PATH_MAX]; - snprintf(oldname, sizeof(oldname), "%s.old", - output_name); - unlink(oldname); - rename(output_name, oldname); - } - } else if (write_mode == WRITE_APPEND) { - write_mode = WRITE_FORCE; + if (!strcmp(output_name, "-")) + pipe_output = 1; + else if (!stat(output_name, &st) && st.st_size) { + if (write_mode == WRITE_FORCE) { + char oldname[PATH_MAX]; + snprintf(oldname, sizeof(oldname), "%s.old", + output_name); + unlink(oldname); + rename(output_name, oldname); } + } else if (write_mode == WRITE_APPEND) { + write_mode = WRITE_FORCE; } flags = O_CREAT|O_RDWR; @@ -535,7 +611,7 @@ static int __cmd_record(int argc, const char **argv) goto out_delete_session; } - if (have_tracepoints(&evsel_list->entries)) + if (have_tracepoints(&evsel_list)) perf_header__set_feat(&session->header, HEADER_TRACE_INFO); /* @@ -583,7 +659,7 @@ static int __cmd_record(int argc, const char **argv) } if (!system_wide && target_tid == -1 && target_pid == -1) - evsel_list->threads->map[0] = child_pid; + threads->map[0] = child_pid; close(child_ready_pipe[1]); close(go_pipe[0]); @@ -597,7 +673,12 @@ static int __cmd_record(int argc, const char **argv) close(child_ready_pipe[0]); } - open_counters(evsel_list); + if (!system_wide && no_inherit && !cpu_list) { + open_counters(-1); + } else { + for (i = 0; i < cpus->nr; i++) + open_counters(cpus->map[i]); + } perf_session__set_sample_type(session, sample_type); @@ -606,8 +687,7 @@ static int __cmd_record(int argc, const char **argv) if (err < 0) return err; } else if (file_new) { - err = perf_header__write(&session->header, evsel_list, - output, false); + err = perf_header__write(&session->header, output, false); if (err < 0) return err; } @@ -617,22 +697,22 @@ static int __cmd_record(int argc, const char **argv) perf_session__set_sample_id_all(session, sample_id_all_avail); if (pipe_output) { - err = perf_event__synthesize_attrs(&session->header, - process_synthesized_event, - session); + err = event__synthesize_attrs(&session->header, + process_synthesized_event, + session); if (err < 0) { pr_err("Couldn't synthesize attrs.\n"); return err; } - err = perf_event__synthesize_event_types(process_synthesized_event, - session); + err = event__synthesize_event_types(process_synthesized_event, + session); if (err < 0) { pr_err("Couldn't synthesize event_types.\n"); return err; } - if (have_tracepoints(&evsel_list->entries)) { + if (have_tracepoints(&evsel_list)) { /* * FIXME err <= 0 here actually means that * there were no tracepoints so its not really @@ -641,9 +721,9 @@ static int __cmd_record(int argc, const char **argv) * return this more properly and also * propagate errors that now are calling die() */ - err = perf_event__synthesize_tracing_data(output, evsel_list, - process_synthesized_event, - session); + err = event__synthesize_tracing_data(output, &evsel_list, + process_synthesized_event, + session); if (err <= 0) { pr_err("Couldn't record tracing data.\n"); return err; @@ -658,34 +738,31 @@ static int __cmd_record(int argc, const char **argv) return -1; } - err = perf_event__synthesize_kernel_mmap(process_synthesized_event, - session, machine, "_text"); + err = event__synthesize_kernel_mmap(process_synthesized_event, + session, machine, "_text"); if (err < 0) - err = perf_event__synthesize_kernel_mmap(process_synthesized_event, - session, machine, "_stext"); + err = event__synthesize_kernel_mmap(process_synthesized_event, + session, machine, "_stext"); if (err < 0) pr_err("Couldn't record kernel reference relocation symbol\n" "Symbol resolution may be skewed if relocation was used (e.g. kexec).\n" "Check /proc/kallsyms permission or run as root.\n"); - err = perf_event__synthesize_modules(process_synthesized_event, - session, machine); + err = event__synthesize_modules(process_synthesized_event, + session, machine); if (err < 0) pr_err("Couldn't record kernel module information.\n" "Symbol resolution may be skewed if relocation was used (e.g. kexec).\n" "Check /proc/modules permission or run as root.\n"); if (perf_guest) - perf_session__process_machines(session, - perf_event__synthesize_guest_os); + perf_session__process_machines(session, event__synthesize_guest_os); if (!system_wide) - perf_event__synthesize_thread_map(evsel_list->threads, - process_synthesized_event, - session); + event__synthesize_thread(target_tid, process_synthesized_event, + session); else - perf_event__synthesize_threads(process_synthesized_event, - session); + event__synthesize_threads(process_synthesized_event, session); if (realtime_prio) { struct sched_param param; @@ -712,17 +789,17 @@ static int __cmd_record(int argc, const char **argv) if (hits == samples) { if (done) break; - err = poll(evsel_list->pollfd, evsel_list->nr_fds, -1); + err = poll(event_array, nr_poll, -1); waking++; } if (done) { - for (i = 0; i < evsel_list->cpus->nr; i++) { + for (i = 0; i < nr_cpu; i++) { struct perf_evsel *pos; - list_for_each_entry(pos, &evsel_list->entries, node) { + list_for_each_entry(pos, &evsel_list, node) { for (thread = 0; - thread < evsel_list->threads->nr; + thread < threads->nr; thread++) ioctl(FD(pos, i, thread), PERF_EVENT_IOC_DISABLE); @@ -761,10 +838,10 @@ static const char * const record_usage[] = { static bool force, append_file; const struct option record_options[] = { - OPT_CALLBACK('e', "event", &evsel_list, "event", + OPT_CALLBACK('e', "event", NULL, "event", "event selector. use 'perf list' to list available events", parse_events), - OPT_CALLBACK(0, "filter", &evsel_list, "filter", + OPT_CALLBACK(0, "filter", NULL, "filter", "event filter", parse_filter), OPT_INTEGER('p', "pid", &target_pid, "record events on existing process id"), @@ -815,10 +892,6 @@ int cmd_record(int argc, const char **argv, const char *prefix __used) int err = -ENOMEM; struct perf_evsel *pos; - evsel_list = perf_evlist__new(NULL, NULL); - if (evsel_list == NULL) - return -ENOMEM; - argc = parse_options(argc, argv, record_options, record_usage, PARSE_OPT_STOP_AT_NON_OPTION); if (!argc && target_pid == -1 && target_tid == -1 && @@ -840,8 +913,7 @@ int cmd_record(int argc, const char **argv, const char *prefix __used) if (no_buildid_cache || no_buildid) disable_buildid_cache(); - if (evsel_list->nr_entries == 0 && - perf_evlist__add_default(evsel_list) < 0) { + if (list_empty(&evsel_list) && perf_evsel_list__create_default() < 0) { pr_err("Not enough memory for event selector list\n"); goto out_symbol_exit; } @@ -849,19 +921,27 @@ int cmd_record(int argc, const char **argv, const char *prefix __used) if (target_pid != -1) target_tid = target_pid; - if (perf_evlist__create_maps(evsel_list, target_pid, - target_tid, cpu_list) < 0) + threads = thread_map__new(target_pid, target_tid); + if (threads == NULL) { + pr_err("Problems finding threads of monitor\n"); usage_with_options(record_usage, record_options); + } + + cpus = cpu_map__new(cpu_list); + if (cpus == NULL) { + perror("failed to parse CPUs map"); + return -1; + } - list_for_each_entry(pos, &evsel_list->entries, node) { - if (perf_evsel__alloc_fd(pos, evsel_list->cpus->nr, - evsel_list->threads->nr) < 0) + list_for_each_entry(pos, &evsel_list, node) { + if (perf_evsel__alloc_fd(pos, cpus->nr, threads->nr) < 0) goto out_free_fd; if (perf_header__push_event(pos->attr.config, event_name(pos))) goto out_free_fd; } - - if (perf_evlist__alloc_pollfd(evsel_list) < 0) + event_array = malloc((sizeof(struct pollfd) * MAX_NR_CPUS * + MAX_COUNTERS * threads->nr)); + if (!event_array) goto out_free_fd; if (user_interval != ULLONG_MAX) @@ -879,12 +959,16 @@ int cmd_record(int argc, const char **argv, const char *prefix __used) } else { fprintf(stderr, "frequency and count are zero, aborting\n"); err = -EINVAL; - goto out_free_fd; + goto out_free_event_array; } err = __cmd_record(argc, argv); + +out_free_event_array: + free(event_array); out_free_fd: - perf_evlist__delete_maps(evsel_list); + thread_map__delete(threads); + threads = NULL; out_symbol_exit: symbol__exit(); return err; diff --git a/trunk/tools/perf/builtin-report.c b/trunk/tools/perf/builtin-report.c index f9a99a1ce609..c27e31f289e6 100644 --- a/trunk/tools/perf/builtin-report.c +++ b/trunk/tools/perf/builtin-report.c @@ -9,7 +9,6 @@ #include "util/util.h" -#include "util/annotate.h" #include "util/color.h" #include #include "util/cache.h" @@ -44,7 +43,6 @@ static const char default_pretty_printing_style[] = "normal"; static const char *pretty_printing_style = default_pretty_printing_style; static char callchain_default_opt[] = "fractal,0.5"; -static symbol_filter_t annotate_init; static struct hists *perf_session__hists_findnew(struct perf_session *self, u64 event_stream, u32 type, @@ -79,96 +77,86 @@ static struct hists *perf_session__hists_findnew(struct perf_session *self, return new; } -static int perf_session__add_hist_entry(struct perf_session *session, +static int perf_session__add_hist_entry(struct perf_session *self, struct addr_location *al, - struct perf_sample *sample) + struct sample_data *data) { + struct map_symbol *syms = NULL; struct symbol *parent = NULL; - int err = 0; + int err = -ENOMEM; struct hist_entry *he; struct hists *hists; struct perf_event_attr *attr; - if ((sort__has_parent || symbol_conf.use_callchain) && sample->callchain) { - err = perf_session__resolve_callchain(session, al->thread, - sample->callchain, &parent); - if (err) - return err; + if ((sort__has_parent || symbol_conf.use_callchain) && data->callchain) { + syms = perf_session__resolve_callchain(self, al->thread, + data->callchain, &parent); + if (syms == NULL) + return -ENOMEM; } - attr = perf_header__find_attr(sample->id, &session->header); + attr = perf_header__find_attr(data->id, &self->header); if (attr) - hists = perf_session__hists_findnew(session, sample->id, attr->type, attr->config); + hists = perf_session__hists_findnew(self, data->id, attr->type, attr->config); else - hists = perf_session__hists_findnew(session, sample->id, 0, 0); + hists = perf_session__hists_findnew(self, data->id, 0, 0); if (hists == NULL) - return -ENOMEM; - - he = __hists__add_entry(hists, al, parent, sample->period); + goto out_free_syms; + he = __hists__add_entry(hists, al, parent, data->period); if (he == NULL) - return -ENOMEM; - + goto out_free_syms; + err = 0; if (symbol_conf.use_callchain) { - err = callchain_append(he->callchain, &session->callchain_cursor, - sample->period); + err = callchain_append(he->callchain, data->callchain, syms, + data->period); if (err) - return err; + goto out_free_syms; } /* * Only in the newt browser we are doing integrated annotation, * so we don't allocated the extra space needed because the stdio * code will not use it. */ - if (al->sym != NULL && use_browser > 0) { - /* - * All aggregated on the first sym_hist. - */ - struct annotation *notes = symbol__annotation(he->ms.sym); - if (notes->src == NULL && - symbol__alloc_hist(he->ms.sym, 1) < 0) - err = -ENOMEM; - else - err = hist_entry__inc_addr_samples(he, 0, al->addr); - } - + if (use_browser > 0) + err = hist_entry__inc_addr_samples(he, al->addr); +out_free_syms: + free(syms); return err; } static int add_event_total(struct perf_session *session, - struct perf_sample *sample, + struct sample_data *data, struct perf_event_attr *attr) { struct hists *hists; if (attr) - hists = perf_session__hists_findnew(session, sample->id, + hists = perf_session__hists_findnew(session, data->id, attr->type, attr->config); else - hists = perf_session__hists_findnew(session, sample->id, 0, 0); + hists = perf_session__hists_findnew(session, data->id, 0, 0); if (!hists) return -ENOMEM; - hists->stats.total_period += sample->period; + hists->stats.total_period += data->period; /* * FIXME: add_event_total should be moved from here to * perf_session__process_event so that the proper hist is passed to * the event_op methods. */ hists__inc_nr_events(hists, PERF_RECORD_SAMPLE); - session->hists.stats.total_period += sample->period; + session->hists.stats.total_period += data->period; return 0; } -static int process_sample_event(union perf_event *event, - struct perf_sample *sample, +static int process_sample_event(event_t *event, struct sample_data *sample, struct perf_session *session) { struct addr_location al; struct perf_event_attr *attr; - if (perf_event__preprocess_sample(event, session, &al, sample, - annotate_init) < 0) { + if (event__preprocess_sample(event, session, &al, sample, NULL) < 0) { fprintf(stderr, "problem processing %d event, skipping it.\n", event->header.type); return -1; @@ -192,8 +180,7 @@ static int process_sample_event(union perf_event *event, return 0; } -static int process_read_event(union perf_event *event, - struct perf_sample *sample __used, +static int process_read_event(event_t *event, struct sample_data *sample __used, struct perf_session *session __used) { struct perf_event_attr *attr; @@ -235,7 +222,7 @@ static int perf_session__setup_sample_type(struct perf_session *self) } else if (!dont_use_callchains && callchain_param.mode != CHAIN_NONE && !symbol_conf.use_callchain) { symbol_conf.use_callchain = true; - if (callchain_register_param(&callchain_param) < 0) { + if (register_callchain_param(&callchain_param) < 0) { fprintf(stderr, "Can't register callchain" " params\n"); return -EINVAL; @@ -246,17 +233,17 @@ static int perf_session__setup_sample_type(struct perf_session *self) } static struct perf_event_ops event_ops = { - .sample = process_sample_event, - .mmap = perf_event__process_mmap, - .comm = perf_event__process_comm, - .exit = perf_event__process_task, - .fork = perf_event__process_task, - .lost = perf_event__process_lost, - .read = process_read_event, - .attr = perf_event__process_attr, - .event_type = perf_event__process_event_type, - .tracing_data = perf_event__process_tracing_data, - .build_id = perf_event__process_build_id, + .sample = process_sample_event, + .mmap = event__process_mmap, + .comm = event__process_comm, + .exit = event__process_task, + .fork = event__process_task, + .lost = event__process_lost, + .read = process_read_event, + .attr = event__process_attr, + .event_type = event__process_event_type, + .tracing_data = event__process_tracing_data, + .build_id = event__process_build_id, .ordered_samples = true, .ordering_requires_timestamps = true, }; @@ -360,7 +347,7 @@ static int __cmd_report(void) } if (use_browser > 0) - hists__tui_browse_tree(&session->hists_tree, help, 0); + hists__tui_browse_tree(&session->hists_tree, help); else hists__tty_browse_tree(&session->hists_tree, help); @@ -437,7 +424,7 @@ parse_callchain_opt(const struct option *opt __used, const char *arg, if (tok2) callchain_param.print_limit = strtod(tok2, &endptr); setup: - if (callchain_register_param(&callchain_param) < 0) { + if (register_callchain_param(&callchain_param) < 0) { fprintf(stderr, "Can't register callchain params\n"); return -1; } @@ -511,7 +498,7 @@ int cmd_report(int argc, const char **argv, const char *prefix __used) use_browser = 1; if (strcmp(input_name, "-") != 0) - setup_browser(true); + setup_browser(); else use_browser = 0; /* @@ -520,8 +507,7 @@ int cmd_report(int argc, const char **argv, const char *prefix __used) * implementation. */ if (use_browser > 0) { - symbol_conf.priv_size = sizeof(struct annotation); - annotate_init = symbol__annotate_init; + symbol_conf.priv_size = sizeof(struct sym_priv); /* * For searching by name on the "Browse map details". * providing it only in verbose mode not to bloat too diff --git a/trunk/tools/perf/builtin-sched.c b/trunk/tools/perf/builtin-sched.c index a32f411faeac..29acb894e035 100644 --- a/trunk/tools/perf/builtin-sched.c +++ b/trunk/tools/perf/builtin-sched.c @@ -369,6 +369,11 @@ static void process_sched_event(struct task_desc *this_task __used, struct sched_atom *atom) { int ret = 0; + u64 now; + long long delta; + + now = get_nsecs(); + delta = start_time + atom->timestamp - now; switch (atom->type) { case SCHED_EVENT_RUN: @@ -557,7 +562,7 @@ static void wait_for_tasks(void) static void run_one_test(void) { - u64 T0, T1, delta, avg_delta, fluct; + u64 T0, T1, delta, avg_delta, fluct, std_dev; T0 = get_nsecs(); wait_for_tasks(); @@ -573,6 +578,7 @@ static void run_one_test(void) else fluct = delta - avg_delta; sum_fluct += fluct; + std_dev = sum_fluct / nr_runs / sqrt(nr_runs); if (!run_avg) run_avg = delta; run_avg = (run_avg*9 + delta)/10; @@ -793,7 +799,7 @@ replay_switch_event(struct trace_switch_event *switch_event, u64 timestamp, struct thread *thread __used) { - struct task_desc *prev, __used *next; + struct task_desc *prev, *next; u64 timestamp0; s64 delta; @@ -1398,7 +1404,7 @@ map_switch_event(struct trace_switch_event *switch_event, u64 timestamp, struct thread *thread __used) { - struct thread *sched_out __used, *sched_in; + struct thread *sched_out, *sched_in; int new_shortname; u64 timestamp0; s64 delta; @@ -1574,9 +1580,9 @@ process_sched_migrate_task_event(void *data, struct perf_session *session, event, cpu, timestamp, thread); } -static void process_raw_event(union perf_event *raw_event __used, - struct perf_session *session, void *data, int cpu, - u64 timestamp, struct thread *thread) +static void +process_raw_event(event_t *raw_event __used, struct perf_session *session, + void *data, int cpu, u64 timestamp, struct thread *thread) { struct event *event; int type; @@ -1601,8 +1607,7 @@ static void process_raw_event(union perf_event *raw_event __used, process_sched_migrate_task_event(data, session, event, cpu, timestamp, thread); } -static int process_sample_event(union perf_event *event, - struct perf_sample *sample, +static int process_sample_event(event_t *event, struct sample_data *sample, struct perf_session *session) { struct thread *thread; @@ -1630,9 +1635,9 @@ static int process_sample_event(union perf_event *event, static struct perf_event_ops event_ops = { .sample = process_sample_event, - .comm = perf_event__process_comm, - .lost = perf_event__process_lost, - .fork = perf_event__process_task, + .comm = event__process_comm, + .lost = event__process_lost, + .fork = event__process_task, .ordered_samples = true, }; diff --git a/trunk/tools/perf/builtin-script.c b/trunk/tools/perf/builtin-script.c index 5f40df635dcb..b766c2a9ac97 100644 --- a/trunk/tools/perf/builtin-script.c +++ b/trunk/tools/perf/builtin-script.c @@ -63,8 +63,7 @@ static int cleanup_scripting(void) static char const *input_name = "perf.data"; -static int process_sample_event(union perf_event *event, - struct perf_sample *sample, +static int process_sample_event(event_t *event, struct sample_data *sample, struct perf_session *session) { struct thread *thread = perf_session__findnew(session, event->ip.pid); @@ -101,14 +100,14 @@ static int process_sample_event(union perf_event *event, } static struct perf_event_ops event_ops = { - .sample = process_sample_event, - .comm = perf_event__process_comm, - .attr = perf_event__process_attr, - .event_type = perf_event__process_event_type, - .tracing_data = perf_event__process_tracing_data, - .build_id = perf_event__process_build_id, - .ordered_samples = true, + .sample = process_sample_event, + .comm = event__process_comm, + .attr = event__process_attr, + .event_type = event__process_event_type, + .tracing_data = event__process_tracing_data, + .build_id = event__process_build_id, .ordering_requires_timestamps = true, + .ordered_samples = true, }; extern volatile int session_done; diff --git a/trunk/tools/perf/builtin-stat.c b/trunk/tools/perf/builtin-stat.c index 806a9998fcd5..a482a191a0ca 100644 --- a/trunk/tools/perf/builtin-stat.c +++ b/trunk/tools/perf/builtin-stat.c @@ -43,13 +43,11 @@ #include "util/parse-options.h" #include "util/parse-events.h" #include "util/event.h" -#include "util/evlist.h" #include "util/evsel.h" #include "util/debug.h" #include "util/header.h" #include "util/cpumap.h" #include "util/thread.h" -#include "util/thread_map.h" #include #include @@ -73,9 +71,8 @@ static struct perf_event_attr default_attrs[] = { }; -struct perf_evlist *evsel_list; - static bool system_wide = false; +static struct cpu_map *cpus; static int run_idx = 0; static int run_count = 1; @@ -84,6 +81,7 @@ static bool scale = true; static bool no_aggr = false; static pid_t target_pid = -1; static pid_t target_tid = -1; +static struct thread_map *threads; static pid_t child_pid = -1; static bool null_run = false; static bool big_num = true; @@ -168,7 +166,7 @@ static int create_perf_stat_counter(struct perf_evsel *evsel) PERF_FORMAT_TOTAL_TIME_RUNNING; if (system_wide) - return perf_evsel__open_per_cpu(evsel, evsel_list->cpus, false, false); + return perf_evsel__open_per_cpu(evsel, cpus); attr->inherit = !no_inherit; if (target_pid == -1 && target_tid == -1) { @@ -176,7 +174,7 @@ static int create_perf_stat_counter(struct perf_evsel *evsel) attr->enable_on_exec = 1; } - return perf_evsel__open_per_thread(evsel, evsel_list->threads, false, false); + return perf_evsel__open_per_thread(evsel, threads); } /* @@ -201,8 +199,7 @@ static int read_counter_aggr(struct perf_evsel *counter) u64 *count = counter->counts->aggr.values; int i; - if (__perf_evsel__read(counter, evsel_list->cpus->nr, - evsel_list->threads->nr, scale) < 0) + if (__perf_evsel__read(counter, cpus->nr, threads->nr, scale) < 0) return -1; for (i = 0; i < 3; i++) @@ -235,7 +232,7 @@ static int read_counter(struct perf_evsel *counter) u64 *count; int cpu; - for (cpu = 0; cpu < evsel_list->cpus->nr; cpu++) { + for (cpu = 0; cpu < cpus->nr; cpu++) { if (__perf_evsel__read_on_cpu(counter, cpu, 0, scale) < 0) return -1; @@ -300,7 +297,7 @@ static int run_perf_stat(int argc __used, const char **argv) } if (target_tid == -1 && target_pid == -1 && !system_wide) - evsel_list->threads->map[0] = child_pid; + threads->map[0] = child_pid; /* * Wait for the child to be ready to exec. @@ -312,7 +309,7 @@ static int run_perf_stat(int argc __used, const char **argv) close(child_ready_pipe[0]); } - list_for_each_entry(counter, &evsel_list->entries, node) { + list_for_each_entry(counter, &evsel_list, node) { if (create_perf_stat_counter(counter) < 0) { if (errno == -EPERM || errno == -EACCES) { error("You may not have permission to collect %sstats.\n" @@ -350,15 +347,14 @@ static int run_perf_stat(int argc __used, const char **argv) update_stats(&walltime_nsecs_stats, t1 - t0); if (no_aggr) { - list_for_each_entry(counter, &evsel_list->entries, node) { + list_for_each_entry(counter, &evsel_list, node) { read_counter(counter); - perf_evsel__close_fd(counter, evsel_list->cpus->nr, 1); + perf_evsel__close_fd(counter, cpus->nr, 1); } } else { - list_for_each_entry(counter, &evsel_list->entries, node) { + list_for_each_entry(counter, &evsel_list, node) { read_counter_aggr(counter); - perf_evsel__close_fd(counter, evsel_list->cpus->nr, - evsel_list->threads->nr); + perf_evsel__close_fd(counter, cpus->nr, threads->nr); } } @@ -386,7 +382,7 @@ static void nsec_printout(int cpu, struct perf_evsel *evsel, double avg) if (no_aggr) sprintf(cpustr, "CPU%*d%s", csv_output ? 0 : -4, - evsel_list->cpus->map[cpu], csv_sep); + cpus->map[cpu], csv_sep); fprintf(stderr, fmt, cpustr, msecs, csv_sep, event_name(evsel)); @@ -414,7 +410,7 @@ static void abs_printout(int cpu, struct perf_evsel *evsel, double avg) if (no_aggr) sprintf(cpustr, "CPU%*d%s", csv_output ? 0 : -4, - evsel_list->cpus->map[cpu], csv_sep); + cpus->map[cpu], csv_sep); else cpu = 0; @@ -500,14 +496,14 @@ static void print_counter(struct perf_evsel *counter) u64 ena, run, val; int cpu; - for (cpu = 0; cpu < evsel_list->cpus->nr; cpu++) { + for (cpu = 0; cpu < cpus->nr; cpu++) { val = counter->counts->cpu[cpu].val; ena = counter->counts->cpu[cpu].ena; run = counter->counts->cpu[cpu].run; if (run == 0 || ena == 0) { fprintf(stderr, "CPU%*d%s%*s%s%-24s", csv_output ? 0 : -4, - evsel_list->cpus->map[cpu], csv_sep, + cpus->map[cpu], csv_sep, csv_output ? 0 : 18, "", csv_sep, event_name(counter)); @@ -559,10 +555,10 @@ static void print_stat(int argc, const char **argv) } if (no_aggr) { - list_for_each_entry(counter, &evsel_list->entries, node) + list_for_each_entry(counter, &evsel_list, node) print_counter(counter); } else { - list_for_each_entry(counter, &evsel_list->entries, node) + list_for_each_entry(counter, &evsel_list, node) print_counter_aggr(counter); } @@ -614,7 +610,7 @@ static int stat__set_big_num(const struct option *opt __used, } static const struct option options[] = { - OPT_CALLBACK('e', "event", &evsel_list, "event", + OPT_CALLBACK('e', "event", NULL, "event", "event selector. use 'perf list' to list available events", parse_events), OPT_BOOLEAN('i', "no-inherit", &no_inherit, @@ -652,10 +648,6 @@ int cmd_stat(int argc, const char **argv, const char *prefix __used) setlocale(LC_ALL, ""); - evsel_list = perf_evlist__new(NULL, NULL); - if (evsel_list == NULL) - return -ENOMEM; - argc = parse_options(argc, argv, options, stat_usage, PARSE_OPT_STOP_AT_NON_OPTION); @@ -687,41 +679,44 @@ int cmd_stat(int argc, const char **argv, const char *prefix __used) usage_with_options(stat_usage, options); /* Set attrs and nr_counters if no event is selected and !null_run */ - if (!null_run && !evsel_list->nr_entries) { + if (!null_run && !nr_counters) { size_t c; + nr_counters = ARRAY_SIZE(default_attrs); + for (c = 0; c < ARRAY_SIZE(default_attrs); ++c) { - pos = perf_evsel__new(&default_attrs[c], c); + pos = perf_evsel__new(&default_attrs[c], + nr_counters); if (pos == NULL) goto out; - perf_evlist__add(evsel_list, pos); + list_add(&pos->node, &evsel_list); } } if (target_pid != -1) target_tid = target_pid; - evsel_list->threads = thread_map__new(target_pid, target_tid); - if (evsel_list->threads == NULL) { + threads = thread_map__new(target_pid, target_tid); + if (threads == NULL) { pr_err("Problems finding threads of monitor\n"); usage_with_options(stat_usage, options); } if (system_wide) - evsel_list->cpus = cpu_map__new(cpu_list); + cpus = cpu_map__new(cpu_list); else - evsel_list->cpus = cpu_map__dummy_new(); + cpus = cpu_map__dummy_new(); - if (evsel_list->cpus == NULL) { + if (cpus == NULL) { perror("failed to parse CPUs map"); usage_with_options(stat_usage, options); return -1; } - list_for_each_entry(pos, &evsel_list->entries, node) { + list_for_each_entry(pos, &evsel_list, node) { if (perf_evsel__alloc_stat_priv(pos) < 0 || - perf_evsel__alloc_counts(pos, evsel_list->cpus->nr) < 0 || - perf_evsel__alloc_fd(pos, evsel_list->cpus->nr, evsel_list->threads->nr) < 0) + perf_evsel__alloc_counts(pos, cpus->nr) < 0 || + perf_evsel__alloc_fd(pos, cpus->nr, threads->nr) < 0) goto out_free_fd; } @@ -746,10 +741,11 @@ int cmd_stat(int argc, const char **argv, const char *prefix __used) if (status != -1) print_stat(argc, argv); out_free_fd: - list_for_each_entry(pos, &evsel_list->entries, node) + list_for_each_entry(pos, &evsel_list, node) perf_evsel__free_stat_priv(pos); - perf_evlist__delete_maps(evsel_list); + perf_evsel_list__delete(); out: - perf_evlist__delete(evsel_list); + thread_map__delete(threads); + threads = NULL; return status; } diff --git a/trunk/tools/perf/builtin-test.c b/trunk/tools/perf/builtin-test.c index 1b2106c58f66..5dcdba653d70 100644 --- a/trunk/tools/perf/builtin-test.c +++ b/trunk/tools/perf/builtin-test.c @@ -7,11 +7,10 @@ #include "util/cache.h" #include "util/debug.h" -#include "util/evlist.h" #include "util/parse-options.h" -#include "util/parse-events.h" +#include "util/session.h" #include "util/symbol.h" -#include "util/thread_map.h" +#include "util/thread.h" static long page_size; @@ -239,14 +238,14 @@ static int test__vmlinux_matches_kallsyms(void) #include "util/evsel.h" #include -static int trace_event__id(const char *evname) +static int trace_event__id(const char *event_name) { char *filename; int err = -1, fd; if (asprintf(&filename, "/sys/kernel/debug/tracing/events/syscalls/%s/id", - evname) < 0) + event_name) < 0) return -1; fd = open(filename, O_RDONLY); @@ -290,7 +289,7 @@ static int test__open_syscall_event(void) goto out_thread_map_delete; } - if (perf_evsel__open_per_thread(evsel, threads, false, false) < 0) { + if (perf_evsel__open_per_thread(evsel, threads) < 0) { pr_debug("failed to open counter: %s, " "tweak /proc/sys/kernel/perf_event_paranoid?\n", strerror(errno)); @@ -348,9 +347,9 @@ static int test__open_syscall_event_on_all_cpus(void) } cpus = cpu_map__new(NULL); - if (cpus == NULL) { - pr_debug("cpu_map__new\n"); - goto out_thread_map_delete; + if (threads == NULL) { + pr_debug("thread_map__new\n"); + return -1; } @@ -365,7 +364,7 @@ static int test__open_syscall_event_on_all_cpus(void) goto out_thread_map_delete; } - if (perf_evsel__open(evsel, cpus, threads, false, false) < 0) { + if (perf_evsel__open(evsel, cpus, threads) < 0) { pr_debug("failed to open counter: %s, " "tweak /proc/sys/kernel/perf_event_paranoid?\n", strerror(errno)); @@ -409,8 +408,6 @@ static int test__open_syscall_event_on_all_cpus(void) goto out_close_fd; } - err = 0; - for (cpu = 0; cpu < cpus->nr; ++cpu) { unsigned int expected; @@ -419,18 +416,18 @@ static int test__open_syscall_event_on_all_cpus(void) if (perf_evsel__read_on_cpu(evsel, cpu, 0) < 0) { pr_debug("perf_evsel__open_read_on_cpu\n"); - err = -1; - break; + goto out_close_fd; } expected = nr_open_calls + cpu; if (evsel->counts->cpu[cpu].val != expected) { pr_debug("perf_evsel__read_on_cpu: expected to intercept %d calls on cpu %d, got %" PRIu64 "\n", expected, cpus->map[cpu], evsel->counts->cpu[cpu].val); - err = -1; + goto out_close_fd; } } + err = 0; out_close_fd: perf_evsel__close_fd(evsel, 1, threads->nr); out_evsel_delete: @@ -440,159 +437,6 @@ static int test__open_syscall_event_on_all_cpus(void) return err; } -/* - * This test will generate random numbers of calls to some getpid syscalls, - * then establish an mmap for a group of events that are created to monitor - * the syscalls. - * - * It will receive the events, using mmap, use its PERF_SAMPLE_ID generated - * sample.id field to map back to its respective perf_evsel instance. - * - * Then it checks if the number of syscalls reported as perf events by - * the kernel corresponds to the number of syscalls made. - */ -static int test__basic_mmap(void) -{ - int err = -1; - union perf_event *event; - struct thread_map *threads; - struct cpu_map *cpus; - struct perf_evlist *evlist; - struct perf_event_attr attr = { - .type = PERF_TYPE_TRACEPOINT, - .read_format = PERF_FORMAT_ID, - .sample_type = PERF_SAMPLE_ID, - .watermark = 0, - }; - cpu_set_t cpu_set; - const char *syscall_names[] = { "getsid", "getppid", "getpgrp", - "getpgid", }; - pid_t (*syscalls[])(void) = { (void *)getsid, getppid, getpgrp, - (void*)getpgid }; -#define nsyscalls ARRAY_SIZE(syscall_names) - int ids[nsyscalls]; - unsigned int nr_events[nsyscalls], - expected_nr_events[nsyscalls], i, j; - struct perf_evsel *evsels[nsyscalls], *evsel; - - for (i = 0; i < nsyscalls; ++i) { - char name[64]; - - snprintf(name, sizeof(name), "sys_enter_%s", syscall_names[i]); - ids[i] = trace_event__id(name); - if (ids[i] < 0) { - pr_debug("Is debugfs mounted on /sys/kernel/debug?\n"); - return -1; - } - nr_events[i] = 0; - expected_nr_events[i] = random() % 257; - } - - threads = thread_map__new(-1, getpid()); - if (threads == NULL) { - pr_debug("thread_map__new\n"); - return -1; - } - - cpus = cpu_map__new(NULL); - if (cpus == NULL) { - pr_debug("cpu_map__new\n"); - goto out_free_threads; - } - - CPU_ZERO(&cpu_set); - CPU_SET(cpus->map[0], &cpu_set); - sched_setaffinity(0, sizeof(cpu_set), &cpu_set); - if (sched_setaffinity(0, sizeof(cpu_set), &cpu_set) < 0) { - pr_debug("sched_setaffinity() failed on CPU %d: %s ", - cpus->map[0], strerror(errno)); - goto out_free_cpus; - } - - evlist = perf_evlist__new(cpus, threads); - if (evlist == NULL) { - pr_debug("perf_evlist__new\n"); - goto out_free_cpus; - } - - /* anonymous union fields, can't be initialized above */ - attr.wakeup_events = 1; - attr.sample_period = 1; - - for (i = 0; i < nsyscalls; ++i) { - attr.config = ids[i]; - evsels[i] = perf_evsel__new(&attr, i); - if (evsels[i] == NULL) { - pr_debug("perf_evsel__new\n"); - goto out_free_evlist; - } - - perf_evlist__add(evlist, evsels[i]); - - if (perf_evsel__open(evsels[i], cpus, threads, false, false) < 0) { - pr_debug("failed to open counter: %s, " - "tweak /proc/sys/kernel/perf_event_paranoid?\n", - strerror(errno)); - goto out_close_fd; - } - } - - if (perf_evlist__mmap(evlist, 128, true) < 0) { - pr_debug("failed to mmap events: %d (%s)\n", errno, - strerror(errno)); - goto out_close_fd; - } - - for (i = 0; i < nsyscalls; ++i) - for (j = 0; j < expected_nr_events[i]; ++j) { - int foo = syscalls[i](); - ++foo; - } - - while ((event = perf_evlist__read_on_cpu(evlist, 0)) != NULL) { - struct perf_sample sample; - - if (event->header.type != PERF_RECORD_SAMPLE) { - pr_debug("unexpected %s event\n", - perf_event__name(event->header.type)); - goto out_munmap; - } - - perf_event__parse_sample(event, attr.sample_type, false, &sample); - evsel = perf_evlist__id2evsel(evlist, sample.id); - if (evsel == NULL) { - pr_debug("event with id %" PRIu64 - " doesn't map to an evsel\n", sample.id); - goto out_munmap; - } - nr_events[evsel->idx]++; - } - - list_for_each_entry(evsel, &evlist->entries, node) { - if (nr_events[evsel->idx] != expected_nr_events[evsel->idx]) { - pr_debug("expected %d %s events, got %d\n", - expected_nr_events[evsel->idx], - event_name(evsel), nr_events[evsel->idx]); - goto out_munmap; - } - } - - err = 0; -out_munmap: - perf_evlist__munmap(evlist); -out_close_fd: - for (i = 0; i < nsyscalls; ++i) - perf_evsel__close_fd(evsels[i], 1, threads->nr); -out_free_evlist: - perf_evlist__delete(evlist); -out_free_cpus: - cpu_map__delete(cpus); -out_free_threads: - thread_map__delete(threads); - return err; -#undef nsyscalls -} - static struct test { const char *desc; int (*func)(void); @@ -609,10 +453,6 @@ static struct test { .desc = "detect open syscall event on all cpus", .func = test__open_syscall_event_on_all_cpus, }, - { - .desc = "read samples using the mmap interface", - .func = test__basic_mmap, - }, { .func = NULL, }, diff --git a/trunk/tools/perf/builtin-timechart.c b/trunk/tools/perf/builtin-timechart.c index 0801275c500e..746cf03cb05d 100644 --- a/trunk/tools/perf/builtin-timechart.c +++ b/trunk/tools/perf/builtin-timechart.c @@ -276,24 +276,21 @@ static int cpus_cstate_state[MAX_CPUS]; static u64 cpus_pstate_start_times[MAX_CPUS]; static u64 cpus_pstate_state[MAX_CPUS]; -static int process_comm_event(union perf_event *event, - struct perf_sample *sample __used, +static int process_comm_event(event_t *event, struct sample_data *sample __used, struct perf_session *session __used) { pid_set_comm(event->comm.tid, event->comm.comm); return 0; } -static int process_fork_event(union perf_event *event, - struct perf_sample *sample __used, +static int process_fork_event(event_t *event, struct sample_data *sample __used, struct perf_session *session __used) { pid_fork(event->fork.pid, event->fork.ppid, event->fork.time); return 0; } -static int process_exit_event(union perf_event *event, - struct perf_sample *sample __used, +static int process_exit_event(event_t *event, struct sample_data *sample __used, struct perf_session *session __used) { pid_exit(event->fork.pid, event->fork.time); @@ -489,8 +486,8 @@ static void sched_switch(int cpu, u64 timestamp, struct trace_entry *te) } -static int process_sample_event(union perf_event *event __used, - struct perf_sample *sample, +static int process_sample_event(event_t *event __used, + struct sample_data *sample, struct perf_session *session) { struct trace_entry *te; diff --git a/trunk/tools/perf/builtin-top.c b/trunk/tools/perf/builtin-top.c index c9fd66d4a082..b6998e055767 100644 --- a/trunk/tools/perf/builtin-top.c +++ b/trunk/tools/perf/builtin-top.c @@ -20,16 +20,11 @@ #include "perf.h" -#include "util/annotate.h" -#include "util/cache.h" #include "util/color.h" -#include "util/evlist.h" #include "util/evsel.h" #include "util/session.h" #include "util/symbol.h" #include "util/thread.h" -#include "util/thread_map.h" -#include "util/top.h" #include "util/util.h" #include #include "util/parse-options.h" @@ -50,6 +45,7 @@ #include #include #include +#include #include #include @@ -64,42 +60,85 @@ #define FD(e, x, y) (*(int *)xyarray__entry(e->fd, x, y)) -static struct perf_top top = { - .count_filter = 5, - .delay_secs = 2, - .display_weighted = -1, - .target_pid = -1, - .target_tid = -1, - .active_symbols = LIST_HEAD_INIT(top.active_symbols), - .active_symbols_lock = PTHREAD_MUTEX_INITIALIZER, - .freq = 1000, /* 1 KHz */ -}; - static bool system_wide = false; -static bool use_tui, use_stdio; - static int default_interval = 0; +static int count_filter = 5; +static int print_entries; + +static int target_pid = -1; +static int target_tid = -1; +static struct thread_map *threads; static bool inherit = false; +static struct cpu_map *cpus; static int realtime_prio = 0; static bool group = false; static unsigned int page_size; -static unsigned int mmap_pages = 128; +static unsigned int mmap_pages = 16; +static int freq = 1000; /* 1 KHz */ +static int delay_secs = 2; +static bool zero = false; static bool dump_symtab = false; +static bool hide_kernel_symbols = false; +static bool hide_user_symbols = false; static struct winsize winsize; +/* + * Source + */ + +struct source_line { + u64 eip; + unsigned long count[MAX_COUNTERS]; + char *line; + struct source_line *next; +}; + static const char *sym_filter = NULL; struct sym_entry *sym_filter_entry = NULL; struct sym_entry *sym_filter_entry_sched = NULL; static int sym_pcnt_filter = 5; +static int sym_counter = 0; +static struct perf_evsel *sym_evsel = NULL; +static int display_weighted = -1; +static const char *cpu_list; + +/* + * Symbols + */ + +struct sym_entry_source { + struct source_line *source; + struct source_line *lines; + struct source_line **lines_tail; + pthread_mutex_t lock; +}; + +struct sym_entry { + struct rb_node rb_node; + struct list_head node; + unsigned long snap_count; + double weight; + int skip; + u16 name_len; + u8 origin; + struct map *map; + struct sym_entry_source *src; + unsigned long count[0]; +}; /* * Source functions */ +static inline struct symbol *sym_entry__symbol(struct sym_entry *self) +{ + return ((void *)self) + symbol_conf.priv_size; +} + void get_term_dimensions(struct winsize *ws) { char *s = getenv("LINES"); @@ -124,10 +163,10 @@ void get_term_dimensions(struct winsize *ws) static void update_print_entries(struct winsize *ws) { - top.print_entries = ws->ws_row; + print_entries = ws->ws_row; - if (top.print_entries > 9) - top.print_entries -= 9; + if (print_entries > 9) + print_entries -= 9; } static void sig_winch_handler(int sig __used) @@ -139,9 +178,12 @@ static void sig_winch_handler(int sig __used) static int parse_source(struct sym_entry *syme) { struct symbol *sym; - struct annotation *notes; + struct sym_entry_source *source; struct map *map; - int err = -1; + FILE *file; + char command[PATH_MAX*2]; + const char *path; + u64 len; if (!syme) return -1; @@ -152,136 +194,411 @@ static int parse_source(struct sym_entry *syme) /* * We can't annotate with just /proc/kallsyms */ - if (map->dso->origin == DSO__ORIG_KERNEL) { - pr_err("Can't annotate %s: No vmlinux file was found in the " - "path\n", sym->name); - sleep(1); + if (map->dso->origin == DSO__ORIG_KERNEL) return -1; + + if (syme->src == NULL) { + syme->src = zalloc(sizeof(*source)); + if (syme->src == NULL) + return -1; + pthread_mutex_init(&syme->src->lock, NULL); } - notes = symbol__annotation(sym); - if (notes->src != NULL) { - pthread_mutex_lock(¬es->lock); + source = syme->src; + + if (source->lines) { + pthread_mutex_lock(&source->lock); goto out_assign; } + path = map->dso->long_name; - pthread_mutex_lock(¬es->lock); + len = sym->end - sym->start; - if (symbol__alloc_hist(sym, top.evlist->nr_entries) < 0) { - pr_err("Not enough memory for annotating '%s' symbol!\n", - sym->name); - sleep(1); - goto out_unlock; - } + sprintf(command, + "objdump --start-address=%#0*" PRIx64 " --stop-address=%#0*" PRIx64 " -dS %s", + BITS_PER_LONG / 4, map__rip_2objdump(map, sym->start), + BITS_PER_LONG / 4, map__rip_2objdump(map, sym->end), path); + + file = popen(command, "r"); + if (!file) + return -1; + + pthread_mutex_lock(&source->lock); + source->lines_tail = &source->lines; + while (!feof(file)) { + struct source_line *src; + size_t dummy = 0; + char *c, *sep; + + src = malloc(sizeof(struct source_line)); + assert(src != NULL); + memset(src, 0, sizeof(struct source_line)); + + if (getline(&src->line, &dummy, file) < 0) + break; + if (!src->line) + break; + + c = strchr(src->line, '\n'); + if (c) + *c = 0; - err = symbol__annotate(sym, syme->map, 0); - if (err == 0) { + src->next = NULL; + *source->lines_tail = src; + source->lines_tail = &src->next; + + src->eip = strtoull(src->line, &sep, 16); + if (*sep == ':') + src->eip = map__objdump_2ip(map, src->eip); + else /* this line has no ip info (e.g. source line) */ + src->eip = 0; + } + pclose(file); out_assign: sym_filter_entry = syme; - } -out_unlock: - pthread_mutex_unlock(¬es->lock); - return err; + pthread_mutex_unlock(&source->lock); + return 0; } static void __zero_source_counters(struct sym_entry *syme) { - struct symbol *sym = sym_entry__symbol(syme); - symbol__annotate_zero_histograms(sym); + int i; + struct source_line *line; + + line = syme->src->lines; + while (line) { + for (i = 0; i < nr_counters; i++) + line->count[i] = 0; + line = line->next; + } } static void record_precise_ip(struct sym_entry *syme, int counter, u64 ip) { - struct annotation *notes; - struct symbol *sym; + struct source_line *line; if (syme != sym_filter_entry) return; - sym = sym_entry__symbol(syme); - notes = symbol__annotation(sym); - - if (pthread_mutex_trylock(¬es->lock)) + if (pthread_mutex_trylock(&syme->src->lock)) return; - ip = syme->map->map_ip(syme->map, ip); - symbol__inc_addr_samples(sym, syme->map, counter, ip); + if (syme->src == NULL || syme->src->source == NULL) + goto out_unlock; - pthread_mutex_unlock(¬es->lock); + for (line = syme->src->lines; line; line = line->next) { + /* skip lines without IP info */ + if (line->eip == 0) + continue; + if (line->eip == ip) { + line->count[counter]++; + break; + } + if (line->eip > ip) + break; + } +out_unlock: + pthread_mutex_unlock(&syme->src->lock); } +#define PATTERN_LEN (BITS_PER_LONG / 4 + 2) + +static void lookup_sym_source(struct sym_entry *syme) +{ + struct symbol *symbol = sym_entry__symbol(syme); + struct source_line *line; + char pattern[PATTERN_LEN + 1]; + + sprintf(pattern, "%0*" PRIx64 " <", BITS_PER_LONG / 4, + map__rip_2objdump(syme->map, symbol->start)); + + pthread_mutex_lock(&syme->src->lock); + for (line = syme->src->lines; line; line = line->next) { + if (memcmp(line->line, pattern, PATTERN_LEN) == 0) { + syme->src->source = line; + break; + } + } + pthread_mutex_unlock(&syme->src->lock); +} + +static void show_lines(struct source_line *queue, int count, int total) +{ + int i; + struct source_line *line; + + line = queue; + for (i = 0; i < count; i++) { + float pcnt = 100.0*(float)line->count[sym_counter]/(float)total; + + printf("%8li %4.1f%%\t%s\n", line->count[sym_counter], pcnt, line->line); + line = line->next; + } +} + +#define TRACE_COUNT 3 + static void show_details(struct sym_entry *syme) { - struct annotation *notes; struct symbol *symbol; - int more; + struct source_line *line; + struct source_line *line_queue = NULL; + int displayed = 0; + int line_queue_count = 0, total = 0, more = 0; if (!syme) return; - symbol = sym_entry__symbol(syme); - notes = symbol__annotation(symbol); + if (!syme->src->source) + lookup_sym_source(syme); - pthread_mutex_lock(¬es->lock); - - if (notes->src == NULL) - goto out_unlock; + if (!syme->src->source) + return; - printf("Showing %s for %s\n", event_name(top.sym_evsel), symbol->name); + symbol = sym_entry__symbol(syme); + printf("Showing %s for %s\n", event_name(sym_evsel), symbol->name); printf(" Events Pcnt (>=%d%%)\n", sym_pcnt_filter); - more = symbol__annotate_printf(symbol, syme->map, top.sym_evsel->idx, - 0, sym_pcnt_filter, top.print_entries, 4); - if (top.zero) - symbol__annotate_zero_histogram(symbol, top.sym_evsel->idx); - else - symbol__annotate_decay_histogram(symbol, top.sym_evsel->idx); - if (more != 0) + pthread_mutex_lock(&syme->src->lock); + line = syme->src->source; + while (line) { + total += line->count[sym_counter]; + line = line->next; + } + + line = syme->src->source; + while (line) { + float pcnt = 0.0; + + if (!line_queue_count) + line_queue = line; + line_queue_count++; + + if (line->count[sym_counter]) + pcnt = 100.0 * line->count[sym_counter] / (float)total; + if (pcnt >= (float)sym_pcnt_filter) { + if (displayed <= print_entries) + show_lines(line_queue, line_queue_count, total); + else more++; + displayed += line_queue_count; + line_queue_count = 0; + line_queue = NULL; + } else if (line_queue_count > TRACE_COUNT) { + line_queue = line_queue->next; + line_queue_count--; + } + + line->count[sym_counter] = zero ? 0 : line->count[sym_counter] * 7 / 8; + line = line->next; + } + pthread_mutex_unlock(&syme->src->lock); + if (more) printf("%d lines not displayed, maybe increase display entries [e]\n", more); -out_unlock: - pthread_mutex_unlock(¬es->lock); } +/* + * Symbols will be added here in event__process_sample and will get out + * after decayed. + */ +static LIST_HEAD(active_symbols); +static pthread_mutex_t active_symbols_lock = PTHREAD_MUTEX_INITIALIZER; + +/* + * Ordering weight: count-1 * count-2 * ... / count-n + */ +static double sym_weight(const struct sym_entry *sym) +{ + double weight = sym->snap_count; + int counter; + + if (!display_weighted) + return weight; + + for (counter = 1; counter < nr_counters-1; counter++) + weight *= sym->count[counter]; + + weight /= (sym->count[counter] + 1); + + return weight; +} + +static long samples; +static long kernel_samples, us_samples; +static long exact_samples; +static long guest_us_samples, guest_kernel_samples; static const char CONSOLE_CLEAR[] = ""; static void __list_insert_active_sym(struct sym_entry *syme) { - list_add(&syme->node, &top.active_symbols); + list_add(&syme->node, &active_symbols); } -static void print_sym_table(struct perf_session *session) +static void list_remove_active_sym(struct sym_entry *syme) { - char bf[160]; - int printed = 0; - struct rb_node *nd; - struct sym_entry *syme; + pthread_mutex_lock(&active_symbols_lock); + list_del_init(&syme->node); + pthread_mutex_unlock(&active_symbols_lock); +} + +static void rb_insert_active_sym(struct rb_root *tree, struct sym_entry *se) +{ + struct rb_node **p = &tree->rb_node; + struct rb_node *parent = NULL; + struct sym_entry *iter; + + while (*p != NULL) { + parent = *p; + iter = rb_entry(parent, struct sym_entry, rb_node); + + if (se->weight > iter->weight) + p = &(*p)->rb_left; + else + p = &(*p)->rb_right; + } + + rb_link_node(&se->rb_node, parent, p); + rb_insert_color(&se->rb_node, tree); +} + +static void print_sym_table(void) +{ + int printed = 0, j; + struct perf_evsel *counter; + int snap = !display_weighted ? sym_counter : 0; + float samples_per_sec = samples/delay_secs; + float ksamples_per_sec = kernel_samples/delay_secs; + float us_samples_per_sec = (us_samples)/delay_secs; + float guest_kernel_samples_per_sec = (guest_kernel_samples)/delay_secs; + float guest_us_samples_per_sec = (guest_us_samples)/delay_secs; + float esamples_percent = (100.0*exact_samples)/samples; + float sum_ksamples = 0.0; + struct sym_entry *syme, *n; struct rb_root tmp = RB_ROOT; + struct rb_node *nd; + int sym_width = 0, dso_width = 0, dso_short_width = 0; const int win_width = winsize.ws_col - 1; - int sym_width, dso_width, dso_short_width; - float sum_ksamples = perf_top__decay_samples(&top, &tmp); - puts(CONSOLE_CLEAR); + samples = us_samples = kernel_samples = exact_samples = 0; + guest_kernel_samples = guest_us_samples = 0; - perf_top__header_snprintf(&top, bf, sizeof(bf)); - printf("%s\n", bf); + /* Sort the active symbols */ + pthread_mutex_lock(&active_symbols_lock); + syme = list_entry(active_symbols.next, struct sym_entry, node); + pthread_mutex_unlock(&active_symbols_lock); - perf_top__reset_sample_counters(&top); + list_for_each_entry_safe_from(syme, n, &active_symbols, node) { + syme->snap_count = syme->count[snap]; + if (syme->snap_count != 0) { + + if ((hide_user_symbols && + syme->origin == PERF_RECORD_MISC_USER) || + (hide_kernel_symbols && + syme->origin == PERF_RECORD_MISC_KERNEL)) { + list_remove_active_sym(syme); + continue; + } + syme->weight = sym_weight(syme); + rb_insert_active_sym(&tmp, syme); + sum_ksamples += syme->snap_count; + + for (j = 0; j < nr_counters; j++) + syme->count[j] = zero ? 0 : syme->count[j] * 7 / 8; + } else + list_remove_active_sym(syme); + } + + puts(CONSOLE_CLEAR); printf("%-*.*s\n", win_width, win_width, graph_dotted_line); + if (!perf_guest) { + printf(" PerfTop:%8.0f irqs/sec kernel:%4.1f%%" + " exact: %4.1f%% [", + samples_per_sec, + 100.0 - (100.0 * ((samples_per_sec - ksamples_per_sec) / + samples_per_sec)), + esamples_percent); + } else { + printf(" PerfTop:%8.0f irqs/sec kernel:%4.1f%% us:%4.1f%%" + " guest kernel:%4.1f%% guest us:%4.1f%%" + " exact: %4.1f%% [", + samples_per_sec, + 100.0 - (100.0 * ((samples_per_sec-ksamples_per_sec) / + samples_per_sec)), + 100.0 - (100.0 * ((samples_per_sec-us_samples_per_sec) / + samples_per_sec)), + 100.0 - (100.0 * ((samples_per_sec - + guest_kernel_samples_per_sec) / + samples_per_sec)), + 100.0 - (100.0 * ((samples_per_sec - + guest_us_samples_per_sec) / + samples_per_sec)), + esamples_percent); + } + + if (nr_counters == 1 || !display_weighted) { + struct perf_evsel *first; + first = list_entry(evsel_list.next, struct perf_evsel, node); + printf("%" PRIu64, (uint64_t)first->attr.sample_period); + if (freq) + printf("Hz "); + else + printf(" "); + } - if (session->hists.stats.total_lost != 0) { - color_fprintf(stdout, PERF_COLOR_RED, "WARNING:"); - printf(" LOST %" PRIu64 " events, Check IO/CPU overload\n", - session->hists.stats.total_lost); + if (!display_weighted) + printf("%s", event_name(sym_evsel)); + else list_for_each_entry(counter, &evsel_list, node) { + if (counter->idx) + printf("/"); + + printf("%s", event_name(counter)); } + printf( "], "); + + if (target_pid != -1) + printf(" (target_pid: %d", target_pid); + else if (target_tid != -1) + printf(" (target_tid: %d", target_tid); + else + printf(" (all"); + + if (cpu_list) + printf(", CPU%s: %s)\n", cpus->nr > 1 ? "s" : "", cpu_list); + else { + if (target_tid != -1) + printf(")\n"); + else + printf(", %d CPU%s)\n", cpus->nr, cpus->nr > 1 ? "s" : ""); + } + + printf("%-*.*s\n", win_width, win_width, graph_dotted_line); + if (sym_filter_entry) { show_details(sym_filter_entry); return; } - perf_top__find_widths(&top, &tmp, &dso_width, &dso_short_width, - &sym_width); + /* + * Find the longest symbol name that will be displayed + */ + for (nd = rb_first(&tmp); nd; nd = rb_next(nd)) { + syme = rb_entry(nd, struct sym_entry, rb_node); + if (++printed > print_entries || + (int)syme->snap_count < count_filter) + continue; + + if (syme->map->dso->long_name_len > dso_width) + dso_width = syme->map->dso->long_name_len; + + if (syme->map->dso->short_name_len > dso_short_width) + dso_short_width = syme->map->dso->short_name_len; + + if (syme->name_len > sym_width) + sym_width = syme->name_len; + } + + printed = 0; if (sym_width + dso_width > winsize.ws_col - 29) { dso_width = dso_short_width; @@ -289,7 +606,7 @@ static void print_sym_table(struct perf_session *session) sym_width = winsize.ws_col - dso_width - 29; } putchar('\n'); - if (top.evlist->nr_entries == 1) + if (nr_counters == 1) printf(" samples pcnt"); else printf(" weight samples pcnt"); @@ -298,7 +615,7 @@ static void print_sym_table(struct perf_session *session) printf(" RIP "); printf(" %-*.*s DSO\n", sym_width, sym_width, "function"); printf(" %s _______ _____", - top.evlist->nr_entries == 1 ? " " : "______"); + nr_counters == 1 ? " " : "______"); if (verbose) printf(" ________________"); printf(" %-*.*s", sym_width, sym_width, graph_line); @@ -311,14 +628,13 @@ static void print_sym_table(struct perf_session *session) syme = rb_entry(nd, struct sym_entry, rb_node); sym = sym_entry__symbol(syme); - if (++printed > top.print_entries || - (int)syme->snap_count < top.count_filter) + if (++printed > print_entries || (int)syme->snap_count < count_filter) continue; pcnt = 100.0 - (100.0 * ((sum_ksamples - syme->snap_count) / sum_ksamples)); - if (top.evlist->nr_entries == 1 || !top.display_weighted) + if (nr_counters == 1 || !display_weighted) printf("%20.2f ", syme->weight); else printf("%9.1f %10ld ", syme->weight, syme->snap_count); @@ -377,8 +693,10 @@ static void prompt_symbol(struct sym_entry **target, const char *msg) /* zero counters of active symbol */ if (syme) { + pthread_mutex_lock(&syme->src->lock); __zero_source_counters(syme); *target = NULL; + pthread_mutex_unlock(&syme->src->lock); } fprintf(stdout, "\n%s: ", msg); @@ -389,11 +707,11 @@ static void prompt_symbol(struct sym_entry **target, const char *msg) if (p) *p = 0; - pthread_mutex_lock(&top.active_symbols_lock); - syme = list_entry(top.active_symbols.next, struct sym_entry, node); - pthread_mutex_unlock(&top.active_symbols_lock); + pthread_mutex_lock(&active_symbols_lock); + syme = list_entry(active_symbols.next, struct sym_entry, node); + pthread_mutex_unlock(&active_symbols_lock); - list_for_each_entry_safe_from(syme, n, &top.active_symbols, node) { + list_for_each_entry_safe_from(syme, n, &active_symbols, node) { struct symbol *sym = sym_entry__symbol(syme); if (!strcmp(buf, sym->name)) { @@ -423,28 +741,28 @@ static void print_mapped_keys(void) } fprintf(stdout, "\nMapped keys:\n"); - fprintf(stdout, "\t[d] display refresh delay. \t(%d)\n", top.delay_secs); - fprintf(stdout, "\t[e] display entries (lines). \t(%d)\n", top.print_entries); + fprintf(stdout, "\t[d] display refresh delay. \t(%d)\n", delay_secs); + fprintf(stdout, "\t[e] display entries (lines). \t(%d)\n", print_entries); - if (top.evlist->nr_entries > 1) - fprintf(stdout, "\t[E] active event counter. \t(%s)\n", event_name(top.sym_evsel)); + if (nr_counters > 1) + fprintf(stdout, "\t[E] active event counter. \t(%s)\n", event_name(sym_evsel)); - fprintf(stdout, "\t[f] profile display filter (count). \t(%d)\n", top.count_filter); + fprintf(stdout, "\t[f] profile display filter (count). \t(%d)\n", count_filter); fprintf(stdout, "\t[F] annotate display filter (percent). \t(%d%%)\n", sym_pcnt_filter); fprintf(stdout, "\t[s] annotate symbol. \t(%s)\n", name?: "NULL"); fprintf(stdout, "\t[S] stop annotation.\n"); - if (top.evlist->nr_entries > 1) - fprintf(stdout, "\t[w] toggle display weighted/count[E]r. \t(%d)\n", top.display_weighted ? 1 : 0); + if (nr_counters > 1) + fprintf(stdout, "\t[w] toggle display weighted/count[E]r. \t(%d)\n", display_weighted ? 1 : 0); fprintf(stdout, "\t[K] hide kernel_symbols symbols. \t(%s)\n", - top.hide_kernel_symbols ? "yes" : "no"); + hide_kernel_symbols ? "yes" : "no"); fprintf(stdout, "\t[U] hide user symbols. \t(%s)\n", - top.hide_user_symbols ? "yes" : "no"); - fprintf(stdout, "\t[z] toggle sample zeroing. \t(%d)\n", top.zero ? 1 : 0); + hide_user_symbols ? "yes" : "no"); + fprintf(stdout, "\t[z] toggle sample zeroing. \t(%d)\n", zero ? 1 : 0); fprintf(stdout, "\t[qQ] quit.\n"); } @@ -465,7 +783,7 @@ static int key_mapped(int c) return 1; case 'E': case 'w': - return top.evlist->nr_entries > 1 ? 1 : 0; + return nr_counters > 1 ? 1 : 0; default: break; } @@ -500,47 +818,47 @@ static void handle_keypress(struct perf_session *session, int c) switch (c) { case 'd': - prompt_integer(&top.delay_secs, "Enter display delay"); - if (top.delay_secs < 1) - top.delay_secs = 1; + prompt_integer(&delay_secs, "Enter display delay"); + if (delay_secs < 1) + delay_secs = 1; break; case 'e': - prompt_integer(&top.print_entries, "Enter display entries (lines)"); - if (top.print_entries == 0) { + prompt_integer(&print_entries, "Enter display entries (lines)"); + if (print_entries == 0) { sig_winch_handler(SIGWINCH); signal(SIGWINCH, sig_winch_handler); } else signal(SIGWINCH, SIG_DFL); break; case 'E': - if (top.evlist->nr_entries > 1) { + if (nr_counters > 1) { fprintf(stderr, "\nAvailable events:"); - list_for_each_entry(top.sym_evsel, &top.evlist->entries, node) - fprintf(stderr, "\n\t%d %s", top.sym_evsel->idx, event_name(top.sym_evsel)); + list_for_each_entry(sym_evsel, &evsel_list, node) + fprintf(stderr, "\n\t%d %s", sym_evsel->idx, event_name(sym_evsel)); - prompt_integer(&top.sym_counter, "Enter details event counter"); + prompt_integer(&sym_counter, "Enter details event counter"); - if (top.sym_counter >= top.evlist->nr_entries) { - top.sym_evsel = list_entry(top.evlist->entries.next, struct perf_evsel, node); - top.sym_counter = 0; - fprintf(stderr, "Sorry, no such event, using %s.\n", event_name(top.sym_evsel)); + if (sym_counter >= nr_counters) { + sym_evsel = list_entry(evsel_list.next, struct perf_evsel, node); + sym_counter = 0; + fprintf(stderr, "Sorry, no such event, using %s.\n", event_name(sym_evsel)); sleep(1); break; } - list_for_each_entry(top.sym_evsel, &top.evlist->entries, node) - if (top.sym_evsel->idx == top.sym_counter) + list_for_each_entry(sym_evsel, &evsel_list, node) + if (sym_evsel->idx == sym_counter) break; - } else top.sym_counter = 0; + } else sym_counter = 0; break; case 'f': - prompt_integer(&top.count_filter, "Enter display event count filter"); + prompt_integer(&count_filter, "Enter display event count filter"); break; case 'F': prompt_percent(&sym_pcnt_filter, "Enter details display event filter (percent)"); break; case 'K': - top.hide_kernel_symbols = !top.hide_kernel_symbols; + hide_kernel_symbols = !hide_kernel_symbols; break; case 'q': case 'Q': @@ -557,32 +875,26 @@ static void handle_keypress(struct perf_session *session, int c) else { struct sym_entry *syme = sym_filter_entry; + pthread_mutex_lock(&syme->src->lock); sym_filter_entry = NULL; __zero_source_counters(syme); + pthread_mutex_unlock(&syme->src->lock); } break; case 'U': - top.hide_user_symbols = !top.hide_user_symbols; + hide_user_symbols = !hide_user_symbols; break; case 'w': - top.display_weighted = ~top.display_weighted; + display_weighted = ~display_weighted; break; case 'z': - top.zero = !top.zero; + zero = !zero; break; default: break; } } -static void *display_thread_tui(void *arg __used) -{ - perf_top__tui_browser(&top); - exit_browser(0); - exit(0); - return NULL; -} - static void *display_thread(void *arg __used) { struct pollfd stdin_poll = { .fd = 0, .events = POLLIN }; @@ -597,13 +909,13 @@ static void *display_thread(void *arg __used) tc.c_cc[VTIME] = 0; repeat: - delay_msecs = top.delay_secs * 1000; + delay_msecs = delay_secs * 1000; tcsetattr(0, TCSANOW, &tc); /* trash return*/ getc(stdin); do { - print_sym_table(session); + print_sym_table(); } while (!poll(&stdin_poll, 1, delay_msecs) == 1); c = getc(stdin); @@ -618,7 +930,6 @@ static void *display_thread(void *arg __used) /* Tag samples to be skipped. */ static const char *skip_symbols[] = { "default_idle", - "native_safe_halt", "cpu_idle", "enter_idle", "exit_idle", @@ -654,7 +965,7 @@ static int symbol_filter(struct map *map, struct symbol *sym) syme = symbol__priv(sym); syme->map = map; - symbol__annotate_init(map, sym); + syme->src = NULL; if (!sym_filter_entry && sym_filter && !strcmp(name, sym_filter)) { /* schedule initial sym_filter_entry setup */ @@ -669,40 +980,44 @@ static int symbol_filter(struct map *map, struct symbol *sym) } } + if (!syme->skip) + syme->name_len = strlen(sym->name); + return 0; } -static void perf_event__process_sample(const union perf_event *event, - struct perf_sample *sample, - struct perf_session *session) +static void event__process_sample(const event_t *self, + struct sample_data *sample, + struct perf_session *session, + struct perf_evsel *evsel) { - u64 ip = event->ip.ip; + u64 ip = self->ip.ip; struct sym_entry *syme; struct addr_location al; struct machine *machine; - u8 origin = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK; + u8 origin = self->header.misc & PERF_RECORD_MISC_CPUMODE_MASK; - ++top.samples; + ++samples; switch (origin) { case PERF_RECORD_MISC_USER: - ++top.us_samples; - if (top.hide_user_symbols) + ++us_samples; + if (hide_user_symbols) return; machine = perf_session__find_host_machine(session); break; case PERF_RECORD_MISC_KERNEL: - ++top.kernel_samples; - if (top.hide_kernel_symbols) + ++kernel_samples; + if (hide_kernel_symbols) return; machine = perf_session__find_host_machine(session); break; case PERF_RECORD_MISC_GUEST_KERNEL: - ++top.guest_kernel_samples; - machine = perf_session__find_machine(session, event->ip.pid); + ++guest_kernel_samples; + machine = perf_session__find_machine(session, self->ip.pid); break; case PERF_RECORD_MISC_GUEST_USER: - ++top.guest_us_samples; + ++guest_us_samples; /* * TODO: we don't process guest user from host side * except simple counting. @@ -714,15 +1029,15 @@ static void perf_event__process_sample(const union perf_event *event, if (!machine && perf_guest) { pr_err("Can't find guest [%d]'s kernel information\n", - event->ip.pid); + self->ip.pid); return; } - if (event->header.misc & PERF_RECORD_MISC_EXACT_IP) - top.exact_samples++; + if (self->header.misc & PERF_RECORD_MISC_EXACT_IP) + exact_samples++; - if (perf_event__preprocess_sample(event, session, &al, sample, - symbol_filter) < 0 || + if (event__preprocess_sample(self, session, &al, sample, + symbol_filter) < 0 || al.filtered) return; @@ -767,67 +1082,166 @@ static void perf_event__process_sample(const union perf_event *event, syme = symbol__priv(al.sym); if (!syme->skip) { - struct perf_evsel *evsel; - - syme->origin = origin; - evsel = perf_evlist__id2evsel(top.evlist, sample->id); - assert(evsel != NULL); syme->count[evsel->idx]++; + syme->origin = origin; record_precise_ip(syme, evsel->idx, ip); - pthread_mutex_lock(&top.active_symbols_lock); + pthread_mutex_lock(&active_symbols_lock); if (list_empty(&syme->node) || !syme->node.next) __list_insert_active_sym(syme); - pthread_mutex_unlock(&top.active_symbols_lock); + pthread_mutex_unlock(&active_symbols_lock); } } -static void perf_session__mmap_read_cpu(struct perf_session *self, int cpu) +struct mmap_data { + void *base; + int mask; + unsigned int prev; +}; + +static int perf_evsel__alloc_mmap_per_thread(struct perf_evsel *evsel, + int ncpus, int nthreads) { - struct perf_sample sample; - union perf_event *event; + evsel->priv = xyarray__new(ncpus, nthreads, sizeof(struct mmap_data)); + return evsel->priv != NULL ? 0 : -ENOMEM; +} - while ((event = perf_evlist__read_on_cpu(top.evlist, cpu)) != NULL) { - perf_session__parse_sample(self, event, &sample); +static void perf_evsel__free_mmap(struct perf_evsel *evsel) +{ + xyarray__delete(evsel->priv); + evsel->priv = NULL; +} + +static unsigned int mmap_read_head(struct mmap_data *md) +{ + struct perf_event_mmap_page *pc = md->base; + int head; + + head = pc->data_head; + rmb(); + + return head; +} +static void perf_session__mmap_read_counter(struct perf_session *self, + struct perf_evsel *evsel, + int cpu, int thread_idx) +{ + struct xyarray *mmap_array = evsel->priv; + struct mmap_data *md = xyarray__entry(mmap_array, cpu, thread_idx); + unsigned int head = mmap_read_head(md); + unsigned int old = md->prev; + unsigned char *data = md->base + page_size; + struct sample_data sample; + int diff; + + /* + * If we're further behind than half the buffer, there's a chance + * the writer will bite our tail and mess up the samples under us. + * + * If we somehow ended up ahead of the head, we got messed up. + * + * In either case, truncate and restart at head. + */ + diff = head - old; + if (diff > md->mask / 2 || diff < 0) { + fprintf(stderr, "WARNING: failed to keep up with mmap data.\n"); + + /* + * head points to a known good entry, start there. + */ + old = head; + } + + for (; old != head;) { + event_t *event = (event_t *)&data[old & md->mask]; + + event_t event_copy; + + size_t size = event->header.size; + + /* + * Event straddles the mmap boundary -- header should always + * be inside due to u64 alignment of output. + */ + if ((old & md->mask) + size != ((old + size) & md->mask)) { + unsigned int offset = old; + unsigned int len = min(sizeof(*event), size), cpy; + void *dst = &event_copy; + + do { + cpy = min(md->mask + 1 - (offset & md->mask), len); + memcpy(dst, &data[offset & md->mask], cpy); + offset += cpy; + dst += cpy; + len -= cpy; + } while (len); + + event = &event_copy; + } + + event__parse_sample(event, self, &sample); if (event->header.type == PERF_RECORD_SAMPLE) - perf_event__process_sample(event, &sample, self); + event__process_sample(event, &sample, self, evsel); else - perf_event__process(event, &sample, self); + event__process(event, &sample, self); + old += size; } + + md->prev = old; } +static struct pollfd *event_array; + static void perf_session__mmap_read(struct perf_session *self) { - int i; - - for (i = 0; i < top.evlist->cpus->nr; i++) - perf_session__mmap_read_cpu(self, i); + struct perf_evsel *counter; + int i, thread_index; + + for (i = 0; i < cpus->nr; i++) { + list_for_each_entry(counter, &evsel_list, node) { + for (thread_index = 0; + thread_index < threads->nr; + thread_index++) { + perf_session__mmap_read_counter(self, + counter, i, thread_index); + } + } + } } -static void start_counters(struct perf_evlist *evlist) +int nr_poll; +int group_fd; + +static void start_counter(int i, struct perf_evsel *evsel) { - struct perf_evsel *counter; + struct xyarray *mmap_array = evsel->priv; + struct mmap_data *mm; + struct perf_event_attr *attr; + int cpu = -1; + int thread_index; - list_for_each_entry(counter, &evlist->entries, node) { - struct perf_event_attr *attr = &counter->attr; + if (target_tid == -1) + cpu = cpus->map[i]; - attr->sample_type = PERF_SAMPLE_IP | PERF_SAMPLE_TID; + attr = &evsel->attr; - if (top.freq) { - attr->sample_type |= PERF_SAMPLE_PERIOD; - attr->freq = 1; - attr->sample_freq = top.freq; - } + attr->sample_type = PERF_SAMPLE_IP | PERF_SAMPLE_TID; - if (evlist->nr_entries > 1) { - attr->sample_type |= PERF_SAMPLE_ID; - attr->read_format |= PERF_FORMAT_ID; - } + if (freq) { + attr->sample_type |= PERF_SAMPLE_PERIOD; + attr->freq = 1; + attr->sample_freq = freq; + } + + attr->inherit = (cpu < 0) && inherit; + attr->mmap = 1; - attr->mmap = 1; + for (thread_index = 0; thread_index < threads->nr; thread_index++) { try_again: - if (perf_evsel__open(counter, top.evlist->cpus, - top.evlist->threads, group, inherit) < 0) { + FD(evsel, i, thread_index) = sys_perf_event_open(attr, + threads->map[thread_index], cpu, group_fd, 0); + + if (FD(evsel, i, thread_index) < 0) { int err = errno; if (err == EPERM || err == EACCES) @@ -839,8 +1253,8 @@ static void start_counters(struct perf_evlist *evlist) * based cpu-clock-tick sw counter, which * is always available even if no PMU support: */ - if (attr->type == PERF_TYPE_HARDWARE && - attr->config == PERF_COUNT_HW_CPU_CYCLES) { + if (attr->type == PERF_TYPE_HARDWARE + && attr->config == PERF_COUNT_HW_CPU_CYCLES) { if (verbose) warning(" ... trying to fall back to cpu-clock-ticks\n"); @@ -850,23 +1264,39 @@ static void start_counters(struct perf_evlist *evlist) goto try_again; } printf("\n"); - error("sys_perf_event_open() syscall returned with %d " - "(%s). /bin/dmesg may provide additional information.\n", - err, strerror(err)); + error("sys_perf_event_open() syscall returned with %d (%s). /bin/dmesg may provide additional information.\n", + FD(evsel, i, thread_index), strerror(err)); die("No CONFIG_PERF_EVENTS=y kernel support configured?\n"); exit(-1); } - } + assert(FD(evsel, i, thread_index) >= 0); + fcntl(FD(evsel, i, thread_index), F_SETFL, O_NONBLOCK); - if (perf_evlist__mmap(evlist, mmap_pages, false) < 0) - die("failed to mmap with %d (%s)\n", errno, strerror(errno)); + /* + * First counter acts as the group leader: + */ + if (group && group_fd == -1) + group_fd = FD(evsel, i, thread_index); + + event_array[nr_poll].fd = FD(evsel, i, thread_index); + event_array[nr_poll].events = POLLIN; + nr_poll++; + + mm = xyarray__entry(mmap_array, i, thread_index); + mm->prev = 0; + mm->mask = mmap_pages*page_size - 1; + mm->base = mmap(NULL, (mmap_pages+1)*page_size, + PROT_READ, MAP_SHARED, FD(evsel, i, thread_index), 0); + if (mm->base == MAP_FAILED) + die("failed to mmap with %d (%s)\n", errno, strerror(errno)); + } } static int __cmd_top(void) { pthread_t thread; - struct perf_evsel *first; - int ret __used; + struct perf_evsel *counter; + int i, ret; /* * FIXME: perf_session__new should allow passing a O_MMAP, so that all this * mmap reading, etc is encapsulated in it. Use O_WRONLY for now. @@ -875,23 +1305,23 @@ static int __cmd_top(void) if (session == NULL) return -ENOMEM; - if (top.target_tid != -1) - perf_event__synthesize_thread_map(top.evlist->threads, - perf_event__process, session); + if (target_tid != -1) + event__synthesize_thread(target_tid, event__process, session); else - perf_event__synthesize_threads(perf_event__process, session); + event__synthesize_threads(event__process, session); - start_counters(top.evlist); - first = list_entry(top.evlist->entries.next, struct perf_evsel, node); - perf_session__set_sample_type(session, first->attr.sample_type); + for (i = 0; i < cpus->nr; i++) { + group_fd = -1; + list_for_each_entry(counter, &evsel_list, node) + start_counter(i, counter); + } /* Wait for a minimal set of events before starting the snapshot */ - poll(top.evlist->pollfd, top.evlist->nr_fds, 100); + poll(&event_array[0], nr_poll, 100); perf_session__mmap_read(session); - if (pthread_create(&thread, NULL, (use_browser > 0 ? display_thread_tui : - display_thread), session)) { + if (pthread_create(&thread, NULL, display_thread, session)) { printf("Could not create display thread.\n"); exit(-1); } @@ -907,12 +1337,12 @@ static int __cmd_top(void) } while (1) { - u64 hits = top.samples; + int hits = samples; perf_session__mmap_read(session); - if (hits == top.samples) - ret = poll(top.evlist->pollfd, top.evlist->nr_fds, 100); + if (hits == samples) + ret = poll(event_array, nr_poll, 100); } return 0; @@ -924,31 +1354,31 @@ static const char * const top_usage[] = { }; static const struct option options[] = { - OPT_CALLBACK('e', "event", &top.evlist, "event", + OPT_CALLBACK('e', "event", NULL, "event", "event selector. use 'perf list' to list available events", parse_events), OPT_INTEGER('c', "count", &default_interval, "event period to sample"), - OPT_INTEGER('p', "pid", &top.target_pid, + OPT_INTEGER('p', "pid", &target_pid, "profile events on existing process id"), - OPT_INTEGER('t', "tid", &top.target_tid, + OPT_INTEGER('t', "tid", &target_tid, "profile events on existing thread id"), OPT_BOOLEAN('a', "all-cpus", &system_wide, "system-wide collection from all CPUs"), - OPT_STRING('C', "cpu", &top.cpu_list, "cpu", + OPT_STRING('C', "cpu", &cpu_list, "cpu", "list of cpus to monitor"), OPT_STRING('k', "vmlinux", &symbol_conf.vmlinux_name, "file", "vmlinux pathname"), - OPT_BOOLEAN('K', "hide_kernel_symbols", &top.hide_kernel_symbols, + OPT_BOOLEAN('K', "hide_kernel_symbols", &hide_kernel_symbols, "hide kernel symbols"), OPT_UINTEGER('m', "mmap-pages", &mmap_pages, "number of mmap data pages"), OPT_INTEGER('r', "realtime", &realtime_prio, "collect data with this RT SCHED_FIFO priority"), - OPT_INTEGER('d', "delay", &top.delay_secs, + OPT_INTEGER('d', "delay", &delay_secs, "number of seconds to delay between refreshes"), OPT_BOOLEAN('D', "dump-symtab", &dump_symtab, "dump the symbol table used for profiling"), - OPT_INTEGER('f', "count-filter", &top.count_filter, + OPT_INTEGER('f', "count-filter", &count_filter, "only display functions with more events than this"), OPT_BOOLEAN('g', "group", &group, "put the counters into a counter group"), @@ -956,16 +1386,14 @@ static const struct option options[] = { "child tasks inherit counters"), OPT_STRING('s', "sym-annotate", &sym_filter, "symbol name", "symbol to annotate"), - OPT_BOOLEAN('z', "zero", &top.zero, + OPT_BOOLEAN('z', "zero", &zero, "zero history across updates"), - OPT_INTEGER('F', "freq", &top.freq, + OPT_INTEGER('F', "freq", &freq, "profile at this frequency"), - OPT_INTEGER('E', "entries", &top.print_entries, + OPT_INTEGER('E', "entries", &print_entries, "display this many functions"), - OPT_BOOLEAN('U', "hide_user_symbols", &top.hide_user_symbols, + OPT_BOOLEAN('U', "hide_user_symbols", &hide_user_symbols, "hide user symbols"), - OPT_BOOLEAN(0, "tui", &use_tui, "Use the TUI interface"), - OPT_BOOLEAN(0, "stdio", &use_stdio, "Use the stdio interface"), OPT_INCR('v', "verbose", &verbose, "be more verbose (show counter open errors, etc)"), OPT_END() @@ -976,68 +1404,64 @@ int cmd_top(int argc, const char **argv, const char *prefix __used) struct perf_evsel *pos; int status = -ENOMEM; - top.evlist = perf_evlist__new(NULL, NULL); - if (top.evlist == NULL) - return -ENOMEM; - page_size = sysconf(_SC_PAGE_SIZE); argc = parse_options(argc, argv, options, top_usage, 0); if (argc) usage_with_options(top_usage, options); - /* - * XXX For now start disabled, only using TUI if explicitely asked for. - * Change that when handle_keys equivalent gets written, live annotation - * done, etc. - */ - use_browser = 0; + if (target_pid != -1) + target_tid = target_pid; - if (use_stdio) - use_browser = 0; - else if (use_tui) - use_browser = 1; + threads = thread_map__new(target_pid, target_tid); + if (threads == NULL) { + pr_err("Problems finding threads of monitor\n"); + usage_with_options(top_usage, options); + } - setup_browser(false); + event_array = malloc((sizeof(struct pollfd) * + MAX_NR_CPUS * MAX_COUNTERS * threads->nr)); + if (!event_array) + return -ENOMEM; /* CPU and PID are mutually exclusive */ - if (top.target_tid > 0 && top.cpu_list) { + if (target_tid > 0 && cpu_list) { printf("WARNING: PID switch overriding CPU\n"); sleep(1); - top.cpu_list = NULL; + cpu_list = NULL; } - if (top.target_pid != -1) - top.target_tid = top.target_pid; - - if (perf_evlist__create_maps(top.evlist, top.target_pid, - top.target_tid, top.cpu_list) < 0) - usage_with_options(top_usage, options); - - if (!top.evlist->nr_entries && - perf_evlist__add_default(top.evlist) < 0) { + if (!nr_counters && perf_evsel_list__create_default() < 0) { pr_err("Not enough memory for event selector list\n"); return -ENOMEM; } - if (top.delay_secs < 1) - top.delay_secs = 1; + if (delay_secs < 1) + delay_secs = 1; /* * User specified count overrides default frequency. */ if (default_interval) - top.freq = 0; - else if (top.freq) { - default_interval = top.freq; + freq = 0; + else if (freq) { + default_interval = freq; } else { fprintf(stderr, "frequency and count are zero, aborting\n"); exit(EXIT_FAILURE); } - list_for_each_entry(pos, &top.evlist->entries, node) { - if (perf_evsel__alloc_fd(pos, top.evlist->cpus->nr, - top.evlist->threads->nr) < 0) + if (target_tid != -1) + cpus = cpu_map__dummy_new(); + else + cpus = cpu_map__new(cpu_list); + + if (cpus == NULL) + usage_with_options(top_usage, options); + + list_for_each_entry(pos, &evsel_list, node) { + if (perf_evsel__alloc_mmap_per_thread(pos, cpus->nr, threads->nr) < 0 || + perf_evsel__alloc_fd(pos, cpus->nr, threads->nr) < 0) goto out_free_fd; /* * Fill in the ones not specifically initialized via -c: @@ -1048,28 +1472,26 @@ int cmd_top(int argc, const char **argv, const char *prefix __used) pos->attr.sample_period = default_interval; } - if (perf_evlist__alloc_pollfd(top.evlist) < 0 || - perf_evlist__alloc_mmap(top.evlist) < 0) - goto out_free_fd; - - top.sym_evsel = list_entry(top.evlist->entries.next, struct perf_evsel, node); + sym_evsel = list_entry(evsel_list.next, struct perf_evsel, node); - symbol_conf.priv_size = (sizeof(struct sym_entry) + sizeof(struct annotation) + - (top.evlist->nr_entries + 1) * sizeof(unsigned long)); + symbol_conf.priv_size = (sizeof(struct sym_entry) + + (nr_counters + 1) * sizeof(unsigned long)); symbol_conf.try_vmlinux_path = (symbol_conf.vmlinux_name == NULL); if (symbol__init() < 0) return -1; get_term_dimensions(&winsize); - if (top.print_entries == 0) { + if (print_entries == 0) { update_print_entries(&winsize); signal(SIGWINCH, sig_winch_handler); } status = __cmd_top(); out_free_fd: - perf_evlist__delete(top.evlist); + list_for_each_entry(pos, &evsel_list, node) + perf_evsel__free_mmap(pos); + perf_evsel_list__delete(); return status; } diff --git a/trunk/tools/perf/perf.h b/trunk/tools/perf/perf.h index a5fc660c1f12..95aaf565c704 100644 --- a/trunk/tools/perf/perf.h +++ b/trunk/tools/perf/perf.h @@ -94,32 +94,6 @@ void get_term_dimensions(struct winsize *ws); #include "util/types.h" #include -struct perf_mmap { - void *base; - int mask; - unsigned int prev; -}; - -static inline unsigned int perf_mmap__read_head(struct perf_mmap *mm) -{ - struct perf_event_mmap_page *pc = mm->base; - int head = pc->data_head; - rmb(); - return head; -} - -static inline void perf_mmap__write_tail(struct perf_mmap *md, - unsigned long tail) -{ - struct perf_event_mmap_page *pc = md->base; - - /* - * ensure all reads are done before we write the tail out. - */ - /* mb(); */ - pc->data_tail = tail; -} - /* * prctl(PR_TASK_PERF_EVENTS_DISABLE) will (cheaply) disable all * counters in the current task. diff --git a/trunk/tools/perf/python/twatch.py b/trunk/tools/perf/python/twatch.py deleted file mode 100755 index df638c438a9f..000000000000 --- a/trunk/tools/perf/python/twatch.py +++ /dev/null @@ -1,41 +0,0 @@ -#! /usr/bin/python -# -*- python -*- -# -*- coding: utf-8 -*- -# twatch - Experimental use of the perf python interface -# Copyright (C) 2011 Arnaldo Carvalho de Melo -# -# This application 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; version 2. -# -# This application 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. - -import perf - -def main(): - cpus = perf.cpu_map() - threads = perf.thread_map() - evsel = perf.evsel(task = 1, comm = 1, mmap = 0, - wakeup_events = 1, sample_period = 1, - sample_id_all = 1, - sample_type = perf.SAMPLE_PERIOD | perf.SAMPLE_TID | perf.SAMPLE_CPU | perf.SAMPLE_TID) - evsel.open(cpus = cpus, threads = threads); - evlist = perf.evlist(cpus, threads) - evlist.add(evsel) - evlist.mmap() - while True: - evlist.poll(timeout = -1) - for cpu in cpus: - event = evlist.read_on_cpu(cpu) - if not event: - continue - print "cpu: %2d, pid: %4d, tid: %4d" % (event.sample_cpu, - event.sample_pid, - event.sample_tid), - print event - -if __name__ == '__main__': - main() diff --git a/trunk/tools/perf/util/annotate.c b/trunk/tools/perf/util/annotate.c deleted file mode 100644 index 02976b895f27..000000000000 --- a/trunk/tools/perf/util/annotate.c +++ /dev/null @@ -1,593 +0,0 @@ -/* - * Copyright (C) 2011, Red Hat Inc, Arnaldo Carvalho de Melo - * - * Parts came from builtin-annotate.c, see those files for further - * copyright notes. - * - * Released under the GPL v2. (and only v2, not any later version) - */ - -#include "util.h" -#include "build-id.h" -#include "color.h" -#include "cache.h" -#include "symbol.h" -#include "debug.h" -#include "annotate.h" -#include - -int symbol__annotate_init(struct map *map __used, struct symbol *sym) -{ - struct annotation *notes = symbol__annotation(sym); - pthread_mutex_init(¬es->lock, NULL); - return 0; -} - -int symbol__alloc_hist(struct symbol *sym, int nevents) -{ - struct annotation *notes = symbol__annotation(sym); - size_t sizeof_sym_hist = (sizeof(struct sym_hist) + - (sym->end - sym->start) * sizeof(u64)); - - notes->src = zalloc(sizeof(*notes->src) + nevents * sizeof_sym_hist); - if (notes->src == NULL) - return -1; - notes->src->sizeof_sym_hist = sizeof_sym_hist; - notes->src->nr_histograms = nevents; - INIT_LIST_HEAD(¬es->src->source); - return 0; -} - -void symbol__annotate_zero_histograms(struct symbol *sym) -{ - struct annotation *notes = symbol__annotation(sym); - - pthread_mutex_lock(¬es->lock); - if (notes->src != NULL) - memset(notes->src->histograms, 0, - notes->src->nr_histograms * notes->src->sizeof_sym_hist); - pthread_mutex_unlock(¬es->lock); -} - -int symbol__inc_addr_samples(struct symbol *sym, struct map *map, - int evidx, u64 addr) -{ - unsigned offset; - struct annotation *notes; - struct sym_hist *h; - - notes = symbol__annotation(sym); - if (notes->src == NULL) - return -ENOMEM; - - pr_debug3("%s: addr=%#" PRIx64 "\n", __func__, map->unmap_ip(map, addr)); - - if (addr >= sym->end) - return 0; - - offset = addr - sym->start; - h = annotation__histogram(notes, evidx); - h->sum++; - h->addr[offset]++; - - pr_debug3("%#" PRIx64 " %s: period++ [addr: %#" PRIx64 ", %#" PRIx64 - ", evidx=%d] => %" PRIu64 "\n", sym->start, sym->name, - addr, addr - sym->start, evidx, h->addr[offset]); - return 0; -} - -static struct objdump_line *objdump_line__new(s64 offset, char *line, size_t privsize) -{ - struct objdump_line *self = malloc(sizeof(*self) + privsize); - - if (self != NULL) { - self->offset = offset; - self->line = line; - } - - return self; -} - -void objdump_line__free(struct objdump_line *self) -{ - free(self->line); - free(self); -} - -static void objdump__add_line(struct list_head *head, struct objdump_line *line) -{ - list_add_tail(&line->node, head); -} - -struct objdump_line *objdump__get_next_ip_line(struct list_head *head, - struct objdump_line *pos) -{ - list_for_each_entry_continue(pos, head, node) - if (pos->offset >= 0) - return pos; - - return NULL; -} - -static int objdump_line__print(struct objdump_line *oline, struct symbol *sym, - int evidx, u64 len, int min_pcnt, - int printed, int max_lines, - struct objdump_line *queue) -{ - static const char *prev_line; - static const char *prev_color; - - if (oline->offset != -1) { - const char *path = NULL; - unsigned int hits = 0; - double percent = 0.0; - const char *color; - struct annotation *notes = symbol__annotation(sym); - struct source_line *src_line = notes->src->lines; - struct sym_hist *h = annotation__histogram(notes, evidx); - s64 offset = oline->offset; - struct objdump_line *next; - - next = objdump__get_next_ip_line(¬es->src->source, oline); - - while (offset < (s64)len && - (next == NULL || offset < next->offset)) { - if (src_line) { - if (path == NULL) - path = src_line[offset].path; - percent += src_line[offset].percent; - } else - hits += h->addr[offset]; - - ++offset; - } - - if (src_line == NULL && h->sum) - percent = 100.0 * hits / h->sum; - - if (percent < min_pcnt) - return -1; - - if (max_lines && printed >= max_lines) - return 1; - - if (queue != NULL) { - list_for_each_entry_from(queue, ¬es->src->source, node) { - if (queue == oline) - break; - objdump_line__print(queue, sym, evidx, len, - 0, 0, 1, NULL); - } - } - - color = get_percent_color(percent); - - /* - * Also color the filename and line if needed, with - * the same color than the percentage. Don't print it - * twice for close colored addr with the same filename:line - */ - if (path) { - if (!prev_line || strcmp(prev_line, path) - || color != prev_color) { - color_fprintf(stdout, color, " %s", path); - prev_line = path; - prev_color = color; - } - } - - color_fprintf(stdout, color, " %7.2f", percent); - printf(" : "); - color_fprintf(stdout, PERF_COLOR_BLUE, "%s\n", oline->line); - } else if (max_lines && printed >= max_lines) - return 1; - else { - if (queue) - return -1; - - if (!*oline->line) - printf(" :\n"); - else - printf(" : %s\n", oline->line); - } - - return 0; -} - -static int symbol__parse_objdump_line(struct symbol *sym, struct map *map, - FILE *file, size_t privsize) -{ - struct annotation *notes = symbol__annotation(sym); - struct objdump_line *objdump_line; - char *line = NULL, *tmp, *tmp2, *c; - size_t line_len; - s64 line_ip, offset = -1; - - if (getline(&line, &line_len, file) < 0) - return -1; - - if (!line) - return -1; - - while (line_len != 0 && isspace(line[line_len - 1])) - line[--line_len] = '\0'; - - c = strchr(line, '\n'); - if (c) - *c = 0; - - line_ip = -1; - - /* - * Strip leading spaces: - */ - tmp = line; - while (*tmp) { - if (*tmp != ' ') - break; - tmp++; - } - - if (*tmp) { - /* - * Parse hexa addresses followed by ':' - */ - line_ip = strtoull(tmp, &tmp2, 16); - if (*tmp2 != ':' || tmp == tmp2 || tmp2[1] == '\0') - line_ip = -1; - } - - if (line_ip != -1) { - u64 start = map__rip_2objdump(map, sym->start), - end = map__rip_2objdump(map, sym->end); - - offset = line_ip - start; - if (offset < 0 || (u64)line_ip > end) - offset = -1; - } - - objdump_line = objdump_line__new(offset, line, privsize); - if (objdump_line == NULL) { - free(line); - return -1; - } - objdump__add_line(¬es->src->source, objdump_line); - - return 0; -} - -int symbol__annotate(struct symbol *sym, struct map *map, size_t privsize) -{ - struct dso *dso = map->dso; - char *filename = dso__build_id_filename(dso, NULL, 0); - bool free_filename = true; - char command[PATH_MAX * 2]; - FILE *file; - int err = 0; - char symfs_filename[PATH_MAX]; - - if (filename) { - snprintf(symfs_filename, sizeof(symfs_filename), "%s%s", - symbol_conf.symfs, filename); - } - - if (filename == NULL) { - if (dso->has_build_id) { - pr_err("Can't annotate %s: not enough memory\n", - sym->name); - return -ENOMEM; - } - goto fallback; - } else if (readlink(symfs_filename, command, sizeof(command)) < 0 || - strstr(command, "[kernel.kallsyms]") || - access(symfs_filename, R_OK)) { - free(filename); -fallback: - /* - * If we don't have build-ids or the build-id file isn't in the - * cache, or is just a kallsyms file, well, lets hope that this - * DSO is the same as when 'perf record' ran. - */ - filename = dso->long_name; - snprintf(symfs_filename, sizeof(symfs_filename), "%s%s", - symbol_conf.symfs, filename); - free_filename = false; - } - - if (dso->origin == DSO__ORIG_KERNEL) { - if (dso->annotate_warned) - goto out_free_filename; - err = -ENOENT; - dso->annotate_warned = 1; - pr_err("Can't annotate %s: No vmlinux file was found in the " - "path\n", sym->name); - goto out_free_filename; - } - - pr_debug("%s: filename=%s, sym=%s, start=%#" PRIx64 ", end=%#" PRIx64 "\n", __func__, - filename, sym->name, map->unmap_ip(map, sym->start), - map->unmap_ip(map, sym->end)); - - pr_debug("annotating [%p] %30s : [%p] %30s\n", - dso, dso->long_name, sym, sym->name); - - snprintf(command, sizeof(command), - "objdump --start-address=0x%016" PRIx64 - " --stop-address=0x%016" PRIx64 " -dS -C %s|grep -v %s|expand", - map__rip_2objdump(map, sym->start), - map__rip_2objdump(map, sym->end), - symfs_filename, filename); - - pr_debug("Executing: %s\n", command); - - file = popen(command, "r"); - if (!file) - goto out_free_filename; - - while (!feof(file)) - if (symbol__parse_objdump_line(sym, map, file, privsize) < 0) - break; - - pclose(file); -out_free_filename: - if (free_filename) - free(filename); - return err; -} - -static void insert_source_line(struct rb_root *root, struct source_line *src_line) -{ - struct source_line *iter; - struct rb_node **p = &root->rb_node; - struct rb_node *parent = NULL; - - while (*p != NULL) { - parent = *p; - iter = rb_entry(parent, struct source_line, node); - - if (src_line->percent > iter->percent) - p = &(*p)->rb_left; - else - p = &(*p)->rb_right; - } - - rb_link_node(&src_line->node, parent, p); - rb_insert_color(&src_line->node, root); -} - -static void symbol__free_source_line(struct symbol *sym, int len) -{ - struct annotation *notes = symbol__annotation(sym); - struct source_line *src_line = notes->src->lines; - int i; - - for (i = 0; i < len; i++) - free(src_line[i].path); - - free(src_line); - notes->src->lines = NULL; -} - -/* Get the filename:line for the colored entries */ -static int symbol__get_source_line(struct symbol *sym, struct map *map, - int evidx, struct rb_root *root, int len, - const char *filename) -{ - u64 start; - int i; - char cmd[PATH_MAX * 2]; - struct source_line *src_line; - struct annotation *notes = symbol__annotation(sym); - struct sym_hist *h = annotation__histogram(notes, evidx); - - if (!h->sum) - return 0; - - src_line = notes->src->lines = calloc(len, sizeof(struct source_line)); - if (!notes->src->lines) - return -1; - - start = map->unmap_ip(map, sym->start); - - for (i = 0; i < len; i++) { - char *path = NULL; - size_t line_len; - u64 offset; - FILE *fp; - - src_line[i].percent = 100.0 * h->addr[i] / h->sum; - if (src_line[i].percent <= 0.5) - continue; - - offset = start + i; - sprintf(cmd, "addr2line -e %s %016" PRIx64, filename, offset); - fp = popen(cmd, "r"); - if (!fp) - continue; - - if (getline(&path, &line_len, fp) < 0 || !line_len) - goto next; - - src_line[i].path = malloc(sizeof(char) * line_len + 1); - if (!src_line[i].path) - goto next; - - strcpy(src_line[i].path, path); - insert_source_line(root, &src_line[i]); - - next: - pclose(fp); - } - - return 0; -} - -static void print_summary(struct rb_root *root, const char *filename) -{ - struct source_line *src_line; - struct rb_node *node; - - printf("\nSorted summary for file %s\n", filename); - printf("----------------------------------------------\n\n"); - - if (RB_EMPTY_ROOT(root)) { - printf(" Nothing higher than %1.1f%%\n", MIN_GREEN); - return; - } - - node = rb_first(root); - while (node) { - double percent; - const char *color; - char *path; - - src_line = rb_entry(node, struct source_line, node); - percent = src_line->percent; - color = get_percent_color(percent); - path = src_line->path; - - color_fprintf(stdout, color, " %7.2f %s", percent, path); - node = rb_next(node); - } -} - -static void symbol__annotate_hits(struct symbol *sym, int evidx) -{ - struct annotation *notes = symbol__annotation(sym); - struct sym_hist *h = annotation__histogram(notes, evidx); - u64 len = sym->end - sym->start, offset; - - for (offset = 0; offset < len; ++offset) - if (h->addr[offset] != 0) - printf("%*" PRIx64 ": %" PRIu64 "\n", BITS_PER_LONG / 2, - sym->start + offset, h->addr[offset]); - printf("%*s: %" PRIu64 "\n", BITS_PER_LONG / 2, "h->sum", h->sum); -} - -int symbol__annotate_printf(struct symbol *sym, struct map *map, int evidx, - bool full_paths, int min_pcnt, int max_lines, - int context) -{ - struct dso *dso = map->dso; - const char *filename = dso->long_name, *d_filename; - struct annotation *notes = symbol__annotation(sym); - struct objdump_line *pos, *queue = NULL; - int printed = 2, queue_len = 0; - int more = 0; - u64 len; - - if (full_paths) - d_filename = filename; - else - d_filename = basename(filename); - - len = sym->end - sym->start; - - printf(" Percent | Source code & Disassembly of %s\n", d_filename); - printf("------------------------------------------------\n"); - - if (verbose) - symbol__annotate_hits(sym, evidx); - - list_for_each_entry(pos, ¬es->src->source, node) { - if (context && queue == NULL) { - queue = pos; - queue_len = 0; - } - - switch (objdump_line__print(pos, sym, evidx, len, min_pcnt, - printed, max_lines, queue)) { - case 0: - ++printed; - if (context) { - printed += queue_len; - queue = NULL; - queue_len = 0; - } - break; - case 1: - /* filtered by max_lines */ - ++more; - break; - case -1: - default: - /* - * Filtered by min_pcnt or non IP lines when - * context != 0 - */ - if (!context) - break; - if (queue_len == context) - queue = list_entry(queue->node.next, typeof(*queue), node); - else - ++queue_len; - break; - } - } - - return more; -} - -void symbol__annotate_zero_histogram(struct symbol *sym, int evidx) -{ - struct annotation *notes = symbol__annotation(sym); - struct sym_hist *h = annotation__histogram(notes, evidx); - - memset(h, 0, notes->src->sizeof_sym_hist); -} - -void symbol__annotate_decay_histogram(struct symbol *sym, int evidx) -{ - struct annotation *notes = symbol__annotation(sym); - struct sym_hist *h = annotation__histogram(notes, evidx); - struct objdump_line *pos; - - h->sum = 0; - - list_for_each_entry(pos, ¬es->src->source, node) { - if (pos->offset != -1) { - h->addr[pos->offset] = h->addr[pos->offset] * 7 / 8; - h->sum += h->addr[pos->offset]; - } - } -} - -void objdump_line_list__purge(struct list_head *head) -{ - struct objdump_line *pos, *n; - - list_for_each_entry_safe(pos, n, head, node) { - list_del(&pos->node); - objdump_line__free(pos); - } -} - -int symbol__tty_annotate(struct symbol *sym, struct map *map, int evidx, - bool print_lines, bool full_paths, int min_pcnt, - int max_lines) -{ - struct dso *dso = map->dso; - const char *filename = dso->long_name; - struct rb_root source_line = RB_ROOT; - u64 len; - - if (symbol__annotate(sym, map, 0) < 0) - return -1; - - len = sym->end - sym->start; - - if (print_lines) { - symbol__get_source_line(sym, map, evidx, &source_line, - len, filename); - print_summary(&source_line, filename); - } - - symbol__annotate_printf(sym, map, evidx, full_paths, - min_pcnt, max_lines, 0); - if (print_lines) - symbol__free_source_line(sym, len); - - objdump_line_list__purge(&symbol__annotation(sym)->src->source); - - return 0; -} diff --git a/trunk/tools/perf/util/annotate.h b/trunk/tools/perf/util/annotate.h deleted file mode 100644 index e848803fcd48..000000000000 --- a/trunk/tools/perf/util/annotate.h +++ /dev/null @@ -1,101 +0,0 @@ -#ifndef __PERF_ANNOTATE_H -#define __PERF_ANNOTATE_H - -#include -#include "types.h" -#include "symbol.h" -#include -#include - -struct objdump_line { - struct list_head node; - s64 offset; - char *line; -}; - -void objdump_line__free(struct objdump_line *self); -struct objdump_line *objdump__get_next_ip_line(struct list_head *head, - struct objdump_line *pos); - -struct sym_hist { - u64 sum; - u64 addr[0]; -}; - -struct source_line { - struct rb_node node; - double percent; - char *path; -}; - -/** struct annotated_source - symbols with hits have this attached as in sannotation - * - * @histogram: Array of addr hit histograms per event being monitored - * @lines: If 'print_lines' is specified, per source code line percentages - * @source: source parsed from objdump -dS - * - * lines is allocated, percentages calculated and all sorted by percentage - * when the annotation is about to be presented, so the percentages are for - * one of the entries in the histogram array, i.e. for the event/counter being - * presented. It is deallocated right after symbol__{tui,tty,etc}_annotate - * returns. - */ -struct annotated_source { - struct list_head source; - struct source_line *lines; - int nr_histograms; - int sizeof_sym_hist; - struct sym_hist histograms[0]; -}; - -struct annotation { - pthread_mutex_t lock; - struct annotated_source *src; -}; - -struct sannotation { - struct annotation annotation; - struct symbol symbol; -}; - -static inline struct sym_hist *annotation__histogram(struct annotation *notes, int idx) -{ - return (((void *)¬es->src->histograms) + - (notes->src->sizeof_sym_hist * idx)); -} - -static inline struct annotation *symbol__annotation(struct symbol *sym) -{ - struct sannotation *a = container_of(sym, struct sannotation, symbol); - return &a->annotation; -} - -int symbol__inc_addr_samples(struct symbol *sym, struct map *map, - int evidx, u64 addr); -int symbol__alloc_hist(struct symbol *sym, int nevents); -void symbol__annotate_zero_histograms(struct symbol *sym); - -int symbol__annotate(struct symbol *sym, struct map *map, size_t privsize); -int symbol__annotate_init(struct map *map __used, struct symbol *sym); -int symbol__annotate_printf(struct symbol *sym, struct map *map, int evidx, - bool full_paths, int min_pcnt, int max_lines, - int context); -void symbol__annotate_zero_histogram(struct symbol *sym, int evidx); -void symbol__annotate_decay_histogram(struct symbol *sym, int evidx); -void objdump_line_list__purge(struct list_head *head); - -int symbol__tty_annotate(struct symbol *sym, struct map *map, int evidx, - bool print_lines, bool full_paths, int min_pcnt, - int max_lines); - -#ifdef NO_NEWT_SUPPORT -static inline int symbol__tui_annotate(struct symbol *sym __used, - struct map *map __used, int evidx __used) -{ - return 0; -} -#else -int symbol__tui_annotate(struct symbol *sym, struct map *map, int evidx); -#endif - -#endif /* __PERF_ANNOTATE_H */ diff --git a/trunk/tools/perf/util/build-id.c b/trunk/tools/perf/util/build-id.c index 31f934af9861..deffb8c96071 100644 --- a/trunk/tools/perf/util/build-id.c +++ b/trunk/tools/perf/util/build-id.c @@ -14,8 +14,8 @@ #include #include "debug.h" -static int build_id__mark_dso_hit(union perf_event *event, - struct perf_sample *sample __used, +static int build_id__mark_dso_hit(event_t *event, + struct sample_data *sample __used, struct perf_session *session) { struct addr_location al; @@ -37,14 +37,13 @@ static int build_id__mark_dso_hit(union perf_event *event, return 0; } -static int perf_event__exit_del_thread(union perf_event *event, - struct perf_sample *sample __used, - struct perf_session *session) +static int event__exit_del_thread(event_t *self, struct sample_data *sample __used, + struct perf_session *session) { - struct thread *thread = perf_session__findnew(session, event->fork.tid); + struct thread *thread = perf_session__findnew(session, self->fork.tid); - dump_printf("(%d:%d):(%d:%d)\n", event->fork.pid, event->fork.tid, - event->fork.ppid, event->fork.ptid); + dump_printf("(%d:%d):(%d:%d)\n", self->fork.pid, self->fork.tid, + self->fork.ppid, self->fork.ptid); if (thread) { rb_erase(&thread->rb_node, &session->threads); @@ -57,9 +56,9 @@ static int perf_event__exit_del_thread(union perf_event *event, struct perf_event_ops build_id__mark_dso_hit_ops = { .sample = build_id__mark_dso_hit, - .mmap = perf_event__process_mmap, - .fork = perf_event__process_task, - .exit = perf_event__exit_del_thread, + .mmap = event__process_mmap, + .fork = event__process_task, + .exit = event__exit_del_thread, }; char *dso__build_id_filename(struct dso *self, char *bf, size_t size) diff --git a/trunk/tools/perf/util/cache.h b/trunk/tools/perf/util/cache.h index fc5e5a09d5b9..a7729797fd96 100644 --- a/trunk/tools/perf/util/cache.h +++ b/trunk/tools/perf/util/cache.h @@ -34,14 +34,13 @@ extern int pager_use_color; extern int use_browser; #ifdef NO_NEWT_SUPPORT -static inline void setup_browser(bool fallback_to_pager) +static inline void setup_browser(void) { - if (fallback_to_pager) - setup_pager(); + setup_pager(); } static inline void exit_browser(bool wait_for_ok __used) {} #else -void setup_browser(bool fallback_to_pager); +void setup_browser(void); void exit_browser(bool wait_for_ok); #endif diff --git a/trunk/tools/perf/util/callchain.c b/trunk/tools/perf/util/callchain.c index 9f7106a8d9a4..e12d539417b2 100644 --- a/trunk/tools/perf/util/callchain.c +++ b/trunk/tools/perf/util/callchain.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2009-2011, Frederic Weisbecker + * Copyright (C) 2009-2010, Frederic Weisbecker * * Handle the callchains from the stream in an ad-hoc radix tree and then * sort them in an rbtree. @@ -18,8 +18,7 @@ #include "util.h" #include "callchain.h" -bool ip_callchain__valid(struct ip_callchain *chain, - const union perf_event *event) +bool ip_callchain__valid(struct ip_callchain *chain, const event_t *event) { unsigned int chain_size = event->header.size; chain_size -= (unsigned long)&event->ip.__more_data - (unsigned long)event; @@ -27,10 +26,10 @@ bool ip_callchain__valid(struct ip_callchain *chain, } #define chain_for_each_child(child, parent) \ - list_for_each_entry(child, &parent->children, siblings) + list_for_each_entry(child, &parent->children, brothers) #define chain_for_each_child_safe(child, next, parent) \ - list_for_each_entry_safe(child, next, &parent->children, siblings) + list_for_each_entry_safe(child, next, &parent->children, brothers) static void rb_insert_callchain(struct rb_root *root, struct callchain_node *chain, @@ -39,14 +38,14 @@ rb_insert_callchain(struct rb_root *root, struct callchain_node *chain, struct rb_node **p = &root->rb_node; struct rb_node *parent = NULL; struct callchain_node *rnode; - u64 chain_cumul = callchain_cumul_hits(chain); + u64 chain_cumul = cumul_hits(chain); while (*p) { u64 rnode_cumul; parent = *p; rnode = rb_entry(parent, struct callchain_node, rb_node); - rnode_cumul = callchain_cumul_hits(rnode); + rnode_cumul = cumul_hits(rnode); switch (mode) { case CHAIN_FLAT: @@ -105,7 +104,7 @@ static void __sort_chain_graph_abs(struct callchain_node *node, chain_for_each_child(child, node) { __sort_chain_graph_abs(child, min_hit); - if (callchain_cumul_hits(child) >= min_hit) + if (cumul_hits(child) >= min_hit) rb_insert_callchain(&node->rb_root, child, CHAIN_GRAPH_ABS); } @@ -130,7 +129,7 @@ static void __sort_chain_graph_rel(struct callchain_node *node, chain_for_each_child(child, node) { __sort_chain_graph_rel(child, min_percent); - if (callchain_cumul_hits(child) >= min_hit) + if (cumul_hits(child) >= min_hit) rb_insert_callchain(&node->rb_root, child, CHAIN_GRAPH_REL); } @@ -144,7 +143,7 @@ sort_chain_graph_rel(struct rb_root *rb_root, struct callchain_root *chain_root, rb_root->rb_node = chain_root->node.rb_root.rb_node; } -int callchain_register_param(struct callchain_param *param) +int register_callchain_param(struct callchain_param *param) { switch (param->mode) { case CHAIN_GRAPH_ABS: @@ -190,27 +189,32 @@ create_child(struct callchain_node *parent, bool inherit_children) chain_for_each_child(next, new) next->parent = new; } - list_add_tail(&new->siblings, &parent->children); + list_add_tail(&new->brothers, &parent->children); return new; } +struct resolved_ip { + u64 ip; + struct map_symbol ms; +}; + +struct resolved_chain { + u64 nr; + struct resolved_ip ips[0]; +}; + + /* * Fill the node with callchain values */ static void -fill_node(struct callchain_node *node, struct callchain_cursor *cursor) +fill_node(struct callchain_node *node, struct resolved_chain *chain, int start) { - struct callchain_cursor_node *cursor_node; - - node->val_nr = cursor->nr - cursor->pos; - if (!node->val_nr) - pr_warning("Warning: empty node in callchain tree\n"); + unsigned int i; - cursor_node = callchain_cursor_current(cursor); - - while (cursor_node) { + for (i = start; i < chain->nr; i++) { struct callchain_list *call; call = zalloc(sizeof(*call)); @@ -218,25 +222,23 @@ fill_node(struct callchain_node *node, struct callchain_cursor *cursor) perror("not enough memory for the code path tree"); return; } - call->ip = cursor_node->ip; - call->ms.sym = cursor_node->sym; - call->ms.map = cursor_node->map; + call->ip = chain->ips[i].ip; + call->ms = chain->ips[i].ms; list_add_tail(&call->list, &node->val); - - callchain_cursor_advance(cursor); - cursor_node = callchain_cursor_current(cursor); } + node->val_nr = chain->nr - start; + if (!node->val_nr) + pr_warning("Warning: empty node in callchain tree\n"); } static void -add_child(struct callchain_node *parent, - struct callchain_cursor *cursor, - u64 period) +add_child(struct callchain_node *parent, struct resolved_chain *chain, + int start, u64 period) { struct callchain_node *new; new = create_child(parent, false); - fill_node(new, cursor); + fill_node(new, chain, start); new->children_hit = 0; new->hit = period; @@ -248,10 +250,9 @@ add_child(struct callchain_node *parent, * Then create another child to host the given callchain of new branch */ static void -split_add_child(struct callchain_node *parent, - struct callchain_cursor *cursor, - struct callchain_list *to_split, - u64 idx_parents, u64 idx_local, u64 period) +split_add_child(struct callchain_node *parent, struct resolved_chain *chain, + struct callchain_list *to_split, int idx_parents, int idx_local, + u64 period) { struct callchain_node *new; struct list_head *old_tail; @@ -271,14 +272,14 @@ split_add_child(struct callchain_node *parent, /* split the hits */ new->hit = parent->hit; new->children_hit = parent->children_hit; - parent->children_hit = callchain_cumul_hits(new); + parent->children_hit = cumul_hits(new); new->val_nr = parent->val_nr - idx_local; parent->val_nr = idx_local; /* create a new child for the new branch if any */ - if (idx_total < cursor->nr) { + if (idx_total < chain->nr) { parent->hit = 0; - add_child(parent, cursor, period); + add_child(parent, chain, idx_total, period); parent->children_hit += period; } else { parent->hit = period; @@ -286,41 +287,36 @@ split_add_child(struct callchain_node *parent, } static int -append_chain(struct callchain_node *root, - struct callchain_cursor *cursor, - u64 period); +append_chain(struct callchain_node *root, struct resolved_chain *chain, + unsigned int start, u64 period); static void -append_chain_children(struct callchain_node *root, - struct callchain_cursor *cursor, - u64 period) +append_chain_children(struct callchain_node *root, struct resolved_chain *chain, + unsigned int start, u64 period) { struct callchain_node *rnode; /* lookup in childrens */ chain_for_each_child(rnode, root) { - unsigned int ret = append_chain(rnode, cursor, period); + unsigned int ret = append_chain(rnode, chain, start, period); if (!ret) goto inc_children_hit; } /* nothing in children, add to the current node */ - add_child(root, cursor, period); + add_child(root, chain, start, period); inc_children_hit: root->children_hit += period; } static int -append_chain(struct callchain_node *root, - struct callchain_cursor *cursor, - u64 period) +append_chain(struct callchain_node *root, struct resolved_chain *chain, + unsigned int start, u64 period) { - struct callchain_cursor_node *curr_snap = cursor->curr; struct callchain_list *cnode; - u64 start = cursor->pos; + unsigned int i = start; bool found = false; - u64 matches; /* * Lookup in the current node @@ -328,134 +324,141 @@ append_chain(struct callchain_node *root, * anywhere inside a function. */ list_for_each_entry(cnode, &root->val, list) { - struct callchain_cursor_node *node; struct symbol *sym; - node = callchain_cursor_current(cursor); - if (!node) + if (i == chain->nr) break; - sym = node->sym; + sym = chain->ips[i].ms.sym; if (cnode->ms.sym && sym) { if (cnode->ms.sym->start != sym->start) break; - } else if (cnode->ip != node->ip) + } else if (cnode->ip != chain->ips[i].ip) break; if (!found) found = true; - - callchain_cursor_advance(cursor); + i++; } /* matches not, relay on the parent */ - if (!found) { - cursor->curr = curr_snap; - cursor->pos = start; + if (!found) return -1; - } - - matches = cursor->pos - start; /* we match only a part of the node. Split it and add the new chain */ - if (matches < root->val_nr) { - split_add_child(root, cursor, cnode, start, matches, period); + if (i - start < root->val_nr) { + split_add_child(root, chain, cnode, start, i - start, period); return 0; } /* we match 100% of the path, increment the hit */ - if (matches == root->val_nr && cursor->pos == cursor->nr) { + if (i - start == root->val_nr && i == chain->nr) { root->hit += period; return 0; } /* We match the node and still have a part remaining */ - append_chain_children(root, cursor, period); + append_chain_children(root, chain, i, period); return 0; } -int callchain_append(struct callchain_root *root, - struct callchain_cursor *cursor, - u64 period) +static void filter_context(struct ip_callchain *old, struct resolved_chain *new, + struct map_symbol *syms) +{ + int i, j = 0; + + for (i = 0; i < (int)old->nr; i++) { + if (old->ips[i] >= PERF_CONTEXT_MAX) + continue; + + new->ips[j].ip = old->ips[i]; + new->ips[j].ms = syms[i]; + j++; + } + + new->nr = j; +} + + +int callchain_append(struct callchain_root *root, struct ip_callchain *chain, + struct map_symbol *syms, u64 period) { - if (!cursor->nr) + struct resolved_chain *filtered; + + if (!chain->nr) return 0; - callchain_cursor_commit(cursor); + filtered = zalloc(sizeof(*filtered) + + chain->nr * sizeof(struct resolved_ip)); + if (!filtered) + return -ENOMEM; + + filter_context(chain, filtered, syms); + + if (!filtered->nr) + goto end; - append_chain_children(&root->node, cursor, period); + append_chain_children(&root->node, filtered, 0, period); - if (cursor->nr > root->max_depth) - root->max_depth = cursor->nr; + if (filtered->nr > root->max_depth) + root->max_depth = filtered->nr; +end: + free(filtered); return 0; } static int -merge_chain_branch(struct callchain_cursor *cursor, - struct callchain_node *dst, struct callchain_node *src) +merge_chain_branch(struct callchain_node *dst, struct callchain_node *src, + struct resolved_chain *chain) { - struct callchain_cursor_node **old_last = cursor->last; struct callchain_node *child, *next_child; struct callchain_list *list, *next_list; - int old_pos = cursor->nr; + int old_pos = chain->nr; int err = 0; list_for_each_entry_safe(list, next_list, &src->val, list) { - callchain_cursor_append(cursor, list->ip, - list->ms.map, list->ms.sym); + chain->ips[chain->nr].ip = list->ip; + chain->ips[chain->nr].ms = list->ms; + chain->nr++; list_del(&list->list); free(list); } - if (src->hit) { - callchain_cursor_commit(cursor); - append_chain_children(dst, cursor, src->hit); - } + if (src->hit) + append_chain_children(dst, chain, 0, src->hit); chain_for_each_child_safe(child, next_child, src) { - err = merge_chain_branch(cursor, dst, child); + err = merge_chain_branch(dst, child, chain); if (err) break; - list_del(&child->siblings); + list_del(&child->brothers); free(child); } - cursor->nr = old_pos; - cursor->last = old_last; + chain->nr = old_pos; return err; } -int callchain_merge(struct callchain_cursor *cursor, - struct callchain_root *dst, struct callchain_root *src) -{ - return merge_chain_branch(cursor, &dst->node, &src->node); -} - -int callchain_cursor_append(struct callchain_cursor *cursor, - u64 ip, struct map *map, struct symbol *sym) +int callchain_merge(struct callchain_root *dst, struct callchain_root *src) { - struct callchain_cursor_node *node = *cursor->last; + struct resolved_chain *chain; + int err; - if (!node) { - node = calloc(sizeof(*node), 1); - if (!node) - return -ENOMEM; + chain = malloc(sizeof(*chain) + + src->max_depth * sizeof(struct resolved_ip)); + if (!chain) + return -ENOMEM; - *cursor->last = node; - } - - node->ip = ip; - node->map = map; - node->sym = sym; + chain->nr = 0; - cursor->nr++; + err = merge_chain_branch(&dst->node, &src->node, chain); - cursor->last = &node->next; + free(chain); - return 0; + return err; } diff --git a/trunk/tools/perf/util/callchain.h b/trunk/tools/perf/util/callchain.h index 1a79df9f739f..c15fb8c24ad2 100644 --- a/trunk/tools/perf/util/callchain.h +++ b/trunk/tools/perf/util/callchain.h @@ -16,7 +16,7 @@ enum chain_mode { struct callchain_node { struct callchain_node *parent; - struct list_head siblings; + struct list_head brothers; struct list_head children; struct list_head val; struct rb_node rb_node; /* to sort nodes in an rbtree */ @@ -49,30 +49,9 @@ struct callchain_list { struct list_head list; }; -/* - * A callchain cursor is a single linked list that - * let one feed a callchain progressively. - * It keeps persitent allocated entries to minimize - * allocations. - */ -struct callchain_cursor_node { - u64 ip; - struct map *map; - struct symbol *sym; - struct callchain_cursor_node *next; -}; - -struct callchain_cursor { - u64 nr; - struct callchain_cursor_node *first; - struct callchain_cursor_node **last; - u64 pos; - struct callchain_cursor_node *curr; -}; - static inline void callchain_init(struct callchain_root *root) { - INIT_LIST_HEAD(&root->node.siblings); + INIT_LIST_HEAD(&root->node.brothers); INIT_LIST_HEAD(&root->node.children); INIT_LIST_HEAD(&root->node.val); @@ -82,54 +61,15 @@ static inline void callchain_init(struct callchain_root *root) root->max_depth = 0; } -static inline u64 callchain_cumul_hits(struct callchain_node *node) +static inline u64 cumul_hits(struct callchain_node *node) { return node->hit + node->children_hit; } -int callchain_register_param(struct callchain_param *param); -int callchain_append(struct callchain_root *root, - struct callchain_cursor *cursor, - u64 period); - -int callchain_merge(struct callchain_cursor *cursor, - struct callchain_root *dst, struct callchain_root *src); - -bool ip_callchain__valid(struct ip_callchain *chain, - const union perf_event *event); -/* - * Initialize a cursor before adding entries inside, but keep - * the previously allocated entries as a cache. - */ -static inline void callchain_cursor_reset(struct callchain_cursor *cursor) -{ - cursor->nr = 0; - cursor->last = &cursor->first; -} - -int callchain_cursor_append(struct callchain_cursor *cursor, u64 ip, - struct map *map, struct symbol *sym); +int register_callchain_param(struct callchain_param *param); +int callchain_append(struct callchain_root *root, struct ip_callchain *chain, + struct map_symbol *syms, u64 period); +int callchain_merge(struct callchain_root *dst, struct callchain_root *src); -/* Close a cursor writing session. Initialize for the reader */ -static inline void callchain_cursor_commit(struct callchain_cursor *cursor) -{ - cursor->curr = cursor->first; - cursor->pos = 0; -} - -/* Cursor reading iteration helpers */ -static inline struct callchain_cursor_node * -callchain_cursor_current(struct callchain_cursor *cursor) -{ - if (cursor->pos == cursor->nr) - return NULL; - - return cursor->curr; -} - -static inline void callchain_cursor_advance(struct callchain_cursor *cursor) -{ - cursor->curr = cursor->curr->next; - cursor->pos++; -} +bool ip_callchain__valid(struct ip_callchain *chain, const event_t *event); #endif /* __PERF_CALLCHAIN_H */ diff --git a/trunk/tools/perf/util/cpumap.c b/trunk/tools/perf/util/cpumap.c index 6893eec693ab..3ccaa1043383 100644 --- a/trunk/tools/perf/util/cpumap.c +++ b/trunk/tools/perf/util/cpumap.c @@ -177,8 +177,3 @@ struct cpu_map *cpu_map__dummy_new(void) return cpus; } - -void cpu_map__delete(struct cpu_map *map) -{ - free(map); -} diff --git a/trunk/tools/perf/util/cpumap.h b/trunk/tools/perf/util/cpumap.h index 072c0a374794..f7a4f42f6307 100644 --- a/trunk/tools/perf/util/cpumap.h +++ b/trunk/tools/perf/util/cpumap.h @@ -8,6 +8,6 @@ struct cpu_map { struct cpu_map *cpu_map__new(const char *cpu_list); struct cpu_map *cpu_map__dummy_new(void); -void cpu_map__delete(struct cpu_map *map); +void *cpu_map__delete(struct cpu_map *map); #endif /* __PERF_CPUMAP_H */ diff --git a/trunk/tools/perf/util/debug.c b/trunk/tools/perf/util/debug.c index d4536a9e0d8c..01bbe8ecec3f 100644 --- a/trunk/tools/perf/util/debug.c +++ b/trunk/tools/perf/util/debug.c @@ -57,7 +57,7 @@ void ui__warning(const char *format, ...) } #endif -void trace_event(union perf_event *event) +void trace_event(event_t *event) { unsigned char *raw_event = (void *)event; const char *color = PERF_COLOR_BLUE; diff --git a/trunk/tools/perf/util/debug.h b/trunk/tools/perf/util/debug.h index 93516cf4682c..ca35fd66b5df 100644 --- a/trunk/tools/perf/util/debug.h +++ b/trunk/tools/perf/util/debug.h @@ -9,7 +9,7 @@ extern int verbose; extern bool quiet, dump_trace; int dump_printf(const char *fmt, ...) __attribute__((format(printf, 1, 2))); -void trace_event(union perf_event *event); +void trace_event(event_t *event); struct ui_progress; diff --git a/trunk/tools/perf/util/event.c b/trunk/tools/perf/util/event.c index fbf5754c8866..1478ab4ee222 100644 --- a/trunk/tools/perf/util/event.c +++ b/trunk/tools/perf/util/event.c @@ -6,9 +6,8 @@ #include "string.h" #include "strlist.h" #include "thread.h" -#include "thread_map.h" -static const char *perf_event__names[] = { +static const char *event__name[] = { [0] = "TOTAL", [PERF_RECORD_MMAP] = "MMAP", [PERF_RECORD_LOST] = "LOST", @@ -26,16 +25,16 @@ static const char *perf_event__names[] = { [PERF_RECORD_FINISHED_ROUND] = "FINISHED_ROUND", }; -const char *perf_event__name(unsigned int id) +const char *event__get_event_name(unsigned int id) { - if (id >= ARRAY_SIZE(perf_event__names)) + if (id >= ARRAY_SIZE(event__name)) return "INVALID"; - if (!perf_event__names[id]) + if (!event__name[id]) return "UNKNOWN"; - return perf_event__names[id]; + return event__name[id]; } -static struct perf_sample synth_sample = { +static struct sample_data synth_sample = { .pid = -1, .tid = -1, .time = -1, @@ -44,9 +43,9 @@ static struct perf_sample synth_sample = { .period = 1, }; -static pid_t perf_event__synthesize_comm(union perf_event *event, pid_t pid, - int full, perf_event__handler_t process, - struct perf_session *session) +static pid_t event__synthesize_comm(event_t *event, pid_t pid, int full, + event__handler_t process, + struct perf_session *session) { char filename[PATH_MAX]; char bf[BUFSIZ]; @@ -127,10 +126,9 @@ static pid_t perf_event__synthesize_comm(union perf_event *event, pid_t pid, return tgid; } -static int perf_event__synthesize_mmap_events(union perf_event *event, - pid_t pid, pid_t tgid, - perf_event__handler_t process, - struct perf_session *session) +static int event__synthesize_mmap_events(event_t *event, pid_t pid, pid_t tgid, + event__handler_t process, + struct perf_session *session) { char filename[PATH_MAX]; FILE *fp; @@ -201,14 +199,14 @@ static int perf_event__synthesize_mmap_events(union perf_event *event, return 0; } -int perf_event__synthesize_modules(perf_event__handler_t process, - struct perf_session *session, - struct machine *machine) +int event__synthesize_modules(event__handler_t process, + struct perf_session *session, + struct machine *machine) { struct rb_node *nd; struct map_groups *kmaps = &machine->kmaps; - union perf_event *event = zalloc((sizeof(event->mmap) + - session->id_hdr_size)); + event_t *event = zalloc(sizeof(event->mmap) + session->id_hdr_size); + if (event == NULL) { pr_debug("Not enough memory synthesizing mmap event " "for kernel modules\n"); @@ -253,25 +251,23 @@ int perf_event__synthesize_modules(perf_event__handler_t process, return 0; } -static int __event__synthesize_thread(union perf_event *comm_event, - union perf_event *mmap_event, - pid_t pid, perf_event__handler_t process, +static int __event__synthesize_thread(event_t *comm_event, event_t *mmap_event, + pid_t pid, event__handler_t process, struct perf_session *session) { - pid_t tgid = perf_event__synthesize_comm(comm_event, pid, 1, process, + pid_t tgid = event__synthesize_comm(comm_event, pid, 1, process, session); if (tgid == -1) return -1; - return perf_event__synthesize_mmap_events(mmap_event, pid, tgid, + return event__synthesize_mmap_events(mmap_event, pid, tgid, process, session); } -int perf_event__synthesize_thread_map(struct thread_map *threads, - perf_event__handler_t process, - struct perf_session *session) +int event__synthesize_thread(pid_t pid, event__handler_t process, + struct perf_session *session) { - union perf_event *comm_event, *mmap_event; - int err = -1, thread; + event_t *comm_event, *mmap_event; + int err = -1; comm_event = malloc(sizeof(comm_event->comm) + session->id_hdr_size); if (comm_event == NULL) @@ -281,15 +277,8 @@ int perf_event__synthesize_thread_map(struct thread_map *threads, if (mmap_event == NULL) goto out_free_comm; - err = 0; - for (thread = 0; thread < threads->nr; ++thread) { - if (__event__synthesize_thread(comm_event, mmap_event, - threads->map[thread], - process, session)) { - err = -1; - break; - } - } + err = __event__synthesize_thread(comm_event, mmap_event, pid, + process, session); free(mmap_event); out_free_comm: free(comm_event); @@ -297,12 +286,12 @@ int perf_event__synthesize_thread_map(struct thread_map *threads, return err; } -int perf_event__synthesize_threads(perf_event__handler_t process, - struct perf_session *session) +int event__synthesize_threads(event__handler_t process, + struct perf_session *session) { DIR *proc; struct dirent dirent, *next; - union perf_event *comm_event, *mmap_event; + event_t *comm_event, *mmap_event; int err = -1; comm_event = malloc(sizeof(comm_event->comm) + session->id_hdr_size); @@ -360,10 +349,10 @@ static int find_symbol_cb(void *arg, const char *name, char type, return 1; } -int perf_event__synthesize_kernel_mmap(perf_event__handler_t process, - struct perf_session *session, - struct machine *machine, - const char *symbol_name) +int event__synthesize_kernel_mmap(event__handler_t process, + struct perf_session *session, + struct machine *machine, + const char *symbol_name) { size_t size; const char *filename, *mmap_name; @@ -377,8 +366,8 @@ int perf_event__synthesize_kernel_mmap(perf_event__handler_t process, * kernels. */ struct process_symbol_args args = { .name = symbol_name, }; - union perf_event *event = zalloc((sizeof(event->mmap) + - session->id_hdr_size)); + event_t *event = zalloc(sizeof(event->mmap) + session->id_hdr_size); + if (event == NULL) { pr_debug("Not enough memory synthesizing mmap event " "for kernel modules\n"); @@ -451,15 +440,14 @@ static int thread__set_comm_adjust(struct thread *self, const char *comm, return 0; } -int perf_event__process_comm(union perf_event *event, - struct perf_sample *sample __used, - struct perf_session *session) +int event__process_comm(event_t *self, struct sample_data *sample __used, + struct perf_session *session) { - struct thread *thread = perf_session__findnew(session, event->comm.tid); + struct thread *thread = perf_session__findnew(session, self->comm.tid); - dump_printf(": %s:%d\n", event->comm.comm, event->comm.tid); + dump_printf(": %s:%d\n", self->comm.comm, self->comm.tid); - if (thread == NULL || thread__set_comm_adjust(thread, event->comm.comm, + if (thread == NULL || thread__set_comm_adjust(thread, self->comm.comm, &session->hists)) { dump_printf("problem processing PERF_RECORD_COMM, skipping event.\n"); return -1; @@ -468,21 +456,19 @@ int perf_event__process_comm(union perf_event *event, return 0; } -int perf_event__process_lost(union perf_event *event, - struct perf_sample *sample __used, - struct perf_session *session) +int event__process_lost(event_t *self, struct sample_data *sample __used, + struct perf_session *session) { dump_printf(": id:%" PRIu64 ": lost:%" PRIu64 "\n", - event->lost.id, event->lost.lost); - session->hists.stats.total_lost += event->lost.lost; + self->lost.id, self->lost.lost); + session->hists.stats.total_lost += self->lost.lost; return 0; } -static void perf_event__set_kernel_mmap_len(union perf_event *event, - struct map **maps) +static void event_set_kernel_mmap_len(struct map **maps, event_t *self) { - maps[MAP__FUNCTION]->start = event->mmap.start; - maps[MAP__FUNCTION]->end = event->mmap.start + event->mmap.len; + maps[MAP__FUNCTION]->start = self->mmap.start; + maps[MAP__FUNCTION]->end = self->mmap.start + self->mmap.len; /* * Be a bit paranoid here, some perf.data file came with * a zero sized synthesized MMAP event for the kernel. @@ -491,8 +477,8 @@ static void perf_event__set_kernel_mmap_len(union perf_event *event, maps[MAP__FUNCTION]->end = ~0ULL; } -static int perf_event__process_kernel_mmap(union perf_event *event, - struct perf_session *session) +static int event__process_kernel_mmap(event_t *self, + struct perf_session *session) { struct map *map; char kmmap_prefix[PATH_MAX]; @@ -500,9 +486,9 @@ static int perf_event__process_kernel_mmap(union perf_event *event, enum dso_kernel_type kernel_type; bool is_kernel_mmap; - machine = perf_session__findnew_machine(session, event->mmap.pid); + machine = perf_session__findnew_machine(session, self->mmap.pid); if (!machine) { - pr_err("Can't find id %d's machine\n", event->mmap.pid); + pr_err("Can't find id %d's machine\n", self->mmap.pid); goto out_problem; } @@ -512,17 +498,17 @@ static int perf_event__process_kernel_mmap(union perf_event *event, else kernel_type = DSO_TYPE_GUEST_KERNEL; - is_kernel_mmap = memcmp(event->mmap.filename, + is_kernel_mmap = memcmp(self->mmap.filename, kmmap_prefix, strlen(kmmap_prefix)) == 0; - if (event->mmap.filename[0] == '/' || - (!is_kernel_mmap && event->mmap.filename[0] == '[')) { + if (self->mmap.filename[0] == '/' || + (!is_kernel_mmap && self->mmap.filename[0] == '[')) { char short_module_name[1024]; char *name, *dot; - if (event->mmap.filename[0] == '/') { - name = strrchr(event->mmap.filename, '/'); + if (self->mmap.filename[0] == '/') { + name = strrchr(self->mmap.filename, '/'); if (name == NULL) goto out_problem; @@ -534,10 +520,10 @@ static int perf_event__process_kernel_mmap(union perf_event *event, "[%.*s]", (int)(dot - name), name); strxfrchar(short_module_name, '-', '_'); } else - strcpy(short_module_name, event->mmap.filename); + strcpy(short_module_name, self->mmap.filename); - map = machine__new_module(machine, event->mmap.start, - event->mmap.filename); + map = machine__new_module(machine, self->mmap.start, + self->mmap.filename); if (map == NULL) goto out_problem; @@ -547,9 +533,9 @@ static int perf_event__process_kernel_mmap(union perf_event *event, map->dso->short_name = name; map->dso->sname_alloc = 1; - map->end = map->start + event->mmap.len; + map->end = map->start + self->mmap.len; } else if (is_kernel_mmap) { - const char *symbol_name = (event->mmap.filename + + const char *symbol_name = (self->mmap.filename + strlen(kmmap_prefix)); /* * Should be there already, from the build-id table in @@ -564,10 +550,10 @@ static int perf_event__process_kernel_mmap(union perf_event *event, if (__machine__create_kernel_maps(machine, kernel) < 0) goto out_problem; - perf_event__set_kernel_mmap_len(event, machine->vmlinux_maps); + event_set_kernel_mmap_len(machine->vmlinux_maps, self); perf_session__set_kallsyms_ref_reloc_sym(machine->vmlinux_maps, symbol_name, - event->mmap.pgoff); + self->mmap.pgoff); if (machine__is_default_guest(machine)) { /* * preload dso of guest kernel and modules @@ -581,23 +567,22 @@ static int perf_event__process_kernel_mmap(union perf_event *event, return -1; } -int perf_event__process_mmap(union perf_event *event, - struct perf_sample *sample __used, - struct perf_session *session) +int event__process_mmap(event_t *self, struct sample_data *sample __used, + struct perf_session *session) { struct machine *machine; struct thread *thread; struct map *map; - u8 cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK; + u8 cpumode = self->header.misc & PERF_RECORD_MISC_CPUMODE_MASK; int ret = 0; dump_printf(" %d/%d: [%#" PRIx64 "(%#" PRIx64 ") @ %#" PRIx64 "]: %s\n", - event->mmap.pid, event->mmap.tid, event->mmap.start, - event->mmap.len, event->mmap.pgoff, event->mmap.filename); + self->mmap.pid, self->mmap.tid, self->mmap.start, + self->mmap.len, self->mmap.pgoff, self->mmap.filename); if (cpumode == PERF_RECORD_MISC_GUEST_KERNEL || cpumode == PERF_RECORD_MISC_KERNEL) { - ret = perf_event__process_kernel_mmap(event, session); + ret = event__process_kernel_mmap(self, session); if (ret < 0) goto out_problem; return 0; @@ -606,12 +591,12 @@ int perf_event__process_mmap(union perf_event *event, machine = perf_session__find_host_machine(session); if (machine == NULL) goto out_problem; - thread = perf_session__findnew(session, event->mmap.pid); + thread = perf_session__findnew(session, self->mmap.pid); if (thread == NULL) goto out_problem; - map = map__new(&machine->user_dsos, event->mmap.start, - event->mmap.len, event->mmap.pgoff, - event->mmap.pid, event->mmap.filename, + map = map__new(&machine->user_dsos, self->mmap.start, + self->mmap.len, self->mmap.pgoff, + self->mmap.pid, self->mmap.filename, MAP__FUNCTION); if (map == NULL) goto out_problem; @@ -624,17 +609,16 @@ int perf_event__process_mmap(union perf_event *event, return 0; } -int perf_event__process_task(union perf_event *event, - struct perf_sample *sample __used, - struct perf_session *session) +int event__process_task(event_t *self, struct sample_data *sample __used, + struct perf_session *session) { - struct thread *thread = perf_session__findnew(session, event->fork.tid); - struct thread *parent = perf_session__findnew(session, event->fork.ptid); + struct thread *thread = perf_session__findnew(session, self->fork.tid); + struct thread *parent = perf_session__findnew(session, self->fork.ptid); - dump_printf("(%d:%d):(%d:%d)\n", event->fork.pid, event->fork.tid, - event->fork.ppid, event->fork.ptid); + dump_printf("(%d:%d):(%d:%d)\n", self->fork.pid, self->fork.tid, + self->fork.ppid, self->fork.ptid); - if (event->header.type == PERF_RECORD_EXIT) { + if (self->header.type == PERF_RECORD_EXIT) { perf_session__remove_thread(session, thread); return 0; } @@ -648,22 +632,20 @@ int perf_event__process_task(union perf_event *event, return 0; } -int perf_event__process(union perf_event *event, struct perf_sample *sample, - struct perf_session *session) +int event__process(event_t *event, struct sample_data *sample, + struct perf_session *session) { switch (event->header.type) { case PERF_RECORD_COMM: - perf_event__process_comm(event, sample, session); + event__process_comm(event, sample, session); break; case PERF_RECORD_MMAP: - perf_event__process_mmap(event, sample, session); + event__process_mmap(event, sample, session); break; case PERF_RECORD_FORK: case PERF_RECORD_EXIT: - perf_event__process_task(event, sample, session); + event__process_task(event, sample, session); break; - case PERF_RECORD_LOST: - perf_event__process_lost(event, sample, session); default: break; } @@ -772,14 +754,12 @@ static void dso__calc_col_width(struct dso *self, struct hists *hists) self->slen_calculated = 1; } -int perf_event__preprocess_sample(const union perf_event *event, - struct perf_session *session, - struct addr_location *al, - struct perf_sample *sample, - symbol_filter_t filter) +int event__preprocess_sample(const event_t *self, struct perf_session *session, + struct addr_location *al, struct sample_data *data, + symbol_filter_t filter) { - u8 cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK; - struct thread *thread = perf_session__findnew(session, event->ip.pid); + u8 cpumode = self->header.misc & PERF_RECORD_MISC_CPUMODE_MASK; + struct thread *thread = perf_session__findnew(session, self->ip.pid); if (thread == NULL) return -1; @@ -801,12 +781,12 @@ int perf_event__preprocess_sample(const union perf_event *event, machine__create_kernel_maps(&session->host_machine); thread__find_addr_map(thread, session, cpumode, MAP__FUNCTION, - event->ip.pid, event->ip.ip, al); + self->ip.pid, self->ip.ip, al); dump_printf(" ...... dso: %s\n", al->map ? al->map->dso->long_name : al->level == 'H' ? "[hypervisor]" : ""); al->sym = NULL; - al->cpu = sample->cpu; + al->cpu = data->cpu; if (al->map) { if (symbol_conf.dso_list && @@ -846,3 +826,128 @@ int perf_event__preprocess_sample(const union perf_event *event, al->filtered = true; return 0; } + +static int event__parse_id_sample(const event_t *event, + struct perf_session *session, + struct sample_data *sample) +{ + const u64 *array; + u64 type; + + sample->cpu = sample->pid = sample->tid = -1; + sample->stream_id = sample->id = sample->time = -1ULL; + + if (!session->sample_id_all) + return 0; + + array = event->sample.array; + array += ((event->header.size - + sizeof(event->header)) / sizeof(u64)) - 1; + type = session->sample_type; + + if (type & PERF_SAMPLE_CPU) { + u32 *p = (u32 *)array; + sample->cpu = *p; + array--; + } + + if (type & PERF_SAMPLE_STREAM_ID) { + sample->stream_id = *array; + array--; + } + + if (type & PERF_SAMPLE_ID) { + sample->id = *array; + array--; + } + + if (type & PERF_SAMPLE_TIME) { + sample->time = *array; + array--; + } + + if (type & PERF_SAMPLE_TID) { + u32 *p = (u32 *)array; + sample->pid = p[0]; + sample->tid = p[1]; + } + + return 0; +} + +int event__parse_sample(const event_t *event, struct perf_session *session, + struct sample_data *data) +{ + const u64 *array; + u64 type; + + if (event->header.type != PERF_RECORD_SAMPLE) + return event__parse_id_sample(event, session, data); + + array = event->sample.array; + type = session->sample_type; + + if (type & PERF_SAMPLE_IP) { + data->ip = event->ip.ip; + array++; + } + + if (type & PERF_SAMPLE_TID) { + u32 *p = (u32 *)array; + data->pid = p[0]; + data->tid = p[1]; + array++; + } + + if (type & PERF_SAMPLE_TIME) { + data->time = *array; + array++; + } + + if (type & PERF_SAMPLE_ADDR) { + data->addr = *array; + array++; + } + + data->id = -1ULL; + if (type & PERF_SAMPLE_ID) { + data->id = *array; + array++; + } + + if (type & PERF_SAMPLE_STREAM_ID) { + data->stream_id = *array; + array++; + } + + if (type & PERF_SAMPLE_CPU) { + u32 *p = (u32 *)array; + data->cpu = *p; + array++; + } else + data->cpu = -1; + + if (type & PERF_SAMPLE_PERIOD) { + data->period = *array; + array++; + } + + if (type & PERF_SAMPLE_READ) { + pr_debug("PERF_SAMPLE_READ is unsuported for now\n"); + return -1; + } + + if (type & PERF_SAMPLE_CALLCHAIN) { + data->callchain = (struct ip_callchain *)array; + array += 1 + data->callchain->nr; + } + + if (type & PERF_SAMPLE_RAW) { + u32 *p = (u32 *)array; + data->raw_size = *p; + p++; + data->raw_data = p; + } + + return 0; +} diff --git a/trunk/tools/perf/util/event.h b/trunk/tools/perf/util/event.h index 9c35170fb379..2b7e91902f10 100644 --- a/trunk/tools/perf/util/event.h +++ b/trunk/tools/perf/util/event.h @@ -61,7 +61,7 @@ struct sample_event { u64 array[]; }; -struct perf_sample { +struct sample_data { u64 ip; u32 pid, tid; u64 time; @@ -117,7 +117,7 @@ struct tracing_data_event { u32 size; }; -union perf_event { +typedef union event_union { struct perf_event_header header; struct ip_event ip; struct mmap_event mmap; @@ -130,54 +130,48 @@ union perf_event { struct event_type_event event_type; struct tracing_data_event tracing_data; struct build_id_event build_id; -}; +} event_t; -void perf_event__print_totals(void); +void event__print_totals(void); struct perf_session; -struct thread_map; -typedef int (*perf_event__handler_synth_t)(union perf_event *event, - struct perf_session *session); -typedef int (*perf_event__handler_t)(union perf_event *event, - struct perf_sample *sample, +typedef int (*event__handler_synth_t)(event_t *event, struct perf_session *session); +typedef int (*event__handler_t)(event_t *event, struct sample_data *sample, + struct perf_session *session); -int perf_event__synthesize_thread_map(struct thread_map *threads, - perf_event__handler_t process, - struct perf_session *session); -int perf_event__synthesize_threads(perf_event__handler_t process, - struct perf_session *session); -int perf_event__synthesize_kernel_mmap(perf_event__handler_t process, - struct perf_session *session, - struct machine *machine, - const char *symbol_name); - -int perf_event__synthesize_modules(perf_event__handler_t process, - struct perf_session *session, - struct machine *machine); - -int perf_event__process_comm(union perf_event *event, struct perf_sample *sample, - struct perf_session *session); -int perf_event__process_lost(union perf_event *event, struct perf_sample *sample, - struct perf_session *session); -int perf_event__process_mmap(union perf_event *event, struct perf_sample *sample, - struct perf_session *session); -int perf_event__process_task(union perf_event *event, struct perf_sample *sample, +int event__synthesize_thread(pid_t pid, event__handler_t process, struct perf_session *session); -int perf_event__process(union perf_event *event, struct perf_sample *sample, +int event__synthesize_threads(event__handler_t process, + struct perf_session *session); +int event__synthesize_kernel_mmap(event__handler_t process, + struct perf_session *session, + struct machine *machine, + const char *symbol_name); + +int event__synthesize_modules(event__handler_t process, + struct perf_session *session, + struct machine *machine); + +int event__process_comm(event_t *self, struct sample_data *sample, struct perf_session *session); +int event__process_lost(event_t *self, struct sample_data *sample, + struct perf_session *session); +int event__process_mmap(event_t *self, struct sample_data *sample, + struct perf_session *session); +int event__process_task(event_t *self, struct sample_data *sample, + struct perf_session *session); +int event__process(event_t *event, struct sample_data *sample, + struct perf_session *session); struct addr_location; -int perf_event__preprocess_sample(const union perf_event *self, - struct perf_session *session, - struct addr_location *al, - struct perf_sample *sample, - symbol_filter_t filter); - -const char *perf_event__name(unsigned int id); +int event__preprocess_sample(const event_t *self, struct perf_session *session, + struct addr_location *al, struct sample_data *data, + symbol_filter_t filter); +int event__parse_sample(const event_t *event, struct perf_session *session, + struct sample_data *sample); -int perf_event__parse_sample(const union perf_event *event, u64 type, - bool sample_id_all, struct perf_sample *sample); +const char *event__get_event_name(unsigned int id); #endif /* __PERF_RECORD_H */ diff --git a/trunk/tools/perf/util/evlist.c b/trunk/tools/perf/util/evlist.c deleted file mode 100644 index 95b21fece2ce..000000000000 --- a/trunk/tools/perf/util/evlist.c +++ /dev/null @@ -1,350 +0,0 @@ -/* - * Copyright (C) 2011, Red Hat Inc, Arnaldo Carvalho de Melo - * - * Parts came from builtin-{top,stat,record}.c, see those files for further - * copyright notes. - * - * Released under the GPL v2. (and only v2, not any later version) - */ -#include -#include "cpumap.h" -#include "thread_map.h" -#include "evlist.h" -#include "evsel.h" -#include "util.h" - -#include - -#include -#include - -#define FD(e, x, y) (*(int *)xyarray__entry(e->fd, x, y)) -#define SID(e, x, y) xyarray__entry(e->id, x, y) - -void perf_evlist__init(struct perf_evlist *evlist, struct cpu_map *cpus, - struct thread_map *threads) -{ - int i; - - for (i = 0; i < PERF_EVLIST__HLIST_SIZE; ++i) - INIT_HLIST_HEAD(&evlist->heads[i]); - INIT_LIST_HEAD(&evlist->entries); - perf_evlist__set_maps(evlist, cpus, threads); -} - -struct perf_evlist *perf_evlist__new(struct cpu_map *cpus, - struct thread_map *threads) -{ - struct perf_evlist *evlist = zalloc(sizeof(*evlist)); - - if (evlist != NULL) - perf_evlist__init(evlist, cpus, threads); - - return evlist; -} - -static void perf_evlist__purge(struct perf_evlist *evlist) -{ - struct perf_evsel *pos, *n; - - list_for_each_entry_safe(pos, n, &evlist->entries, node) { - list_del_init(&pos->node); - perf_evsel__delete(pos); - } - - evlist->nr_entries = 0; -} - -void perf_evlist__exit(struct perf_evlist *evlist) -{ - free(evlist->mmap); - free(evlist->pollfd); - evlist->mmap = NULL; - evlist->pollfd = NULL; -} - -void perf_evlist__delete(struct perf_evlist *evlist) -{ - perf_evlist__purge(evlist); - perf_evlist__exit(evlist); - free(evlist); -} - -void perf_evlist__add(struct perf_evlist *evlist, struct perf_evsel *entry) -{ - list_add_tail(&entry->node, &evlist->entries); - ++evlist->nr_entries; -} - -int perf_evlist__add_default(struct perf_evlist *evlist) -{ - struct perf_event_attr attr = { - .type = PERF_TYPE_HARDWARE, - .config = PERF_COUNT_HW_CPU_CYCLES, - }; - struct perf_evsel *evsel = perf_evsel__new(&attr, 0); - - if (evsel == NULL) - return -ENOMEM; - - perf_evlist__add(evlist, evsel); - return 0; -} - -int perf_evlist__alloc_pollfd(struct perf_evlist *evlist) -{ - int nfds = evlist->cpus->nr * evlist->threads->nr * evlist->nr_entries; - evlist->pollfd = malloc(sizeof(struct pollfd) * nfds); - return evlist->pollfd != NULL ? 0 : -ENOMEM; -} - -void perf_evlist__add_pollfd(struct perf_evlist *evlist, int fd) -{ - fcntl(fd, F_SETFL, O_NONBLOCK); - evlist->pollfd[evlist->nr_fds].fd = fd; - evlist->pollfd[evlist->nr_fds].events = POLLIN; - evlist->nr_fds++; -} - -static int perf_evlist__id_hash(struct perf_evlist *evlist, struct perf_evsel *evsel, - int cpu, int thread, int fd) -{ - struct perf_sample_id *sid; - u64 read_data[4] = { 0, }; - int hash, id_idx = 1; /* The first entry is the counter value */ - - if (!(evsel->attr.read_format & PERF_FORMAT_ID) || - read(fd, &read_data, sizeof(read_data)) == -1) - return -1; - - if (evsel->attr.read_format & PERF_FORMAT_TOTAL_TIME_ENABLED) - ++id_idx; - if (evsel->attr.read_format & PERF_FORMAT_TOTAL_TIME_RUNNING) - ++id_idx; - - sid = SID(evsel, cpu, thread); - sid->id = read_data[id_idx]; - sid->evsel = evsel; - hash = hash_64(sid->id, PERF_EVLIST__HLIST_BITS); - hlist_add_head(&sid->node, &evlist->heads[hash]); - return 0; -} - -struct perf_evsel *perf_evlist__id2evsel(struct perf_evlist *evlist, u64 id) -{ - struct hlist_head *head; - struct hlist_node *pos; - struct perf_sample_id *sid; - int hash; - - if (evlist->nr_entries == 1) - return list_entry(evlist->entries.next, struct perf_evsel, node); - - hash = hash_64(id, PERF_EVLIST__HLIST_BITS); - head = &evlist->heads[hash]; - - hlist_for_each_entry(sid, pos, head, node) - if (sid->id == id) - return sid->evsel; - return NULL; -} - -union perf_event *perf_evlist__read_on_cpu(struct perf_evlist *evlist, int cpu) -{ - /* XXX Move this to perf.c, making it generally available */ - unsigned int page_size = sysconf(_SC_PAGE_SIZE); - struct perf_mmap *md = &evlist->mmap[cpu]; - unsigned int head = perf_mmap__read_head(md); - unsigned int old = md->prev; - unsigned char *data = md->base + page_size; - union perf_event *event = NULL; - - if (evlist->overwrite) { - /* - * If we're further behind than half the buffer, there's a chance - * the writer will bite our tail and mess up the samples under us. - * - * If we somehow ended up ahead of the head, we got messed up. - * - * In either case, truncate and restart at head. - */ - int diff = head - old; - if (diff > md->mask / 2 || diff < 0) { - fprintf(stderr, "WARNING: failed to keep up with mmap data.\n"); - - /* - * head points to a known good entry, start there. - */ - old = head; - } - } - - if (old != head) { - size_t size; - - event = (union perf_event *)&data[old & md->mask]; - size = event->header.size; - - /* - * Event straddles the mmap boundary -- header should always - * be inside due to u64 alignment of output. - */ - if ((old & md->mask) + size != ((old + size) & md->mask)) { - unsigned int offset = old; - unsigned int len = min(sizeof(*event), size), cpy; - void *dst = &evlist->event_copy; - - do { - cpy = min(md->mask + 1 - (offset & md->mask), len); - memcpy(dst, &data[offset & md->mask], cpy); - offset += cpy; - dst += cpy; - len -= cpy; - } while (len); - - event = &evlist->event_copy; - } - - old += size; - } - - md->prev = old; - - if (!evlist->overwrite) - perf_mmap__write_tail(md, old); - - return event; -} - -void perf_evlist__munmap(struct perf_evlist *evlist) -{ - int cpu; - - for (cpu = 0; cpu < evlist->cpus->nr; cpu++) { - if (evlist->mmap[cpu].base != NULL) { - munmap(evlist->mmap[cpu].base, evlist->mmap_len); - evlist->mmap[cpu].base = NULL; - } - } -} - -int perf_evlist__alloc_mmap(struct perf_evlist *evlist) -{ - evlist->mmap = zalloc(evlist->cpus->nr * sizeof(struct perf_mmap)); - return evlist->mmap != NULL ? 0 : -ENOMEM; -} - -static int __perf_evlist__mmap(struct perf_evlist *evlist, int cpu, int prot, - int mask, int fd) -{ - evlist->mmap[cpu].prev = 0; - evlist->mmap[cpu].mask = mask; - evlist->mmap[cpu].base = mmap(NULL, evlist->mmap_len, prot, - MAP_SHARED, fd, 0); - if (evlist->mmap[cpu].base == MAP_FAILED) - return -1; - - perf_evlist__add_pollfd(evlist, fd); - return 0; -} - -/** perf_evlist__mmap - Create per cpu maps to receive events - * - * @evlist - list of events - * @pages - map length in pages - * @overwrite - overwrite older events? - * - * If overwrite is false the user needs to signal event consuption using: - * - * struct perf_mmap *m = &evlist->mmap[cpu]; - * unsigned int head = perf_mmap__read_head(m); - * - * perf_mmap__write_tail(m, head) - * - * Using perf_evlist__read_on_cpu does this automatically. - */ -int perf_evlist__mmap(struct perf_evlist *evlist, int pages, bool overwrite) -{ - unsigned int page_size = sysconf(_SC_PAGE_SIZE); - int mask = pages * page_size - 1, cpu; - struct perf_evsel *first_evsel, *evsel; - const struct cpu_map *cpus = evlist->cpus; - const struct thread_map *threads = evlist->threads; - int thread, prot = PROT_READ | (overwrite ? 0 : PROT_WRITE); - - if (evlist->mmap == NULL && perf_evlist__alloc_mmap(evlist) < 0) - return -ENOMEM; - - if (evlist->pollfd == NULL && perf_evlist__alloc_pollfd(evlist) < 0) - return -ENOMEM; - - evlist->overwrite = overwrite; - evlist->mmap_len = (pages + 1) * page_size; - first_evsel = list_entry(evlist->entries.next, struct perf_evsel, node); - - list_for_each_entry(evsel, &evlist->entries, node) { - if ((evsel->attr.read_format & PERF_FORMAT_ID) && - evsel->id == NULL && - perf_evsel__alloc_id(evsel, cpus->nr, threads->nr) < 0) - return -ENOMEM; - - for (cpu = 0; cpu < cpus->nr; cpu++) { - for (thread = 0; thread < threads->nr; thread++) { - int fd = FD(evsel, cpu, thread); - - if (evsel->idx || thread) { - if (ioctl(fd, PERF_EVENT_IOC_SET_OUTPUT, - FD(first_evsel, cpu, 0)) != 0) - goto out_unmap; - } else if (__perf_evlist__mmap(evlist, cpu, prot, mask, fd) < 0) - goto out_unmap; - - if ((evsel->attr.read_format & PERF_FORMAT_ID) && - perf_evlist__id_hash(evlist, evsel, cpu, thread, fd) < 0) - goto out_unmap; - } - } - } - - return 0; - -out_unmap: - for (cpu = 0; cpu < cpus->nr; cpu++) { - if (evlist->mmap[cpu].base != NULL) { - munmap(evlist->mmap[cpu].base, evlist->mmap_len); - evlist->mmap[cpu].base = NULL; - } - } - return -1; -} - -int perf_evlist__create_maps(struct perf_evlist *evlist, pid_t target_pid, - pid_t target_tid, const char *cpu_list) -{ - evlist->threads = thread_map__new(target_pid, target_tid); - - if (evlist->threads == NULL) - return -1; - - if (target_tid != -1) - evlist->cpus = cpu_map__dummy_new(); - else - evlist->cpus = cpu_map__new(cpu_list); - - if (evlist->cpus == NULL) - goto out_delete_threads; - - return 0; - -out_delete_threads: - thread_map__delete(evlist->threads); - return -1; -} - -void perf_evlist__delete_maps(struct perf_evlist *evlist) -{ - cpu_map__delete(evlist->cpus); - thread_map__delete(evlist->threads); - evlist->cpus = NULL; - evlist->threads = NULL; -} diff --git a/trunk/tools/perf/util/evlist.h b/trunk/tools/perf/util/evlist.h deleted file mode 100644 index c9884056097c..000000000000 --- a/trunk/tools/perf/util/evlist.h +++ /dev/null @@ -1,64 +0,0 @@ -#ifndef __PERF_EVLIST_H -#define __PERF_EVLIST_H 1 - -#include -#include "../perf.h" -#include "event.h" - -struct pollfd; -struct thread_map; -struct cpu_map; - -#define PERF_EVLIST__HLIST_BITS 8 -#define PERF_EVLIST__HLIST_SIZE (1 << PERF_EVLIST__HLIST_BITS) - -struct perf_evlist { - struct list_head entries; - struct hlist_head heads[PERF_EVLIST__HLIST_SIZE]; - int nr_entries; - int nr_fds; - int mmap_len; - bool overwrite; - union perf_event event_copy; - struct perf_mmap *mmap; - struct pollfd *pollfd; - struct thread_map *threads; - struct cpu_map *cpus; -}; - -struct perf_evsel; - -struct perf_evlist *perf_evlist__new(struct cpu_map *cpus, - struct thread_map *threads); -void perf_evlist__init(struct perf_evlist *evlist, struct cpu_map *cpus, - struct thread_map *threads); -void perf_evlist__exit(struct perf_evlist *evlist); -void perf_evlist__delete(struct perf_evlist *evlist); - -void perf_evlist__add(struct perf_evlist *evlist, struct perf_evsel *entry); -int perf_evlist__add_default(struct perf_evlist *evlist); - -int perf_evlist__alloc_pollfd(struct perf_evlist *evlist); -void perf_evlist__add_pollfd(struct perf_evlist *evlist, int fd); - -struct perf_evsel *perf_evlist__id2evsel(struct perf_evlist *evlist, u64 id); - -union perf_event *perf_evlist__read_on_cpu(struct perf_evlist *self, int cpu); - -int perf_evlist__alloc_mmap(struct perf_evlist *evlist); -int perf_evlist__mmap(struct perf_evlist *evlist, int pages, bool overwrite); -void perf_evlist__munmap(struct perf_evlist *evlist); - -static inline void perf_evlist__set_maps(struct perf_evlist *evlist, - struct cpu_map *cpus, - struct thread_map *threads) -{ - evlist->cpus = cpus; - evlist->threads = threads; -} - -int perf_evlist__create_maps(struct perf_evlist *evlist, pid_t target_pid, - pid_t target_tid, const char *cpu_list); -void perf_evlist__delete_maps(struct perf_evlist *evlist); - -#endif /* __PERF_EVLIST_H */ diff --git a/trunk/tools/perf/util/evsel.c b/trunk/tools/perf/util/evsel.c index 211063eed474..d8575d31ee6c 100644 --- a/trunk/tools/perf/util/evsel.c +++ b/trunk/tools/perf/util/evsel.c @@ -1,34 +1,20 @@ -/* - * Copyright (C) 2011, Red Hat Inc, Arnaldo Carvalho de Melo - * - * Parts came from builtin-{top,stat,record}.c, see those files for further - * copyright notes. - * - * Released under the GPL v2. (and only v2, not any later version) - */ - #include "evsel.h" -#include "evlist.h" +#include "../perf.h" #include "util.h" #include "cpumap.h" -#include "thread_map.h" +#include "thread.h" #define FD(e, x, y) (*(int *)xyarray__entry(e->fd, x, y)) -void perf_evsel__init(struct perf_evsel *evsel, - struct perf_event_attr *attr, int idx) -{ - evsel->idx = idx; - evsel->attr = *attr; - INIT_LIST_HEAD(&evsel->node); -} - struct perf_evsel *perf_evsel__new(struct perf_event_attr *attr, int idx) { struct perf_evsel *evsel = zalloc(sizeof(*evsel)); - if (evsel != NULL) - perf_evsel__init(evsel, attr, idx); + if (evsel != NULL) { + evsel->idx = idx; + evsel->attr = *attr; + INIT_LIST_HEAD(&evsel->node); + } return evsel; } @@ -39,12 +25,6 @@ int perf_evsel__alloc_fd(struct perf_evsel *evsel, int ncpus, int nthreads) return evsel->fd != NULL ? 0 : -ENOMEM; } -int perf_evsel__alloc_id(struct perf_evsel *evsel, int ncpus, int nthreads) -{ - evsel->id = xyarray__new(ncpus, nthreads, sizeof(struct perf_sample_id)); - return evsel->id != NULL ? 0 : -ENOMEM; -} - int perf_evsel__alloc_counts(struct perf_evsel *evsel, int ncpus) { evsel->counts = zalloc((sizeof(*evsel->counts) + @@ -58,12 +38,6 @@ void perf_evsel__free_fd(struct perf_evsel *evsel) evsel->fd = NULL; } -void perf_evsel__free_id(struct perf_evsel *evsel) -{ - xyarray__delete(evsel->id); - evsel->id = NULL; -} - void perf_evsel__close_fd(struct perf_evsel *evsel, int ncpus, int nthreads) { int cpu, thread; @@ -75,16 +49,10 @@ void perf_evsel__close_fd(struct perf_evsel *evsel, int ncpus, int nthreads) } } -void perf_evsel__exit(struct perf_evsel *evsel) +void perf_evsel__delete(struct perf_evsel *evsel) { assert(list_empty(&evsel->node)); xyarray__delete(evsel->fd); - xyarray__delete(evsel->id); -} - -void perf_evsel__delete(struct perf_evsel *evsel) -{ - perf_evsel__exit(evsel); free(evsel); } @@ -160,7 +128,7 @@ int __perf_evsel__read(struct perf_evsel *evsel, } static int __perf_evsel__open(struct perf_evsel *evsel, struct cpu_map *cpus, - struct thread_map *threads, bool group, bool inherit) + struct thread_map *threads) { int cpu, thread; @@ -169,20 +137,12 @@ static int __perf_evsel__open(struct perf_evsel *evsel, struct cpu_map *cpus, return -1; for (cpu = 0; cpu < cpus->nr; cpu++) { - int group_fd = -1; - - evsel->attr.inherit = (cpus->map[cpu] < 0) && inherit; - for (thread = 0; thread < threads->nr; thread++) { FD(evsel, cpu, thread) = sys_perf_event_open(&evsel->attr, threads->map[thread], - cpus->map[cpu], - group_fd, 0); + cpus->map[cpu], -1, 0); if (FD(evsel, cpu, thread) < 0) goto out_close; - - if (group && group_fd == -1) - group_fd = FD(evsel, cpu, thread); } } @@ -215,9 +175,10 @@ static struct { .threads = { -1, }, }; -int perf_evsel__open(struct perf_evsel *evsel, struct cpu_map *cpus, - struct thread_map *threads, bool group, bool inherit) +int perf_evsel__open(struct perf_evsel *evsel, + struct cpu_map *cpus, struct thread_map *threads) { + if (cpus == NULL) { /* Work around old compiler warnings about strict aliasing */ cpus = &empty_cpu_map.map; @@ -226,135 +187,15 @@ int perf_evsel__open(struct perf_evsel *evsel, struct cpu_map *cpus, if (threads == NULL) threads = &empty_thread_map.map; - return __perf_evsel__open(evsel, cpus, threads, group, inherit); -} - -int perf_evsel__open_per_cpu(struct perf_evsel *evsel, - struct cpu_map *cpus, bool group, bool inherit) -{ - return __perf_evsel__open(evsel, cpus, &empty_thread_map.map, group, inherit); + return __perf_evsel__open(evsel, cpus, threads); } -int perf_evsel__open_per_thread(struct perf_evsel *evsel, - struct thread_map *threads, bool group, bool inherit) +int perf_evsel__open_per_cpu(struct perf_evsel *evsel, struct cpu_map *cpus) { - return __perf_evsel__open(evsel, &empty_cpu_map.map, threads, group, inherit); + return __perf_evsel__open(evsel, cpus, &empty_thread_map.map); } -static int perf_event__parse_id_sample(const union perf_event *event, u64 type, - struct perf_sample *sample) +int perf_evsel__open_per_thread(struct perf_evsel *evsel, struct thread_map *threads) { - const u64 *array = event->sample.array; - - array += ((event->header.size - - sizeof(event->header)) / sizeof(u64)) - 1; - - if (type & PERF_SAMPLE_CPU) { - u32 *p = (u32 *)array; - sample->cpu = *p; - array--; - } - - if (type & PERF_SAMPLE_STREAM_ID) { - sample->stream_id = *array; - array--; - } - - if (type & PERF_SAMPLE_ID) { - sample->id = *array; - array--; - } - - if (type & PERF_SAMPLE_TIME) { - sample->time = *array; - array--; - } - - if (type & PERF_SAMPLE_TID) { - u32 *p = (u32 *)array; - sample->pid = p[0]; - sample->tid = p[1]; - } - - return 0; -} - -int perf_event__parse_sample(const union perf_event *event, u64 type, - bool sample_id_all, struct perf_sample *data) -{ - const u64 *array; - - data->cpu = data->pid = data->tid = -1; - data->stream_id = data->id = data->time = -1ULL; - - if (event->header.type != PERF_RECORD_SAMPLE) { - if (!sample_id_all) - return 0; - return perf_event__parse_id_sample(event, type, data); - } - - array = event->sample.array; - - if (type & PERF_SAMPLE_IP) { - data->ip = event->ip.ip; - array++; - } - - if (type & PERF_SAMPLE_TID) { - u32 *p = (u32 *)array; - data->pid = p[0]; - data->tid = p[1]; - array++; - } - - if (type & PERF_SAMPLE_TIME) { - data->time = *array; - array++; - } - - if (type & PERF_SAMPLE_ADDR) { - data->addr = *array; - array++; - } - - data->id = -1ULL; - if (type & PERF_SAMPLE_ID) { - data->id = *array; - array++; - } - - if (type & PERF_SAMPLE_STREAM_ID) { - data->stream_id = *array; - array++; - } - - if (type & PERF_SAMPLE_CPU) { - u32 *p = (u32 *)array; - data->cpu = *p; - array++; - } - - if (type & PERF_SAMPLE_PERIOD) { - data->period = *array; - array++; - } - - if (type & PERF_SAMPLE_READ) { - fprintf(stderr, "PERF_SAMPLE_READ is unsuported for now\n"); - return -1; - } - - if (type & PERF_SAMPLE_CALLCHAIN) { - data->callchain = (struct ip_callchain *)array; - array += 1 + data->callchain->nr; - } - - if (type & PERF_SAMPLE_RAW) { - u32 *p = (u32 *)array; - data->raw_size = *p; - p++; - data->raw_data = p; - } - - return 0; + return __perf_evsel__open(evsel, &empty_cpu_map.map, threads); } diff --git a/trunk/tools/perf/util/evsel.h b/trunk/tools/perf/util/evsel.h index eecdc3aabc14..b2d755fe88a5 100644 --- a/trunk/tools/perf/util/evsel.h +++ b/trunk/tools/perf/util/evsel.h @@ -24,24 +24,11 @@ struct perf_counts { struct perf_counts_values cpu[]; }; -struct perf_evsel; - -/* - * Per fd, to map back from PERF_SAMPLE_ID to evsel, only used when there are - * more than one entry in the evlist. - */ -struct perf_sample_id { - struct hlist_node node; - u64 id; - struct perf_evsel *evsel; -}; - struct perf_evsel { struct list_head node; struct perf_event_attr attr; char *filter; struct xyarray *fd; - struct xyarray *id; struct perf_counts *counts; int idx; void *priv; @@ -49,27 +36,19 @@ struct perf_evsel { struct cpu_map; struct thread_map; -struct perf_evlist; struct perf_evsel *perf_evsel__new(struct perf_event_attr *attr, int idx); -void perf_evsel__init(struct perf_evsel *evsel, - struct perf_event_attr *attr, int idx); -void perf_evsel__exit(struct perf_evsel *evsel); void perf_evsel__delete(struct perf_evsel *evsel); int perf_evsel__alloc_fd(struct perf_evsel *evsel, int ncpus, int nthreads); -int perf_evsel__alloc_id(struct perf_evsel *evsel, int ncpus, int nthreads); int perf_evsel__alloc_counts(struct perf_evsel *evsel, int ncpus); void perf_evsel__free_fd(struct perf_evsel *evsel); -void perf_evsel__free_id(struct perf_evsel *evsel); void perf_evsel__close_fd(struct perf_evsel *evsel, int ncpus, int nthreads); -int perf_evsel__open_per_cpu(struct perf_evsel *evsel, - struct cpu_map *cpus, bool group, bool inherit); -int perf_evsel__open_per_thread(struct perf_evsel *evsel, - struct thread_map *threads, bool group, bool inherit); -int perf_evsel__open(struct perf_evsel *evsel, struct cpu_map *cpus, - struct thread_map *threads, bool group, bool inherit); +int perf_evsel__open_per_cpu(struct perf_evsel *evsel, struct cpu_map *cpus); +int perf_evsel__open_per_thread(struct perf_evsel *evsel, struct thread_map *threads); +int perf_evsel__open(struct perf_evsel *evsel, + struct cpu_map *cpus, struct thread_map *threads); #define perf_evsel__match(evsel, t, c) \ (evsel->attr.type == PERF_TYPE_##t && \ diff --git a/trunk/tools/perf/util/header.c b/trunk/tools/perf/util/header.c index 72c124dc5781..f6a929e74981 100644 --- a/trunk/tools/perf/util/header.c +++ b/trunk/tools/perf/util/header.c @@ -8,7 +8,6 @@ #include #include -#include "evlist.h" #include "util.h" #include "header.h" #include "../perf.h" @@ -429,8 +428,7 @@ static bool perf_session__read_build_ids(struct perf_session *self, bool with_hi return ret; } -static int perf_header__adds_write(struct perf_header *self, - struct perf_evlist *evlist, int fd) +static int perf_header__adds_write(struct perf_header *self, int fd) { int nr_sections; struct perf_session *session; @@ -465,7 +463,7 @@ static int perf_header__adds_write(struct perf_header *self, /* Write trace info */ trace_sec->offset = lseek(fd, 0, SEEK_CUR); - read_tracing_data(fd, &evlist->entries); + read_tracing_data(fd, &evsel_list); trace_sec->size = lseek(fd, 0, SEEK_CUR) - trace_sec->offset; } @@ -515,8 +513,7 @@ int perf_header__write_pipe(int fd) return 0; } -int perf_header__write(struct perf_header *self, struct perf_evlist *evlist, - int fd, bool at_exit) +int perf_header__write(struct perf_header *self, int fd, bool at_exit) { struct perf_file_header f_header; struct perf_file_attr f_attr; @@ -569,7 +566,7 @@ int perf_header__write(struct perf_header *self, struct perf_evlist *evlist, self->data_offset = lseek(fd, 0, SEEK_CUR); if (at_exit) { - err = perf_header__adds_write(self, evlist, fd); + err = perf_header__adds_write(self, fd); if (err < 0) return err; } @@ -1000,11 +997,11 @@ perf_header__find_attr(u64 id, struct perf_header *header) return NULL; } -int perf_event__synthesize_attr(struct perf_event_attr *attr, u16 ids, u64 *id, - perf_event__handler_t process, - struct perf_session *session) +int event__synthesize_attr(struct perf_event_attr *attr, u16 ids, u64 *id, + event__handler_t process, + struct perf_session *session) { - union perf_event *ev; + event_t *ev; size_t size; int err; @@ -1031,9 +1028,8 @@ int perf_event__synthesize_attr(struct perf_event_attr *attr, u16 ids, u64 *id, return err; } -int perf_event__synthesize_attrs(struct perf_header *self, - perf_event__handler_t process, - struct perf_session *session) +int event__synthesize_attrs(struct perf_header *self, event__handler_t process, + struct perf_session *session) { struct perf_header_attr *attr; int i, err = 0; @@ -1041,8 +1037,8 @@ int perf_event__synthesize_attrs(struct perf_header *self, for (i = 0; i < self->attrs; i++) { attr = self->attr[i]; - err = perf_event__synthesize_attr(&attr->attr, attr->ids, - attr->id, process, session); + err = event__synthesize_attr(&attr->attr, attr->ids, attr->id, + process, session); if (err) { pr_debug("failed to create perf header attribute\n"); return err; @@ -1052,22 +1048,21 @@ int perf_event__synthesize_attrs(struct perf_header *self, return err; } -int perf_event__process_attr(union perf_event *event, - struct perf_session *session) +int event__process_attr(event_t *self, struct perf_session *session) { struct perf_header_attr *attr; unsigned int i, ids, n_ids; - attr = perf_header_attr__new(&event->attr.attr); + attr = perf_header_attr__new(&self->attr.attr); if (attr == NULL) return -ENOMEM; - ids = event->header.size; - ids -= (void *)&event->attr.id - (void *)event; + ids = self->header.size; + ids -= (void *)&self->attr.id - (void *)self; n_ids = ids / sizeof(u64); for (i = 0; i < n_ids; i++) { - if (perf_header_attr__add_id(attr, event->attr.id[i]) < 0) { + if (perf_header_attr__add_id(attr, self->attr.id[i]) < 0) { perf_header_attr__delete(attr); return -ENOMEM; } @@ -1083,11 +1078,11 @@ int perf_event__process_attr(union perf_event *event, return 0; } -int perf_event__synthesize_event_type(u64 event_id, char *name, - perf_event__handler_t process, - struct perf_session *session) +int event__synthesize_event_type(u64 event_id, char *name, + event__handler_t process, + struct perf_session *session) { - union perf_event ev; + event_t ev; size_t size = 0; int err = 0; @@ -1108,8 +1103,8 @@ int perf_event__synthesize_event_type(u64 event_id, char *name, return err; } -int perf_event__synthesize_event_types(perf_event__handler_t process, - struct perf_session *session) +int event__synthesize_event_types(event__handler_t process, + struct perf_session *session) { struct perf_trace_event_type *type; int i, err = 0; @@ -1117,9 +1112,8 @@ int perf_event__synthesize_event_types(perf_event__handler_t process, for (i = 0; i < event_count; i++) { type = &events[i]; - err = perf_event__synthesize_event_type(type->event_id, - type->name, process, - session); + err = event__synthesize_event_type(type->event_id, type->name, + process, session); if (err) { pr_debug("failed to create perf header event type\n"); return err; @@ -1129,28 +1123,28 @@ int perf_event__synthesize_event_types(perf_event__handler_t process, return err; } -int perf_event__process_event_type(union perf_event *event, - struct perf_session *session __unused) +int event__process_event_type(event_t *self, + struct perf_session *session __unused) { - if (perf_header__push_event(event->event_type.event_type.event_id, - event->event_type.event_type.name) < 0) + if (perf_header__push_event(self->event_type.event_type.event_id, + self->event_type.event_type.name) < 0) return -ENOMEM; return 0; } -int perf_event__synthesize_tracing_data(int fd, struct perf_evlist *evlist, - perf_event__handler_t process, +int event__synthesize_tracing_data(int fd, struct list_head *pattrs, + event__handler_t process, struct perf_session *session __unused) { - union perf_event ev; + event_t ev; ssize_t size = 0, aligned_size = 0, padding; - int err __used = 0; + int err = 0; memset(&ev, 0, sizeof(ev)); ev.tracing_data.header.type = PERF_RECORD_HEADER_TRACING_DATA; - size = read_tracing_data_size(fd, &evlist->entries); + size = read_tracing_data_size(fd, pattrs); if (size <= 0) return size; aligned_size = ALIGN(size, sizeof(u64)); @@ -1160,16 +1154,16 @@ int perf_event__synthesize_tracing_data(int fd, struct perf_evlist *evlist, process(&ev, NULL, session); - err = read_tracing_data(fd, &evlist->entries); + err = read_tracing_data(fd, pattrs); write_padded(fd, NULL, 0, padding); return aligned_size; } -int perf_event__process_tracing_data(union perf_event *event, - struct perf_session *session) +int event__process_tracing_data(event_t *self, + struct perf_session *session) { - ssize_t size_read, padding, size = event->tracing_data.size; + ssize_t size_read, padding, size = self->tracing_data.size; off_t offset = lseek(session->fd, 0, SEEK_CUR); char buf[BUFSIZ]; @@ -1195,12 +1189,12 @@ int perf_event__process_tracing_data(union perf_event *event, return size_read + padding; } -int perf_event__synthesize_build_id(struct dso *pos, u16 misc, - perf_event__handler_t process, - struct machine *machine, - struct perf_session *session) +int event__synthesize_build_id(struct dso *pos, u16 misc, + event__handler_t process, + struct machine *machine, + struct perf_session *session) { - union perf_event ev; + event_t ev; size_t len; int err = 0; @@ -1223,11 +1217,11 @@ int perf_event__synthesize_build_id(struct dso *pos, u16 misc, return err; } -int perf_event__process_build_id(union perf_event *event, - struct perf_session *session) +int event__process_build_id(event_t *self, + struct perf_session *session) { - __event_process_build_id(&event->build_id, - event->build_id.filename, + __event_process_build_id(&self->build_id, + self->build_id.filename, session); return 0; } diff --git a/trunk/tools/perf/util/header.h b/trunk/tools/perf/util/header.h index f042cebcec1e..33f16be7b72f 100644 --- a/trunk/tools/perf/util/header.h +++ b/trunk/tools/perf/util/header.h @@ -65,11 +65,8 @@ struct perf_header { int perf_header__init(struct perf_header *self); void perf_header__exit(struct perf_header *self); -struct perf_evlist; - int perf_header__read(struct perf_session *session, int fd); -int perf_header__write(struct perf_header *self, struct perf_evlist *evlist, - int fd, bool at_exit); +int perf_header__write(struct perf_header *self, int fd, bool at_exit); int perf_header__write_pipe(int fd); int perf_header__add_attr(struct perf_header *self, @@ -100,32 +97,32 @@ int build_id_cache__add_s(const char *sbuild_id, const char *debugdir, const char *name, bool is_kallsyms); int build_id_cache__remove_s(const char *sbuild_id, const char *debugdir); -int perf_event__synthesize_attr(struct perf_event_attr *attr, u16 ids, u64 *id, - perf_event__handler_t process, - struct perf_session *session); -int perf_event__synthesize_attrs(struct perf_header *self, - perf_event__handler_t process, +int event__synthesize_attr(struct perf_event_attr *attr, u16 ids, u64 *id, + event__handler_t process, + struct perf_session *session); +int event__synthesize_attrs(struct perf_header *self, + event__handler_t process, + struct perf_session *session); +int event__process_attr(event_t *self, struct perf_session *session); + +int event__synthesize_event_type(u64 event_id, char *name, + event__handler_t process, struct perf_session *session); -int perf_event__process_attr(union perf_event *event, struct perf_session *session); - -int perf_event__synthesize_event_type(u64 event_id, char *name, - perf_event__handler_t process, - struct perf_session *session); -int perf_event__synthesize_event_types(perf_event__handler_t process, - struct perf_session *session); -int perf_event__process_event_type(union perf_event *event, +int event__synthesize_event_types(event__handler_t process, + struct perf_session *session); +int event__process_event_type(event_t *self, + struct perf_session *session); + +int event__synthesize_tracing_data(int fd, struct list_head *pattrs, + event__handler_t process, struct perf_session *session); +int event__process_tracing_data(event_t *self, + struct perf_session *session); + +int event__synthesize_build_id(struct dso *pos, u16 misc, + event__handler_t process, + struct machine *machine, + struct perf_session *session); +int event__process_build_id(event_t *self, struct perf_session *session); -int perf_event__synthesize_tracing_data(int fd, struct perf_evlist *evlist, - perf_event__handler_t process, - struct perf_session *session); -int perf_event__process_tracing_data(union perf_event *event, - struct perf_session *session); - -int perf_event__synthesize_build_id(struct dso *pos, u16 misc, - perf_event__handler_t process, - struct machine *machine, - struct perf_session *session); -int perf_event__process_build_id(union perf_event *event, - struct perf_session *session); #endif /* __PERF_HEADER_H */ diff --git a/trunk/tools/perf/util/hist.c b/trunk/tools/perf/util/hist.c index 3f437236f193..32f4f1f2f6e4 100644 --- a/trunk/tools/perf/util/hist.c +++ b/trunk/tools/perf/util/hist.c @@ -1,4 +1,3 @@ -#include "annotate.h" #include "util.h" #include "build-id.h" #include "hist.h" @@ -212,9 +211,7 @@ void hist_entry__free(struct hist_entry *he) * collapse the histogram */ -static bool hists__collapse_insert_entry(struct hists *self, - struct rb_root *root, - struct hist_entry *he) +static bool collapse__insert_entry(struct rb_root *root, struct hist_entry *he) { struct rb_node **p = &root->rb_node; struct rb_node *parent = NULL; @@ -229,11 +226,8 @@ static bool hists__collapse_insert_entry(struct hists *self, if (!cmp) { iter->period += he->period; - if (symbol_conf.use_callchain) { - callchain_cursor_reset(&self->callchain_cursor); - callchain_merge(&self->callchain_cursor, iter->callchain, - he->callchain); - } + if (symbol_conf.use_callchain) + callchain_merge(iter->callchain, he->callchain); hist_entry__free(he); return false; } @@ -268,7 +262,7 @@ void hists__collapse_resort(struct hists *self) next = rb_next(&n->rb_node); rb_erase(&n->rb_node, &self->entries); - if (hists__collapse_insert_entry(self, &tmp, n)) + if (collapse__insert_entry(&tmp, n)) hists__inc_nr_entries(self, n); } @@ -431,7 +425,7 @@ static size_t __callchain__fprintf_graph(FILE *fp, struct callchain_node *self, u64 cumul; child = rb_entry(node, struct callchain_node, rb_node); - cumul = callchain_cumul_hits(child); + cumul = cumul_hits(child); remaining -= cumul; /* @@ -950,14 +944,225 @@ void hists__filter_by_thread(struct hists *self, const struct thread *thread) } } -int hist_entry__inc_addr_samples(struct hist_entry *he, int evidx, u64 ip) +static int symbol__alloc_hist(struct symbol *self) +{ + struct sym_priv *priv = symbol__priv(self); + const int size = (sizeof(*priv->hist) + + (self->end - self->start) * sizeof(u64)); + + priv->hist = zalloc(size); + return priv->hist == NULL ? -1 : 0; +} + +int hist_entry__inc_addr_samples(struct hist_entry *self, u64 ip) +{ + unsigned int sym_size, offset; + struct symbol *sym = self->ms.sym; + struct sym_priv *priv; + struct sym_hist *h; + + if (!sym || !self->ms.map) + return 0; + + priv = symbol__priv(sym); + if (priv->hist == NULL && symbol__alloc_hist(sym) < 0) + return -ENOMEM; + + sym_size = sym->end - sym->start; + offset = ip - sym->start; + + pr_debug3("%s: ip=%#" PRIx64 "\n", __func__, self->ms.map->unmap_ip(self->ms.map, ip)); + + if (offset >= sym_size) + return 0; + + h = priv->hist; + h->sum++; + h->ip[offset]++; + + pr_debug3("%#" PRIx64 " %s: period++ [ip: %#" PRIx64 ", %#" PRIx64 + "] => %" PRIu64 "\n", self->ms.sym->start, self->ms.sym->name, + ip, ip - self->ms.sym->start, h->ip[offset]); + return 0; +} + +static struct objdump_line *objdump_line__new(s64 offset, char *line, size_t privsize) +{ + struct objdump_line *self = malloc(sizeof(*self) + privsize); + + if (self != NULL) { + self->offset = offset; + self->line = line; + } + + return self; +} + +void objdump_line__free(struct objdump_line *self) +{ + free(self->line); + free(self); +} + +static void objdump__add_line(struct list_head *head, struct objdump_line *line) +{ + list_add_tail(&line->node, head); +} + +struct objdump_line *objdump__get_next_ip_line(struct list_head *head, + struct objdump_line *pos) +{ + list_for_each_entry_continue(pos, head, node) + if (pos->offset >= 0) + return pos; + + return NULL; +} + +static int hist_entry__parse_objdump_line(struct hist_entry *self, FILE *file, + struct list_head *head, size_t privsize) { - return symbol__inc_addr_samples(he->ms.sym, he->ms.map, evidx, ip); + struct symbol *sym = self->ms.sym; + struct objdump_line *objdump_line; + char *line = NULL, *tmp, *tmp2, *c; + size_t line_len; + s64 line_ip, offset = -1; + + if (getline(&line, &line_len, file) < 0) + return -1; + + if (!line) + return -1; + + while (line_len != 0 && isspace(line[line_len - 1])) + line[--line_len] = '\0'; + + c = strchr(line, '\n'); + if (c) + *c = 0; + + line_ip = -1; + + /* + * Strip leading spaces: + */ + tmp = line; + while (*tmp) { + if (*tmp != ' ') + break; + tmp++; + } + + if (*tmp) { + /* + * Parse hexa addresses followed by ':' + */ + line_ip = strtoull(tmp, &tmp2, 16); + if (*tmp2 != ':' || tmp == tmp2 || tmp2[1] == '\0') + line_ip = -1; + } + + if (line_ip != -1) { + u64 start = map__rip_2objdump(self->ms.map, sym->start), + end = map__rip_2objdump(self->ms.map, sym->end); + + offset = line_ip - start; + if (offset < 0 || (u64)line_ip > end) + offset = -1; + } + + objdump_line = objdump_line__new(offset, line, privsize); + if (objdump_line == NULL) { + free(line); + return -1; + } + objdump__add_line(head, objdump_line); + + return 0; } -int hist_entry__annotate(struct hist_entry *he, size_t privsize) +int hist_entry__annotate(struct hist_entry *self, struct list_head *head, + size_t privsize) { - return symbol__annotate(he->ms.sym, he->ms.map, privsize); + struct symbol *sym = self->ms.sym; + struct map *map = self->ms.map; + struct dso *dso = map->dso; + char *filename = dso__build_id_filename(dso, NULL, 0); + bool free_filename = true; + char command[PATH_MAX * 2]; + FILE *file; + int err = 0; + u64 len; + char symfs_filename[PATH_MAX]; + + if (filename) { + snprintf(symfs_filename, sizeof(symfs_filename), "%s%s", + symbol_conf.symfs, filename); + } + + if (filename == NULL) { + if (dso->has_build_id) { + pr_err("Can't annotate %s: not enough memory\n", + sym->name); + return -ENOMEM; + } + goto fallback; + } else if (readlink(symfs_filename, command, sizeof(command)) < 0 || + strstr(command, "[kernel.kallsyms]") || + access(symfs_filename, R_OK)) { + free(filename); +fallback: + /* + * If we don't have build-ids or the build-id file isn't in the + * cache, or is just a kallsyms file, well, lets hope that this + * DSO is the same as when 'perf record' ran. + */ + filename = dso->long_name; + snprintf(symfs_filename, sizeof(symfs_filename), "%s%s", + symbol_conf.symfs, filename); + free_filename = false; + } + + if (dso->origin == DSO__ORIG_KERNEL) { + if (dso->annotate_warned) + goto out_free_filename; + err = -ENOENT; + dso->annotate_warned = 1; + pr_err("Can't annotate %s: No vmlinux file was found in the " + "path\n", sym->name); + goto out_free_filename; + } + + pr_debug("%s: filename=%s, sym=%s, start=%#" PRIx64 ", end=%#" PRIx64 "\n", __func__, + filename, sym->name, map->unmap_ip(map, sym->start), + map->unmap_ip(map, sym->end)); + + len = sym->end - sym->start; + + pr_debug("annotating [%p] %30s : [%p] %30s\n", + dso, dso->long_name, sym, sym->name); + + snprintf(command, sizeof(command), + "objdump --start-address=0x%016" PRIx64 " --stop-address=0x%016" PRIx64 " -dS -C %s|grep -v %s|expand", + map__rip_2objdump(map, sym->start), + map__rip_2objdump(map, sym->end), + symfs_filename, filename); + + pr_debug("Executing: %s\n", command); + + file = popen(command, "r"); + if (!file) + goto out_free_filename; + + while (!feof(file)) + if (hist_entry__parse_objdump_line(self, file, head, privsize) < 0) + break; + + pclose(file); +out_free_filename: + if (free_filename) + free(filename); + return err; } void hists__inc_nr_events(struct hists *self, u32 type) @@ -972,7 +1177,7 @@ size_t hists__fprintf_nr_events(struct hists *self, FILE *fp) size_t ret = 0; for (i = 0; i < PERF_RECORD_HEADER_MAX; ++i) { - const char *name = perf_event__name(i); + const char *name = event__get_event_name(i); if (!strcmp(name, "UNKNOWN")) continue; diff --git a/trunk/tools/perf/util/hist.h b/trunk/tools/perf/util/hist.h index 37c79089de09..ee789856a8c9 100644 --- a/trunk/tools/perf/util/hist.h +++ b/trunk/tools/perf/util/hist.h @@ -9,6 +9,33 @@ extern struct callchain_param callchain_param; struct hist_entry; struct addr_location; struct symbol; +struct rb_root; + +struct objdump_line { + struct list_head node; + s64 offset; + char *line; +}; + +void objdump_line__free(struct objdump_line *self); +struct objdump_line *objdump__get_next_ip_line(struct list_head *head, + struct objdump_line *pos); + +struct sym_hist { + u64 sum; + u64 ip[0]; +}; + +struct sym_ext { + struct rb_node node; + double percent; + char *path; +}; + +struct sym_priv { + struct sym_hist *hist; + struct sym_ext *ext; +}; /* * The kernel collects the number of events it couldn't send in a stretch and @@ -50,8 +77,6 @@ struct hists { u64 event_stream; u32 type; u16 col_len[HISTC_NR_COLS]; - /* Best would be to reuse the session callchain cursor */ - struct callchain_cursor callchain_cursor; }; struct hist_entry *__hists__add_entry(struct hists *self, @@ -77,8 +102,9 @@ size_t hists__fprintf_nr_events(struct hists *self, FILE *fp); size_t hists__fprintf(struct hists *self, struct hists *pair, bool show_displacement, FILE *fp); -int hist_entry__inc_addr_samples(struct hist_entry *self, int evidx, u64 addr); -int hist_entry__annotate(struct hist_entry *self, size_t privsize); +int hist_entry__inc_addr_samples(struct hist_entry *self, u64 ip); +int hist_entry__annotate(struct hist_entry *self, struct list_head *head, + size_t privsize); void hists__filter_by_dso(struct hists *self, const struct dso *dso); void hists__filter_by_thread(struct hists *self, const struct thread *thread); @@ -90,20 +116,18 @@ bool hists__new_col_len(struct hists *self, enum hist_column col, u16 len); #ifdef NO_NEWT_SUPPORT static inline int hists__browse(struct hists *self __used, const char *helpline __used, - const char *ev_name __used, int evidx __used) + const char *ev_name __used) { return 0; } static inline int hists__tui_browse_tree(struct rb_root *self __used, - const char *help __used, - int evidx __used) + const char *help __used) { return 0; } -static inline int hist_entry__tui_annotate(struct hist_entry *self __used, - int evidx __used) +static inline int hist_entry__tui_annotate(struct hist_entry *self __used) { return 0; } @@ -112,13 +136,13 @@ static inline int hist_entry__tui_annotate(struct hist_entry *self __used, #else #include int hists__browse(struct hists *self, const char *helpline, - const char *ev_name, int evidx); -int hist_entry__tui_annotate(struct hist_entry *self, int evidx); + const char *ev_name); +int hist_entry__tui_annotate(struct hist_entry *self); #define KEY_LEFT NEWT_KEY_LEFT #define KEY_RIGHT NEWT_KEY_RIGHT -int hists__tui_browse_tree(struct rb_root *self, const char *help, int evidx); +int hists__tui_browse_tree(struct rb_root *self, const char *help); #endif unsigned int hists__sort_list_width(struct hists *self); diff --git a/trunk/tools/perf/util/include/linux/list.h b/trunk/tools/perf/util/include/linux/list.h index 356c7e467b83..f5ca26e53fbb 100644 --- a/trunk/tools/perf/util/include/linux/list.h +++ b/trunk/tools/perf/util/include/linux/list.h @@ -1,4 +1,3 @@ -#include #include "../../../../include/linux/list.h" #ifndef PERF_LIST_H diff --git a/trunk/tools/perf/util/parse-events.c b/trunk/tools/perf/util/parse-events.c index cf082daa43e3..135f69baf966 100644 --- a/trunk/tools/perf/util/parse-events.c +++ b/trunk/tools/perf/util/parse-events.c @@ -1,7 +1,6 @@ #include "../../../include/linux/hw_breakpoint.h" #include "util.h" #include "../perf.h" -#include "evlist.h" #include "evsel.h" #include "parse-options.h" #include "parse-events.h" @@ -12,6 +11,10 @@ #include "header.h" #include "debugfs.h" +int nr_counters; + +LIST_HEAD(evsel_list); + struct event_symbol { u8 type; u64 config; @@ -446,8 +449,8 @@ parse_single_tracepoint_event(char *sys_name, /* sys + ':' + event + ':' + flags*/ #define MAX_EVOPT_LEN (MAX_EVENT_LENGTH * 2 + 2 + 128) static enum event_result -parse_multiple_tracepoint_event(const struct option *opt, char *sys_name, - const char *evt_exp, char *flags) +parse_multiple_tracepoint_event(char *sys_name, const char *evt_exp, + char *flags) { char evt_path[MAXPATHLEN]; struct dirent *evt_ent; @@ -480,16 +483,15 @@ parse_multiple_tracepoint_event(const struct option *opt, char *sys_name, if (len < 0) return EVT_FAILED; - if (parse_events(opt, event_opt, 0)) + if (parse_events(NULL, event_opt, 0)) return EVT_FAILED; } return EVT_HANDLED_ALL; } -static enum event_result -parse_tracepoint_event(const struct option *opt, const char **strp, - struct perf_event_attr *attr) +static enum event_result parse_tracepoint_event(const char **strp, + struct perf_event_attr *attr) { const char *evt_name; char *flags = NULL, *comma_loc; @@ -528,7 +530,7 @@ parse_tracepoint_event(const struct option *opt, const char **strp, return EVT_FAILED; if (strpbrk(evt_name, "*?")) { *strp += strlen(sys_name) + evt_length + 1; /* 1 == the ':' */ - return parse_multiple_tracepoint_event(opt, sys_name, evt_name, + return parse_multiple_tracepoint_event(sys_name, evt_name, flags); } else { return parse_single_tracepoint_event(sys_name, evt_name, @@ -738,12 +740,11 @@ parse_event_modifier(const char **strp, struct perf_event_attr *attr) * Symbolic names are (almost) exactly matched. */ static enum event_result -parse_event_symbols(const struct option *opt, const char **str, - struct perf_event_attr *attr) +parse_event_symbols(const char **str, struct perf_event_attr *attr) { enum event_result ret; - ret = parse_tracepoint_event(opt, str, attr); + ret = parse_tracepoint_event(str, attr); if (ret != EVT_FAILED) goto modifier; @@ -777,15 +778,14 @@ parse_event_symbols(const struct option *opt, const char **str, return ret; } -int parse_events(const struct option *opt, const char *str, int unset __used) +int parse_events(const struct option *opt __used, const char *str, int unset __used) { - struct perf_evlist *evlist = *(struct perf_evlist **)opt->value; struct perf_event_attr attr; enum event_result ret; for (;;) { memset(&attr, 0, sizeof(attr)); - ret = parse_event_symbols(opt, &str, &attr); + ret = parse_event_symbols(&str, &attr); if (ret == EVT_FAILED) return -1; @@ -794,10 +794,12 @@ int parse_events(const struct option *opt, const char *str, int unset __used) if (ret != EVT_HANDLED_ALL) { struct perf_evsel *evsel; - evsel = perf_evsel__new(&attr, evlist->nr_entries); + evsel = perf_evsel__new(&attr, + nr_counters); if (evsel == NULL) return -1; - perf_evlist__add(evlist, evsel); + list_add_tail(&evsel->node, &evsel_list); + ++nr_counters; } if (*str == 0) @@ -811,14 +813,13 @@ int parse_events(const struct option *opt, const char *str, int unset __used) return 0; } -int parse_filter(const struct option *opt, const char *str, +int parse_filter(const struct option *opt __used, const char *str, int unset __used) { - struct perf_evlist *evlist = *(struct perf_evlist **)opt->value; struct perf_evsel *last = NULL; - if (evlist->nr_entries > 0) - last = list_entry(evlist->entries.prev, struct perf_evsel, node); + if (!list_empty(&evsel_list)) + last = list_entry(evsel_list.prev, struct perf_evsel, node); if (last == NULL || last->attr.type != PERF_TYPE_TRACEPOINT) { fprintf(stderr, @@ -980,3 +981,33 @@ void print_events(void) exit(129); } + +int perf_evsel_list__create_default(void) +{ + struct perf_evsel *evsel; + struct perf_event_attr attr; + + memset(&attr, 0, sizeof(attr)); + attr.type = PERF_TYPE_HARDWARE; + attr.config = PERF_COUNT_HW_CPU_CYCLES; + + evsel = perf_evsel__new(&attr, 0); + + if (evsel == NULL) + return -ENOMEM; + + list_add(&evsel->node, &evsel_list); + ++nr_counters; + return 0; +} + +void perf_evsel_list__delete(void) +{ + struct perf_evsel *pos, *n; + + list_for_each_entry_safe(pos, n, &evsel_list, node) { + list_del_init(&pos->node); + perf_evsel__delete(pos); + } + nr_counters = 0; +} diff --git a/trunk/tools/perf/util/parse-events.h b/trunk/tools/perf/util/parse-events.h index cf7e94abb676..458e3ecf17af 100644 --- a/trunk/tools/perf/util/parse-events.h +++ b/trunk/tools/perf/util/parse-events.h @@ -9,6 +9,11 @@ struct list_head; struct perf_evsel; +extern struct list_head evsel_list; + +int perf_evsel_list__create_default(void); +void perf_evsel_list__delete(void); + struct option; struct tracepoint_path { @@ -20,6 +25,8 @@ struct tracepoint_path { extern struct tracepoint_path *tracepoint_id_to_path(u64 config); extern bool have_tracepoints(struct list_head *evlist); +extern int nr_counters; + const char *event_name(struct perf_evsel *event); extern const char *__event_name(int type, u64 config); diff --git a/trunk/tools/perf/util/probe-event.c b/trunk/tools/perf/util/probe-event.c index 9d237e3cff5d..6e29d9c9dccc 100644 --- a/trunk/tools/perf/util/probe-event.c +++ b/trunk/tools/perf/util/probe-event.c @@ -31,7 +31,6 @@ #include #include #include -#include #undef _GNU_SOURCE #include "util.h" @@ -112,25 +111,7 @@ static struct symbol *__find_kernel_function_by_name(const char *name, NULL); } -static struct map *kernel_get_module_map(const char *module) -{ - struct rb_node *nd; - struct map_groups *grp = &machine.kmaps; - - if (!module) - module = "kernel"; - - for (nd = rb_first(&grp->maps[MAP__FUNCTION]); nd; nd = rb_next(nd)) { - struct map *pos = rb_entry(nd, struct map, rb_node); - if (strncmp(pos->dso->short_name + 1, module, - pos->dso->short_name_len - 2) == 0) { - return pos; - } - } - return NULL; -} - -static struct dso *kernel_get_module_dso(const char *module) +const char *kernel_get_module_path(const char *module) { struct dso *dso; struct map *map; @@ -160,13 +141,7 @@ static struct dso *kernel_get_module_dso(const char *module) } } found: - return dso; -} - -const char *kernel_get_module_path(const char *module) -{ - struct dso *dso = kernel_get_module_dso(module); - return (dso) ? dso->long_name : NULL; + return dso->long_name; } #ifdef DWARF_SUPPORT @@ -451,14 +426,12 @@ int show_line_range(struct line_range *lr, const char *module) } static int show_available_vars_at(int fd, struct perf_probe_event *pev, - int max_vls, struct strfilter *_filter, - bool externs) + int max_vls, bool externs) { char *buf; - int ret, i, nvars; + int ret, i; struct str_node *node; struct variable_list *vls = NULL, *vl; - const char *var; buf = synthesize_perf_probe_point(&pev->point); if (!buf) @@ -466,45 +439,36 @@ static int show_available_vars_at(int fd, struct perf_probe_event *pev, pr_debug("Searching variables at %s\n", buf); ret = find_available_vars_at(fd, pev, &vls, max_vls, externs); - if (ret <= 0) { - pr_err("Failed to find variables at %s (%d)\n", buf, ret); - goto end; - } - /* Some variables are found */ - fprintf(stdout, "Available variables at %s\n", buf); - for (i = 0; i < ret; i++) { - vl = &vls[i]; - /* - * A probe point might be converted to - * several trace points. - */ - fprintf(stdout, "\t@<%s+%lu>\n", vl->point.symbol, - vl->point.offset); - free(vl->point.symbol); - nvars = 0; - if (vl->vars) { - strlist__for_each(node, vl->vars) { - var = strchr(node->s, '\t') + 1; - if (strfilter__compare(_filter, var)) { + if (ret > 0) { + /* Some variables were found */ + fprintf(stdout, "Available variables at %s\n", buf); + for (i = 0; i < ret; i++) { + vl = &vls[i]; + /* + * A probe point might be converted to + * several trace points. + */ + fprintf(stdout, "\t@<%s+%lu>\n", vl->point.symbol, + vl->point.offset); + free(vl->point.symbol); + if (vl->vars) { + strlist__for_each(node, vl->vars) fprintf(stdout, "\t\t%s\n", node->s); - nvars++; - } - } - strlist__delete(vl->vars); + strlist__delete(vl->vars); + } else + fprintf(stdout, "(No variables)\n"); } - if (nvars == 0) - fprintf(stdout, "\t\t(No matched variables)\n"); - } - free(vls); -end: + free(vls); + } else + pr_err("Failed to find variables at %s (%d)\n", buf, ret); + free(buf); return ret; } /* Show available variables on given probe point */ int show_available_vars(struct perf_probe_event *pevs, int npevs, - int max_vls, const char *module, - struct strfilter *_filter, bool externs) + int max_vls, const char *module, bool externs) { int i, fd, ret = 0; @@ -521,8 +485,7 @@ int show_available_vars(struct perf_probe_event *pevs, int npevs, setup_pager(); for (i = 0; i < npevs && ret >= 0; i++) - ret = show_available_vars_at(fd, &pevs[i], max_vls, _filter, - externs); + ret = show_available_vars_at(fd, &pevs[i], max_vls, externs); close(fd); return ret; @@ -568,9 +531,7 @@ int show_line_range(struct line_range *lr __unused, const char *module __unused) int show_available_vars(struct perf_probe_event *pevs __unused, int npevs __unused, int max_vls __unused, - const char *module __unused, - struct strfilter *filter __unused, - bool externs __unused) + const char *module __unused, bool externs __unused) { pr_warning("Debuginfo-analysis is not supported.\n"); return -ENOSYS; @@ -1951,46 +1912,4 @@ int del_perf_probe_events(struct strlist *dellist) return ret; } -/* TODO: don't use a global variable for filter ... */ -static struct strfilter *available_func_filter; -/* - * If a symbol corresponds to a function with global binding and - * matches filter return 0. For all others return 1. - */ -static int filter_available_functions(struct map *map __unused, - struct symbol *sym) -{ - if (sym->binding == STB_GLOBAL && - strfilter__compare(available_func_filter, sym->name)) - return 0; - return 1; -} - -int show_available_funcs(const char *module, struct strfilter *_filter) -{ - struct map *map; - int ret; - - setup_pager(); - - ret = init_vmlinux(); - if (ret < 0) - return ret; - - map = kernel_get_module_map(module); - if (!map) { - pr_err("Failed to find %s map.\n", (module) ? : "kernel"); - return -EINVAL; - } - available_func_filter = _filter; - if (map__load(map, filter_available_functions)) { - pr_err("Failed to load map.\n"); - return -EINVAL; - } - if (!dso__sorted_by_name(map->dso, map->type)) - dso__sort_by_name(map->dso, map->type); - - dso__fprintf_symbols_by_name(map->dso, map->type, stdout); - return 0; -} diff --git a/trunk/tools/perf/util/probe-event.h b/trunk/tools/perf/util/probe-event.h index 3434fc9d79d5..5accbedfea37 100644 --- a/trunk/tools/perf/util/probe-event.h +++ b/trunk/tools/perf/util/probe-event.h @@ -3,7 +3,6 @@ #include #include "strlist.h" -#include "strfilter.h" extern bool probe_event_dry_run; @@ -127,8 +126,7 @@ extern int show_perf_probe_events(void); extern int show_line_range(struct line_range *lr, const char *module); extern int show_available_vars(struct perf_probe_event *pevs, int npevs, int max_probe_points, const char *module, - struct strfilter *filter, bool externs); -extern int show_available_funcs(const char *module, struct strfilter *filter); + bool externs); /* Maximum index number of event-name postfix */ diff --git a/trunk/tools/perf/util/probe-finder.c b/trunk/tools/perf/util/probe-finder.c index fe461f6559f1..ab83b6ac5d65 100644 --- a/trunk/tools/perf/util/probe-finder.c +++ b/trunk/tools/perf/util/probe-finder.c @@ -33,7 +33,6 @@ #include #include -#include #include "event.h" #include "debug.h" #include "util.h" @@ -281,19 +280,6 @@ static bool die_compare_name(Dwarf_Die *dw_die, const char *tname) return name ? (strcmp(tname, name) == 0) : false; } -/* Get callsite line number of inline-function instance */ -static int die_get_call_lineno(Dwarf_Die *in_die) -{ - Dwarf_Attribute attr; - Dwarf_Word ret; - - if (!dwarf_attr(in_die, DW_AT_call_line, &attr)) - return -ENOENT; - - dwarf_formudata(&attr, &ret); - return (int)ret; -} - /* Get type die */ static Dwarf_Die *die_get_type(Dwarf_Die *vr_die, Dwarf_Die *die_mem) { @@ -334,23 +320,13 @@ static Dwarf_Die *die_get_real_type(Dwarf_Die *vr_die, Dwarf_Die *die_mem) return vr_die; } -static int die_get_attr_udata(Dwarf_Die *tp_die, unsigned int attr_name, - Dwarf_Word *result) -{ - Dwarf_Attribute attr; - - if (dwarf_attr(tp_die, attr_name, &attr) == NULL || - dwarf_formudata(&attr, result) != 0) - return -ENOENT; - - return 0; -} - static bool die_is_signed_type(Dwarf_Die *tp_die) { + Dwarf_Attribute attr; Dwarf_Word ret; - if (die_get_attr_udata(tp_die, DW_AT_encoding, &ret)) + if (dwarf_attr(tp_die, DW_AT_encoding, &attr) == NULL || + dwarf_formudata(&attr, &ret) != 0) return false; return (ret == DW_ATE_signed_char || ret == DW_ATE_signed || @@ -359,29 +335,11 @@ static bool die_is_signed_type(Dwarf_Die *tp_die) static int die_get_byte_size(Dwarf_Die *tp_die) { + Dwarf_Attribute attr; Dwarf_Word ret; - if (die_get_attr_udata(tp_die, DW_AT_byte_size, &ret)) - return 0; - - return (int)ret; -} - -static int die_get_bit_size(Dwarf_Die *tp_die) -{ - Dwarf_Word ret; - - if (die_get_attr_udata(tp_die, DW_AT_bit_size, &ret)) - return 0; - - return (int)ret; -} - -static int die_get_bit_offset(Dwarf_Die *tp_die) -{ - Dwarf_Word ret; - - if (die_get_attr_udata(tp_die, DW_AT_bit_offset, &ret)) + if (dwarf_attr(tp_die, DW_AT_byte_size, &attr) == NULL || + dwarf_formudata(&attr, &ret) != 0) return 0; return (int)ret; @@ -500,151 +458,6 @@ static Dwarf_Die *die_find_inlinefunc(Dwarf_Die *sp_die, Dwarf_Addr addr, return die_find_child(sp_die, __die_find_inline_cb, &addr, die_mem); } -/* Walker on lines (Note: line number will not be sorted) */ -typedef int (* line_walk_handler_t) (const char *fname, int lineno, - Dwarf_Addr addr, void *data); - -struct __line_walk_param { - const char *fname; - line_walk_handler_t handler; - void *data; - int retval; -}; - -static int __die_walk_funclines_cb(Dwarf_Die *in_die, void *data) -{ - struct __line_walk_param *lw = data; - Dwarf_Addr addr; - int lineno; - - if (dwarf_tag(in_die) == DW_TAG_inlined_subroutine) { - lineno = die_get_call_lineno(in_die); - if (lineno > 0 && dwarf_entrypc(in_die, &addr) == 0) { - lw->retval = lw->handler(lw->fname, lineno, addr, - lw->data); - if (lw->retval != 0) - return DIE_FIND_CB_FOUND; - } - } - return DIE_FIND_CB_SIBLING; -} - -/* Walk on lines of blocks included in given DIE */ -static int __die_walk_funclines(Dwarf_Die *sp_die, - line_walk_handler_t handler, void *data) -{ - struct __line_walk_param lw = { - .handler = handler, - .data = data, - .retval = 0, - }; - Dwarf_Die die_mem; - Dwarf_Addr addr; - int lineno; - - /* Handle function declaration line */ - lw.fname = dwarf_decl_file(sp_die); - if (lw.fname && dwarf_decl_line(sp_die, &lineno) == 0 && - dwarf_entrypc(sp_die, &addr) == 0) { - lw.retval = handler(lw.fname, lineno, addr, data); - if (lw.retval != 0) - goto done; - } - die_find_child(sp_die, __die_walk_funclines_cb, &lw, &die_mem); -done: - return lw.retval; -} - -static int __die_walk_culines_cb(Dwarf_Die *sp_die, void *data) -{ - struct __line_walk_param *lw = data; - - lw->retval = __die_walk_funclines(sp_die, lw->handler, lw->data); - if (lw->retval != 0) - return DWARF_CB_ABORT; - - return DWARF_CB_OK; -} - -/* - * Walk on lines inside given PDIE. If the PDIE is subprogram, walk only on - * the lines inside the subprogram, otherwise PDIE must be a CU DIE. - */ -static int die_walk_lines(Dwarf_Die *pdie, line_walk_handler_t handler, - void *data) -{ - Dwarf_Lines *lines; - Dwarf_Line *line; - Dwarf_Addr addr; - const char *fname; - int lineno, ret = 0; - Dwarf_Die die_mem, *cu_die; - size_t nlines, i; - - /* Get the CU die */ - if (dwarf_tag(pdie) == DW_TAG_subprogram) - cu_die = dwarf_diecu(pdie, &die_mem, NULL, NULL); - else - cu_die = pdie; - if (!cu_die) { - pr_debug2("Failed to get CU from subprogram\n"); - return -EINVAL; - } - - /* Get lines list in the CU */ - if (dwarf_getsrclines(cu_die, &lines, &nlines) != 0) { - pr_debug2("Failed to get source lines on this CU.\n"); - return -ENOENT; - } - pr_debug2("Get %zd lines from this CU\n", nlines); - - /* Walk on the lines on lines list */ - for (i = 0; i < nlines; i++) { - line = dwarf_onesrcline(lines, i); - if (line == NULL || - dwarf_lineno(line, &lineno) != 0 || - dwarf_lineaddr(line, &addr) != 0) { - pr_debug2("Failed to get line info. " - "Possible error in debuginfo.\n"); - continue; - } - /* Filter lines based on address */ - if (pdie != cu_die) - /* - * Address filtering - * The line is included in given function, and - * no inline block includes it. - */ - if (!dwarf_haspc(pdie, addr) || - die_find_inlinefunc(pdie, addr, &die_mem)) - continue; - /* Get source line */ - fname = dwarf_linesrc(line, NULL, NULL); - - ret = handler(fname, lineno, addr, data); - if (ret != 0) - return ret; - } - - /* - * Dwarf lines doesn't include function declarations and inlined - * subroutines. We have to check functions list or given function. - */ - if (pdie != cu_die) - ret = __die_walk_funclines(pdie, handler, data); - else { - struct __line_walk_param param = { - .handler = handler, - .data = data, - .retval = 0, - }; - dwarf_getfuncs(cu_die, __die_walk_culines_cb, ¶m, 0); - ret = param.retval; - } - - return ret; -} - struct __find_variable_param { const char *name; Dwarf_Addr addr; @@ -856,8 +669,6 @@ static int convert_variable_location(Dwarf_Die *vr_die, Dwarf_Addr addr, return 0; } -#define BYTES_TO_BITS(nb) ((nb) * BITS_PER_LONG / sizeof(long)) - static int convert_variable_type(Dwarf_Die *vr_die, struct probe_trace_arg *tvar, const char *cast) @@ -874,14 +685,6 @@ static int convert_variable_type(Dwarf_Die *vr_die, return (tvar->type == NULL) ? -ENOMEM : 0; } - if (die_get_bit_size(vr_die) != 0) { - /* This is a bitfield */ - ret = snprintf(buf, 16, "b%d@%d/%zd", die_get_bit_size(vr_die), - die_get_bit_offset(vr_die), - BYTES_TO_BITS(die_get_byte_size(vr_die))); - goto formatted; - } - if (die_get_real_type(vr_die, &type) == NULL) { pr_warning("Failed to get a type information of %s.\n", dwarf_diename(vr_die)); @@ -926,31 +729,29 @@ static int convert_variable_type(Dwarf_Die *vr_die, return (tvar->type == NULL) ? -ENOMEM : 0; } - ret = BYTES_TO_BITS(die_get_byte_size(&type)); - if (!ret) - /* No size ... try to use default type */ - return 0; + ret = die_get_byte_size(&type) * 8; + if (ret) { + /* Check the bitwidth */ + if (ret > MAX_BASIC_TYPE_BITS) { + pr_info("%s exceeds max-bitwidth." + " Cut down to %d bits.\n", + dwarf_diename(&type), MAX_BASIC_TYPE_BITS); + ret = MAX_BASIC_TYPE_BITS; + } - /* Check the bitwidth */ - if (ret > MAX_BASIC_TYPE_BITS) { - pr_info("%s exceeds max-bitwidth. Cut down to %d bits.\n", - dwarf_diename(&type), MAX_BASIC_TYPE_BITS); - ret = MAX_BASIC_TYPE_BITS; - } - ret = snprintf(buf, 16, "%c%d", - die_is_signed_type(&type) ? 's' : 'u', ret); - -formatted: - if (ret < 0 || ret >= 16) { - if (ret >= 16) - ret = -E2BIG; - pr_warning("Failed to convert variable type: %s\n", - strerror(-ret)); - return ret; + ret = snprintf(buf, 16, "%c%d", + die_is_signed_type(&type) ? 's' : 'u', ret); + if (ret < 0 || ret >= 16) { + if (ret >= 16) + ret = -E2BIG; + pr_warning("Failed to convert variable type: %s\n", + strerror(-ret)); + return ret; + } + tvar->type = strdup(buf); + if (tvar->type == NULL) + return -ENOMEM; } - tvar->type = strdup(buf); - if (tvar->type == NULL) - return -ENOMEM; return 0; } @@ -1249,102 +1050,157 @@ static int call_probe_finder(Dwarf_Die *sp_die, struct probe_finder *pf) return ret; } -static int probe_point_line_walker(const char *fname, int lineno, - Dwarf_Addr addr, void *data) +/* Find probe point from its line number */ +static int find_probe_point_by_line(struct probe_finder *pf) { - struct probe_finder *pf = data; - int ret; + Dwarf_Lines *lines; + Dwarf_Line *line; + size_t nlines, i; + Dwarf_Addr addr; + int lineno; + int ret = 0; - if (lineno != pf->lno || strtailcmp(fname, pf->fname) != 0) - return 0; + if (dwarf_getsrclines(&pf->cu_die, &lines, &nlines) != 0) { + pr_warning("No source lines found.\n"); + return -ENOENT; + } - pf->addr = addr; - ret = call_probe_finder(NULL, pf); + for (i = 0; i < nlines && ret == 0; i++) { + line = dwarf_onesrcline(lines, i); + if (dwarf_lineno(line, &lineno) != 0 || + lineno != pf->lno) + continue; - /* Continue if no error, because the line will be in inline function */ - return ret < 0 ?: 0; -} + /* TODO: Get fileno from line, but how? */ + if (strtailcmp(dwarf_linesrc(line, NULL, NULL), pf->fname) != 0) + continue; -/* Find probe point from its line number */ -static int find_probe_point_by_line(struct probe_finder *pf) -{ - return die_walk_lines(&pf->cu_die, probe_point_line_walker, pf); + if (dwarf_lineaddr(line, &addr) != 0) { + pr_warning("Failed to get the address of the line.\n"); + return -ENOENT; + } + pr_debug("Probe line found: line[%d]:%d addr:0x%jx\n", + (int)i, lineno, (uintmax_t)addr); + pf->addr = addr; + + ret = call_probe_finder(NULL, pf); + /* Continuing, because target line might be inlined. */ + } + return ret; } /* Find lines which match lazy pattern */ static int find_lazy_match_lines(struct list_head *head, const char *fname, const char *pat) { - FILE *fp; - char *line = NULL; - size_t line_len; - ssize_t len; - int count = 0, linenum = 1; - - fp = fopen(fname, "r"); - if (!fp) { - pr_warning("Failed to open %s: %s\n", fname, strerror(errno)); + char *fbuf, *p1, *p2; + int fd, line, nlines = -1; + struct stat st; + + fd = open(fname, O_RDONLY); + if (fd < 0) { + pr_warning("Failed to open %s: %s\n", fname, strerror(-fd)); return -errno; } - while ((len = getline(&line, &line_len, fp)) > 0) { - - if (line[len - 1] == '\n') - line[len - 1] = '\0'; - - if (strlazymatch(line, pat)) { - line_list__add_line(head, linenum); - count++; + if (fstat(fd, &st) < 0) { + pr_warning("Failed to get the size of %s: %s\n", + fname, strerror(errno)); + nlines = -errno; + goto out_close; + } + + nlines = -ENOMEM; + fbuf = malloc(st.st_size + 2); + if (fbuf == NULL) + goto out_close; + if (read(fd, fbuf, st.st_size) < 0) { + pr_warning("Failed to read %s: %s\n", fname, strerror(errno)); + nlines = -errno; + goto out_free_fbuf; + } + fbuf[st.st_size] = '\n'; /* Dummy line */ + fbuf[st.st_size + 1] = '\0'; + p1 = fbuf; + line = 1; + nlines = 0; + while ((p2 = strchr(p1, '\n')) != NULL) { + *p2 = '\0'; + if (strlazymatch(p1, pat)) { + line_list__add_line(head, line); + nlines++; } - linenum++; + line++; + p1 = p2 + 1; } - - if (ferror(fp)) - count = -errno; - free(line); - fclose(fp); - - if (count == 0) - pr_debug("No matched lines found in %s.\n", fname); - return count; -} - -static int probe_point_lazy_walker(const char *fname, int lineno, - Dwarf_Addr addr, void *data) -{ - struct probe_finder *pf = data; - int ret; - - if (!line_list__has_line(&pf->lcache, lineno) || - strtailcmp(fname, pf->fname) != 0) - return 0; - - pr_debug("Probe line found: line:%d addr:0x%llx\n", - lineno, (unsigned long long)addr); - pf->addr = addr; - ret = call_probe_finder(NULL, pf); - - /* - * Continue if no error, because the lazy pattern will match - * to other lines - */ - return ret < 0 ?: 0; +out_free_fbuf: + free(fbuf); +out_close: + close(fd); + return nlines; } /* Find probe points from lazy pattern */ static int find_probe_point_lazy(Dwarf_Die *sp_die, struct probe_finder *pf) { + Dwarf_Lines *lines; + Dwarf_Line *line; + size_t nlines, i; + Dwarf_Addr addr; + Dwarf_Die die_mem; + int lineno; int ret = 0; if (list_empty(&pf->lcache)) { /* Matching lazy line pattern */ ret = find_lazy_match_lines(&pf->lcache, pf->fname, pf->pev->point.lazy_line); - if (ret <= 0) + if (ret == 0) { + pr_debug("No matched lines found in %s.\n", pf->fname); + return 0; + } else if (ret < 0) return ret; } - return die_walk_lines(sp_die, probe_point_lazy_walker, pf); + if (dwarf_getsrclines(&pf->cu_die, &lines, &nlines) != 0) { + pr_warning("No source lines found.\n"); + return -ENOENT; + } + + for (i = 0; i < nlines && ret >= 0; i++) { + line = dwarf_onesrcline(lines, i); + + if (dwarf_lineno(line, &lineno) != 0 || + !line_list__has_line(&pf->lcache, lineno)) + continue; + + /* TODO: Get fileno from line, but how? */ + if (strtailcmp(dwarf_linesrc(line, NULL, NULL), pf->fname) != 0) + continue; + + if (dwarf_lineaddr(line, &addr) != 0) { + pr_debug("Failed to get the address of line %d.\n", + lineno); + continue; + } + if (sp_die) { + /* Address filtering 1: does sp_die include addr? */ + if (!dwarf_haspc(sp_die, addr)) + continue; + /* Address filtering 2: No child include addr? */ + if (die_find_inlinefunc(sp_die, addr, &die_mem)) + continue; + } + + pr_debug("Probe line found: line[%d]:%d addr:0x%llx\n", + (int)i, lineno, (unsigned long long)addr); + pf->addr = addr; + + ret = call_probe_finder(sp_die, pf); + /* Continuing, because target line might be inlined. */ + } + /* TODO: deallocate lines, but how? */ + return ret; } /* Callback parameter with return value */ @@ -1788,28 +1644,91 @@ static int line_range_add_line(const char *src, unsigned int lineno, return line_list__add_line(&lr->line_list, lineno); } -static int line_range_walk_cb(const char *fname, int lineno, - Dwarf_Addr addr __used, - void *data) +/* Search function declaration lines */ +static int line_range_funcdecl_cb(Dwarf_Die *sp_die, void *data) { - struct line_finder *lf = data; + struct dwarf_callback_param *param = data; + struct line_finder *lf = param->data; + const char *src; + int lineno; - if ((strtailcmp(fname, lf->fname) != 0) || + src = dwarf_decl_file(sp_die); + if (src && strtailcmp(src, lf->fname) != 0) + return DWARF_CB_OK; + + if (dwarf_decl_line(sp_die, &lineno) != 0 || (lf->lno_s > lineno || lf->lno_e < lineno)) - return 0; + return DWARF_CB_OK; - if (line_range_add_line(fname, lineno, lf->lr) < 0) - return -EINVAL; + param->retval = line_range_add_line(src, lineno, lf->lr); + if (param->retval < 0) + return DWARF_CB_ABORT; + return DWARF_CB_OK; +} - return 0; +static int find_line_range_func_decl_lines(struct line_finder *lf) +{ + struct dwarf_callback_param param = {.data = (void *)lf, .retval = 0}; + dwarf_getfuncs(&lf->cu_die, line_range_funcdecl_cb, ¶m, 0); + return param.retval; } /* Find line range from its line number */ static int find_line_range_by_line(Dwarf_Die *sp_die, struct line_finder *lf) { - int ret; + Dwarf_Lines *lines; + Dwarf_Line *line; + size_t nlines, i; + Dwarf_Addr addr; + int lineno, ret = 0; + const char *src; + Dwarf_Die die_mem; + + line_list__init(&lf->lr->line_list); + if (dwarf_getsrclines(&lf->cu_die, &lines, &nlines) != 0) { + pr_warning("No source lines found.\n"); + return -ENOENT; + } - ret = die_walk_lines(sp_die ?: &lf->cu_die, line_range_walk_cb, lf); + /* Search probable lines on lines list */ + for (i = 0; i < nlines; i++) { + line = dwarf_onesrcline(lines, i); + if (dwarf_lineno(line, &lineno) != 0 || + (lf->lno_s > lineno || lf->lno_e < lineno)) + continue; + + if (sp_die) { + /* Address filtering 1: does sp_die include addr? */ + if (dwarf_lineaddr(line, &addr) != 0 || + !dwarf_haspc(sp_die, addr)) + continue; + + /* Address filtering 2: No child include addr? */ + if (die_find_inlinefunc(sp_die, addr, &die_mem)) + continue; + } + + /* TODO: Get fileno from line, but how? */ + src = dwarf_linesrc(line, NULL, NULL); + if (strtailcmp(src, lf->fname) != 0) + continue; + + ret = line_range_add_line(src, lineno, lf->lr); + if (ret < 0) + return ret; + } + + /* + * Dwarf lines doesn't include function declarations. We have to + * check functions list or given function. + */ + if (sp_die) { + src = dwarf_decl_file(sp_die); + if (src && dwarf_decl_line(sp_die, &lineno) == 0 && + (lf->lno_s <= lineno && lf->lno_e >= lineno)) + ret = line_range_add_line(src, lineno, lf->lr); + } else + ret = find_line_range_func_decl_lines(lf); /* Update status */ if (ret >= 0) @@ -1839,6 +1758,9 @@ static int line_range_search_cb(Dwarf_Die *sp_die, void *data) struct line_finder *lf = param->data; struct line_range *lr = lf->lr; + pr_debug("find (%llx) %s\n", + (unsigned long long)dwarf_dieoffset(sp_die), + dwarf_diename(sp_die)); if (dwarf_tag(sp_die) == DW_TAG_subprogram && die_compare_name(sp_die, lr->function)) { lf->fname = dwarf_decl_file(sp_die); diff --git a/trunk/tools/perf/util/python.c b/trunk/tools/perf/util/python.c deleted file mode 100644 index 5317ef229041..000000000000 --- a/trunk/tools/perf/util/python.c +++ /dev/null @@ -1,891 +0,0 @@ -#include -#include -#include -#include -#include "evlist.h" -#include "evsel.h" -#include "event.h" -#include "cpumap.h" -#include "thread_map.h" - -struct throttle_event { - struct perf_event_header header; - u64 time; - u64 id; - u64 stream_id; -}; - -PyMODINIT_FUNC initperf(void); - -#define member_def(type, member, ptype, help) \ - { #member, ptype, \ - offsetof(struct pyrf_event, event) + offsetof(struct type, member), \ - 0, help } - -#define sample_member_def(name, member, ptype, help) \ - { #name, ptype, \ - offsetof(struct pyrf_event, sample) + offsetof(struct perf_sample, member), \ - 0, help } - -struct pyrf_event { - PyObject_HEAD - struct perf_sample sample; - union perf_event event; -}; - -#define sample_members \ - sample_member_def(sample_ip, ip, T_ULONGLONG, "event type"), \ - sample_member_def(sample_pid, pid, T_INT, "event pid"), \ - sample_member_def(sample_tid, tid, T_INT, "event tid"), \ - sample_member_def(sample_time, time, T_ULONGLONG, "event timestamp"), \ - sample_member_def(sample_addr, addr, T_ULONGLONG, "event addr"), \ - sample_member_def(sample_id, id, T_ULONGLONG, "event id"), \ - sample_member_def(sample_stream_id, stream_id, T_ULONGLONG, "event stream id"), \ - sample_member_def(sample_period, period, T_ULONGLONG, "event period"), \ - sample_member_def(sample_cpu, cpu, T_UINT, "event cpu"), - -static char pyrf_mmap_event__doc[] = PyDoc_STR("perf mmap event object."); - -static PyMemberDef pyrf_mmap_event__members[] = { - sample_members - member_def(perf_event_header, type, T_UINT, "event type"), - member_def(mmap_event, pid, T_UINT, "event pid"), - member_def(mmap_event, tid, T_UINT, "event tid"), - member_def(mmap_event, start, T_ULONGLONG, "start of the map"), - member_def(mmap_event, len, T_ULONGLONG, "map length"), - member_def(mmap_event, pgoff, T_ULONGLONG, "page offset"), - member_def(mmap_event, filename, T_STRING_INPLACE, "backing store"), - { .name = NULL, }, -}; - -static PyObject *pyrf_mmap_event__repr(struct pyrf_event *pevent) -{ - PyObject *ret; - char *s; - - if (asprintf(&s, "{ type: mmap, pid: %u, tid: %u, start: %#" PRIx64 ", " - "length: %#" PRIx64 ", offset: %#" PRIx64 ", " - "filename: %s }", - pevent->event.mmap.pid, pevent->event.mmap.tid, - pevent->event.mmap.start, pevent->event.mmap.len, - pevent->event.mmap.pgoff, pevent->event.mmap.filename) < 0) { - ret = PyErr_NoMemory(); - } else { - ret = PyString_FromString(s); - free(s); - } - return ret; -} - -static PyTypeObject pyrf_mmap_event__type = { - PyVarObject_HEAD_INIT(NULL, 0) - .tp_name = "perf.mmap_event", - .tp_basicsize = sizeof(struct pyrf_event), - .tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, - .tp_doc = pyrf_mmap_event__doc, - .tp_members = pyrf_mmap_event__members, - .tp_repr = (reprfunc)pyrf_mmap_event__repr, -}; - -static char pyrf_task_event__doc[] = PyDoc_STR("perf task (fork/exit) event object."); - -static PyMemberDef pyrf_task_event__members[] = { - sample_members - member_def(perf_event_header, type, T_UINT, "event type"), - member_def(fork_event, pid, T_UINT, "event pid"), - member_def(fork_event, ppid, T_UINT, "event ppid"), - member_def(fork_event, tid, T_UINT, "event tid"), - member_def(fork_event, ptid, T_UINT, "event ptid"), - member_def(fork_event, time, T_ULONGLONG, "timestamp"), - { .name = NULL, }, -}; - -static PyObject *pyrf_task_event__repr(struct pyrf_event *pevent) -{ - return PyString_FromFormat("{ type: %s, pid: %u, ppid: %u, tid: %u, " - "ptid: %u, time: %" PRIu64 "}", - pevent->event.header.type == PERF_RECORD_FORK ? "fork" : "exit", - pevent->event.fork.pid, - pevent->event.fork.ppid, - pevent->event.fork.tid, - pevent->event.fork.ptid, - pevent->event.fork.time); -} - -static PyTypeObject pyrf_task_event__type = { - PyVarObject_HEAD_INIT(NULL, 0) - .tp_name = "perf.task_event", - .tp_basicsize = sizeof(struct pyrf_event), - .tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, - .tp_doc = pyrf_task_event__doc, - .tp_members = pyrf_task_event__members, - .tp_repr = (reprfunc)pyrf_task_event__repr, -}; - -static char pyrf_comm_event__doc[] = PyDoc_STR("perf comm event object."); - -static PyMemberDef pyrf_comm_event__members[] = { - sample_members - member_def(perf_event_header, type, T_UINT, "event type"), - member_def(comm_event, pid, T_UINT, "event pid"), - member_def(comm_event, tid, T_UINT, "event tid"), - member_def(comm_event, comm, T_STRING_INPLACE, "process name"), - { .name = NULL, }, -}; - -static PyObject *pyrf_comm_event__repr(struct pyrf_event *pevent) -{ - return PyString_FromFormat("{ type: comm, pid: %u, tid: %u, comm: %s }", - pevent->event.comm.pid, - pevent->event.comm.tid, - pevent->event.comm.comm); -} - -static PyTypeObject pyrf_comm_event__type = { - PyVarObject_HEAD_INIT(NULL, 0) - .tp_name = "perf.comm_event", - .tp_basicsize = sizeof(struct pyrf_event), - .tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, - .tp_doc = pyrf_comm_event__doc, - .tp_members = pyrf_comm_event__members, - .tp_repr = (reprfunc)pyrf_comm_event__repr, -}; - -static char pyrf_throttle_event__doc[] = PyDoc_STR("perf throttle event object."); - -static PyMemberDef pyrf_throttle_event__members[] = { - sample_members - member_def(perf_event_header, type, T_UINT, "event type"), - member_def(throttle_event, time, T_ULONGLONG, "timestamp"), - member_def(throttle_event, id, T_ULONGLONG, "event id"), - member_def(throttle_event, stream_id, T_ULONGLONG, "event stream id"), - { .name = NULL, }, -}; - -static PyObject *pyrf_throttle_event__repr(struct pyrf_event *pevent) -{ - struct throttle_event *te = (struct throttle_event *)(&pevent->event.header + 1); - - return PyString_FromFormat("{ type: %sthrottle, time: %" PRIu64 ", id: %" PRIu64 - ", stream_id: %" PRIu64 " }", - pevent->event.header.type == PERF_RECORD_THROTTLE ? "" : "un", - te->time, te->id, te->stream_id); -} - -static PyTypeObject pyrf_throttle_event__type = { - PyVarObject_HEAD_INIT(NULL, 0) - .tp_name = "perf.throttle_event", - .tp_basicsize = sizeof(struct pyrf_event), - .tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, - .tp_doc = pyrf_throttle_event__doc, - .tp_members = pyrf_throttle_event__members, - .tp_repr = (reprfunc)pyrf_throttle_event__repr, -}; - -static int pyrf_event__setup_types(void) -{ - int err; - pyrf_mmap_event__type.tp_new = - pyrf_task_event__type.tp_new = - pyrf_comm_event__type.tp_new = - pyrf_throttle_event__type.tp_new = PyType_GenericNew; - err = PyType_Ready(&pyrf_mmap_event__type); - if (err < 0) - goto out; - err = PyType_Ready(&pyrf_task_event__type); - if (err < 0) - goto out; - err = PyType_Ready(&pyrf_comm_event__type); - if (err < 0) - goto out; - err = PyType_Ready(&pyrf_throttle_event__type); - if (err < 0) - goto out; -out: - return err; -} - -static PyTypeObject *pyrf_event__type[] = { - [PERF_RECORD_MMAP] = &pyrf_mmap_event__type, - [PERF_RECORD_LOST] = &pyrf_mmap_event__type, - [PERF_RECORD_COMM] = &pyrf_comm_event__type, - [PERF_RECORD_EXIT] = &pyrf_task_event__type, - [PERF_RECORD_THROTTLE] = &pyrf_throttle_event__type, - [PERF_RECORD_UNTHROTTLE] = &pyrf_throttle_event__type, - [PERF_RECORD_FORK] = &pyrf_task_event__type, - [PERF_RECORD_READ] = &pyrf_mmap_event__type, - [PERF_RECORD_SAMPLE] = &pyrf_mmap_event__type, -}; - -static PyObject *pyrf_event__new(union perf_event *event) -{ - struct pyrf_event *pevent; - PyTypeObject *ptype; - - if (event->header.type < PERF_RECORD_MMAP || - event->header.type > PERF_RECORD_SAMPLE) - return NULL; - - ptype = pyrf_event__type[event->header.type]; - pevent = PyObject_New(struct pyrf_event, ptype); - if (pevent != NULL) - memcpy(&pevent->event, event, event->header.size); - return (PyObject *)pevent; -} - -struct pyrf_cpu_map { - PyObject_HEAD - - struct cpu_map *cpus; -}; - -static int pyrf_cpu_map__init(struct pyrf_cpu_map *pcpus, - PyObject *args, PyObject *kwargs) -{ - static char *kwlist[] = { "cpustr", NULL, NULL, }; - char *cpustr = NULL; - - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|s", - kwlist, &cpustr)) - return -1; - - pcpus->cpus = cpu_map__new(cpustr); - if (pcpus->cpus == NULL) - return -1; - return 0; -} - -static void pyrf_cpu_map__delete(struct pyrf_cpu_map *pcpus) -{ - cpu_map__delete(pcpus->cpus); - pcpus->ob_type->tp_free((PyObject*)pcpus); -} - -static Py_ssize_t pyrf_cpu_map__length(PyObject *obj) -{ - struct pyrf_cpu_map *pcpus = (void *)obj; - - return pcpus->cpus->nr; -} - -static PyObject *pyrf_cpu_map__item(PyObject *obj, Py_ssize_t i) -{ - struct pyrf_cpu_map *pcpus = (void *)obj; - - if (i >= pcpus->cpus->nr) - return NULL; - - return Py_BuildValue("i", pcpus->cpus->map[i]); -} - -static PySequenceMethods pyrf_cpu_map__sequence_methods = { - .sq_length = pyrf_cpu_map__length, - .sq_item = pyrf_cpu_map__item, -}; - -static char pyrf_cpu_map__doc[] = PyDoc_STR("cpu map object."); - -static PyTypeObject pyrf_cpu_map__type = { - PyVarObject_HEAD_INIT(NULL, 0) - .tp_name = "perf.cpu_map", - .tp_basicsize = sizeof(struct pyrf_cpu_map), - .tp_dealloc = (destructor)pyrf_cpu_map__delete, - .tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, - .tp_doc = pyrf_cpu_map__doc, - .tp_as_sequence = &pyrf_cpu_map__sequence_methods, - .tp_init = (initproc)pyrf_cpu_map__init, -}; - -static int pyrf_cpu_map__setup_types(void) -{ - pyrf_cpu_map__type.tp_new = PyType_GenericNew; - return PyType_Ready(&pyrf_cpu_map__type); -} - -struct pyrf_thread_map { - PyObject_HEAD - - struct thread_map *threads; -}; - -static int pyrf_thread_map__init(struct pyrf_thread_map *pthreads, - PyObject *args, PyObject *kwargs) -{ - static char *kwlist[] = { "pid", "tid", NULL, NULL, }; - int pid = -1, tid = -1; - - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|ii", - kwlist, &pid, &tid)) - return -1; - - pthreads->threads = thread_map__new(pid, tid); - if (pthreads->threads == NULL) - return -1; - return 0; -} - -static void pyrf_thread_map__delete(struct pyrf_thread_map *pthreads) -{ - thread_map__delete(pthreads->threads); - pthreads->ob_type->tp_free((PyObject*)pthreads); -} - -static Py_ssize_t pyrf_thread_map__length(PyObject *obj) -{ - struct pyrf_thread_map *pthreads = (void *)obj; - - return pthreads->threads->nr; -} - -static PyObject *pyrf_thread_map__item(PyObject *obj, Py_ssize_t i) -{ - struct pyrf_thread_map *pthreads = (void *)obj; - - if (i >= pthreads->threads->nr) - return NULL; - - return Py_BuildValue("i", pthreads->threads->map[i]); -} - -static PySequenceMethods pyrf_thread_map__sequence_methods = { - .sq_length = pyrf_thread_map__length, - .sq_item = pyrf_thread_map__item, -}; - -static char pyrf_thread_map__doc[] = PyDoc_STR("thread map object."); - -static PyTypeObject pyrf_thread_map__type = { - PyVarObject_HEAD_INIT(NULL, 0) - .tp_name = "perf.thread_map", - .tp_basicsize = sizeof(struct pyrf_thread_map), - .tp_dealloc = (destructor)pyrf_thread_map__delete, - .tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, - .tp_doc = pyrf_thread_map__doc, - .tp_as_sequence = &pyrf_thread_map__sequence_methods, - .tp_init = (initproc)pyrf_thread_map__init, -}; - -static int pyrf_thread_map__setup_types(void) -{ - pyrf_thread_map__type.tp_new = PyType_GenericNew; - return PyType_Ready(&pyrf_thread_map__type); -} - -struct pyrf_evsel { - PyObject_HEAD - - struct perf_evsel evsel; -}; - -static int pyrf_evsel__init(struct pyrf_evsel *pevsel, - PyObject *args, PyObject *kwargs) -{ - struct perf_event_attr attr = { - .type = PERF_TYPE_HARDWARE, - .config = PERF_COUNT_HW_CPU_CYCLES, - .sample_type = PERF_SAMPLE_PERIOD | PERF_SAMPLE_TID, - }; - static char *kwlist[] = { - "type", - "config", - "sample_freq", - "sample_period", - "sample_type", - "read_format", - "disabled", - "inherit", - "pinned", - "exclusive", - "exclude_user", - "exclude_kernel", - "exclude_hv", - "exclude_idle", - "mmap", - "comm", - "freq", - "inherit_stat", - "enable_on_exec", - "task", - "watermark", - "precise_ip", - "mmap_data", - "sample_id_all", - "wakeup_events", - "bp_type", - "bp_addr", - "bp_len", NULL, NULL, }; - u64 sample_period = 0; - u32 disabled = 0, - inherit = 0, - pinned = 0, - exclusive = 0, - exclude_user = 0, - exclude_kernel = 0, - exclude_hv = 0, - exclude_idle = 0, - mmap = 0, - comm = 0, - freq = 1, - inherit_stat = 0, - enable_on_exec = 0, - task = 0, - watermark = 0, - precise_ip = 0, - mmap_data = 0, - sample_id_all = 1; - int idx = 0; - - if (!PyArg_ParseTupleAndKeywords(args, kwargs, - "|iKiKKiiiiiiiiiiiiiiiiiiiiiKK", kwlist, - &attr.type, &attr.config, &attr.sample_freq, - &sample_period, &attr.sample_type, - &attr.read_format, &disabled, &inherit, - &pinned, &exclusive, &exclude_user, - &exclude_kernel, &exclude_hv, &exclude_idle, - &mmap, &comm, &freq, &inherit_stat, - &enable_on_exec, &task, &watermark, - &precise_ip, &mmap_data, &sample_id_all, - &attr.wakeup_events, &attr.bp_type, - &attr.bp_addr, &attr.bp_len, &idx)) - return -1; - - /* union... */ - if (sample_period != 0) { - if (attr.sample_freq != 0) - return -1; /* FIXME: throw right exception */ - attr.sample_period = sample_period; - } - - /* Bitfields */ - attr.disabled = disabled; - attr.inherit = inherit; - attr.pinned = pinned; - attr.exclusive = exclusive; - attr.exclude_user = exclude_user; - attr.exclude_kernel = exclude_kernel; - attr.exclude_hv = exclude_hv; - attr.exclude_idle = exclude_idle; - attr.mmap = mmap; - attr.comm = comm; - attr.freq = freq; - attr.inherit_stat = inherit_stat; - attr.enable_on_exec = enable_on_exec; - attr.task = task; - attr.watermark = watermark; - attr.precise_ip = precise_ip; - attr.mmap_data = mmap_data; - attr.sample_id_all = sample_id_all; - - perf_evsel__init(&pevsel->evsel, &attr, idx); - return 0; -} - -static void pyrf_evsel__delete(struct pyrf_evsel *pevsel) -{ - perf_evsel__exit(&pevsel->evsel); - pevsel->ob_type->tp_free((PyObject*)pevsel); -} - -static PyObject *pyrf_evsel__open(struct pyrf_evsel *pevsel, - PyObject *args, PyObject *kwargs) -{ - struct perf_evsel *evsel = &pevsel->evsel; - struct cpu_map *cpus = NULL; - struct thread_map *threads = NULL; - PyObject *pcpus = NULL, *pthreads = NULL; - int group = 0, overwrite = 0; - static char *kwlist[] = {"cpus", "threads", "group", "overwrite", NULL, NULL}; - - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|OOii", kwlist, - &pcpus, &pthreads, &group, &overwrite)) - return NULL; - - if (pthreads != NULL) - threads = ((struct pyrf_thread_map *)pthreads)->threads; - - if (pcpus != NULL) - cpus = ((struct pyrf_cpu_map *)pcpus)->cpus; - - if (perf_evsel__open(evsel, cpus, threads, group, overwrite) < 0) { - PyErr_SetFromErrno(PyExc_OSError); - return NULL; - } - - Py_INCREF(Py_None); - return Py_None; -} - -static PyMethodDef pyrf_evsel__methods[] = { - { - .ml_name = "open", - .ml_meth = (PyCFunction)pyrf_evsel__open, - .ml_flags = METH_VARARGS | METH_KEYWORDS, - .ml_doc = PyDoc_STR("open the event selector file descriptor table.") - }, - { .ml_name = NULL, } -}; - -static char pyrf_evsel__doc[] = PyDoc_STR("perf event selector list object."); - -static PyTypeObject pyrf_evsel__type = { - PyVarObject_HEAD_INIT(NULL, 0) - .tp_name = "perf.evsel", - .tp_basicsize = sizeof(struct pyrf_evsel), - .tp_dealloc = (destructor)pyrf_evsel__delete, - .tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, - .tp_doc = pyrf_evsel__doc, - .tp_methods = pyrf_evsel__methods, - .tp_init = (initproc)pyrf_evsel__init, -}; - -static int pyrf_evsel__setup_types(void) -{ - pyrf_evsel__type.tp_new = PyType_GenericNew; - return PyType_Ready(&pyrf_evsel__type); -} - -struct pyrf_evlist { - PyObject_HEAD - - struct perf_evlist evlist; -}; - -static int pyrf_evlist__init(struct pyrf_evlist *pevlist, - PyObject *args, PyObject *kwargs __used) -{ - PyObject *pcpus = NULL, *pthreads = NULL; - struct cpu_map *cpus; - struct thread_map *threads; - - if (!PyArg_ParseTuple(args, "OO", &pcpus, &pthreads)) - return -1; - - threads = ((struct pyrf_thread_map *)pthreads)->threads; - cpus = ((struct pyrf_cpu_map *)pcpus)->cpus; - perf_evlist__init(&pevlist->evlist, cpus, threads); - return 0; -} - -static void pyrf_evlist__delete(struct pyrf_evlist *pevlist) -{ - perf_evlist__exit(&pevlist->evlist); - pevlist->ob_type->tp_free((PyObject*)pevlist); -} - -static PyObject *pyrf_evlist__mmap(struct pyrf_evlist *pevlist, - PyObject *args, PyObject *kwargs) -{ - struct perf_evlist *evlist = &pevlist->evlist; - static char *kwlist[] = {"pages", "overwrite", - NULL, NULL}; - int pages = 128, overwrite = false; - - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|ii", kwlist, - &pages, &overwrite)) - return NULL; - - if (perf_evlist__mmap(evlist, pages, overwrite) < 0) { - PyErr_SetFromErrno(PyExc_OSError); - return NULL; - } - - Py_INCREF(Py_None); - return Py_None; -} - -static PyObject *pyrf_evlist__poll(struct pyrf_evlist *pevlist, - PyObject *args, PyObject *kwargs) -{ - struct perf_evlist *evlist = &pevlist->evlist; - static char *kwlist[] = {"timeout", NULL, NULL}; - int timeout = -1, n; - - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i", kwlist, &timeout)) - return NULL; - - n = poll(evlist->pollfd, evlist->nr_fds, timeout); - if (n < 0) { - PyErr_SetFromErrno(PyExc_OSError); - return NULL; - } - - return Py_BuildValue("i", n); -} - -static PyObject *pyrf_evlist__get_pollfd(struct pyrf_evlist *pevlist, - PyObject *args __used, PyObject *kwargs __used) -{ - struct perf_evlist *evlist = &pevlist->evlist; - PyObject *list = PyList_New(0); - int i; - - for (i = 0; i < evlist->nr_fds; ++i) { - PyObject *file; - FILE *fp = fdopen(evlist->pollfd[i].fd, "r"); - - if (fp == NULL) - goto free_list; - - file = PyFile_FromFile(fp, "perf", "r", NULL); - if (file == NULL) - goto free_list; - - if (PyList_Append(list, file) != 0) { - Py_DECREF(file); - goto free_list; - } - - Py_DECREF(file); - } - - return list; -free_list: - return PyErr_NoMemory(); -} - - -static PyObject *pyrf_evlist__add(struct pyrf_evlist *pevlist, - PyObject *args, PyObject *kwargs __used) -{ - struct perf_evlist *evlist = &pevlist->evlist; - PyObject *pevsel; - struct perf_evsel *evsel; - - if (!PyArg_ParseTuple(args, "O", &pevsel)) - return NULL; - - Py_INCREF(pevsel); - evsel = &((struct pyrf_evsel *)pevsel)->evsel; - evsel->idx = evlist->nr_entries; - perf_evlist__add(evlist, evsel); - - return Py_BuildValue("i", evlist->nr_entries); -} - -static PyObject *pyrf_evlist__read_on_cpu(struct pyrf_evlist *pevlist, - PyObject *args, PyObject *kwargs) -{ - struct perf_evlist *evlist = &pevlist->evlist; - union perf_event *event; - int sample_id_all = 1, cpu; - static char *kwlist[] = {"sample_id_all", NULL, NULL}; - - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|i", kwlist, - &cpu, &sample_id_all)) - return NULL; - - event = perf_evlist__read_on_cpu(evlist, cpu); - if (event != NULL) { - struct perf_evsel *first; - PyObject *pyevent = pyrf_event__new(event); - struct pyrf_event *pevent = (struct pyrf_event *)pyevent; - - if (pyevent == NULL) - return PyErr_NoMemory(); - - first = list_entry(evlist->entries.next, struct perf_evsel, node); - perf_event__parse_sample(event, first->attr.sample_type, sample_id_all, - &pevent->sample); - return pyevent; - } - - Py_INCREF(Py_None); - return Py_None; -} - -static PyMethodDef pyrf_evlist__methods[] = { - { - .ml_name = "mmap", - .ml_meth = (PyCFunction)pyrf_evlist__mmap, - .ml_flags = METH_VARARGS | METH_KEYWORDS, - .ml_doc = PyDoc_STR("mmap the file descriptor table.") - }, - { - .ml_name = "poll", - .ml_meth = (PyCFunction)pyrf_evlist__poll, - .ml_flags = METH_VARARGS | METH_KEYWORDS, - .ml_doc = PyDoc_STR("poll the file descriptor table.") - }, - { - .ml_name = "get_pollfd", - .ml_meth = (PyCFunction)pyrf_evlist__get_pollfd, - .ml_flags = METH_VARARGS | METH_KEYWORDS, - .ml_doc = PyDoc_STR("get the poll file descriptor table.") - }, - { - .ml_name = "add", - .ml_meth = (PyCFunction)pyrf_evlist__add, - .ml_flags = METH_VARARGS | METH_KEYWORDS, - .ml_doc = PyDoc_STR("adds an event selector to the list.") - }, - { - .ml_name = "read_on_cpu", - .ml_meth = (PyCFunction)pyrf_evlist__read_on_cpu, - .ml_flags = METH_VARARGS | METH_KEYWORDS, - .ml_doc = PyDoc_STR("reads an event.") - }, - { .ml_name = NULL, } -}; - -static Py_ssize_t pyrf_evlist__length(PyObject *obj) -{ - struct pyrf_evlist *pevlist = (void *)obj; - - return pevlist->evlist.nr_entries; -} - -static PyObject *pyrf_evlist__item(PyObject *obj, Py_ssize_t i) -{ - struct pyrf_evlist *pevlist = (void *)obj; - struct perf_evsel *pos; - - if (i >= pevlist->evlist.nr_entries) - return NULL; - - list_for_each_entry(pos, &pevlist->evlist.entries, node) - if (i-- == 0) - break; - - return Py_BuildValue("O", container_of(pos, struct pyrf_evsel, evsel)); -} - -static PySequenceMethods pyrf_evlist__sequence_methods = { - .sq_length = pyrf_evlist__length, - .sq_item = pyrf_evlist__item, -}; - -static char pyrf_evlist__doc[] = PyDoc_STR("perf event selector list object."); - -static PyTypeObject pyrf_evlist__type = { - PyVarObject_HEAD_INIT(NULL, 0) - .tp_name = "perf.evlist", - .tp_basicsize = sizeof(struct pyrf_evlist), - .tp_dealloc = (destructor)pyrf_evlist__delete, - .tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, - .tp_as_sequence = &pyrf_evlist__sequence_methods, - .tp_doc = pyrf_evlist__doc, - .tp_methods = pyrf_evlist__methods, - .tp_init = (initproc)pyrf_evlist__init, -}; - -static int pyrf_evlist__setup_types(void) -{ - pyrf_evlist__type.tp_new = PyType_GenericNew; - return PyType_Ready(&pyrf_evlist__type); -} - -static struct { - const char *name; - int value; -} perf__constants[] = { - { "TYPE_HARDWARE", PERF_TYPE_HARDWARE }, - { "TYPE_SOFTWARE", PERF_TYPE_SOFTWARE }, - { "TYPE_TRACEPOINT", PERF_TYPE_TRACEPOINT }, - { "TYPE_HW_CACHE", PERF_TYPE_HW_CACHE }, - { "TYPE_RAW", PERF_TYPE_RAW }, - { "TYPE_BREAKPOINT", PERF_TYPE_BREAKPOINT }, - - { "COUNT_HW_CPU_CYCLES", PERF_COUNT_HW_CPU_CYCLES }, - { "COUNT_HW_INSTRUCTIONS", PERF_COUNT_HW_INSTRUCTIONS }, - { "COUNT_HW_CACHE_REFERENCES", PERF_COUNT_HW_CACHE_REFERENCES }, - { "COUNT_HW_CACHE_MISSES", PERF_COUNT_HW_CACHE_MISSES }, - { "COUNT_HW_BRANCH_INSTRUCTIONS", PERF_COUNT_HW_BRANCH_INSTRUCTIONS }, - { "COUNT_HW_BRANCH_MISSES", PERF_COUNT_HW_BRANCH_MISSES }, - { "COUNT_HW_BUS_CYCLES", PERF_COUNT_HW_BUS_CYCLES }, - { "COUNT_HW_CACHE_L1D", PERF_COUNT_HW_CACHE_L1D }, - { "COUNT_HW_CACHE_L1I", PERF_COUNT_HW_CACHE_L1I }, - { "COUNT_HW_CACHE_LL", PERF_COUNT_HW_CACHE_LL }, - { "COUNT_HW_CACHE_DTLB", PERF_COUNT_HW_CACHE_DTLB }, - { "COUNT_HW_CACHE_ITLB", PERF_COUNT_HW_CACHE_ITLB }, - { "COUNT_HW_CACHE_BPU", PERF_COUNT_HW_CACHE_BPU }, - { "COUNT_HW_CACHE_OP_READ", PERF_COUNT_HW_CACHE_OP_READ }, - { "COUNT_HW_CACHE_OP_WRITE", PERF_COUNT_HW_CACHE_OP_WRITE }, - { "COUNT_HW_CACHE_OP_PREFETCH", PERF_COUNT_HW_CACHE_OP_PREFETCH }, - { "COUNT_HW_CACHE_RESULT_ACCESS", PERF_COUNT_HW_CACHE_RESULT_ACCESS }, - { "COUNT_HW_CACHE_RESULT_MISS", PERF_COUNT_HW_CACHE_RESULT_MISS }, - - { "COUNT_SW_CPU_CLOCK", PERF_COUNT_SW_CPU_CLOCK }, - { "COUNT_SW_TASK_CLOCK", PERF_COUNT_SW_TASK_CLOCK }, - { "COUNT_SW_PAGE_FAULTS", PERF_COUNT_SW_PAGE_FAULTS }, - { "COUNT_SW_CONTEXT_SWITCHES", PERF_COUNT_SW_CONTEXT_SWITCHES }, - { "COUNT_SW_CPU_MIGRATIONS", PERF_COUNT_SW_CPU_MIGRATIONS }, - { "COUNT_SW_PAGE_FAULTS_MIN", PERF_COUNT_SW_PAGE_FAULTS_MIN }, - { "COUNT_SW_PAGE_FAULTS_MAJ", PERF_COUNT_SW_PAGE_FAULTS_MAJ }, - { "COUNT_SW_ALIGNMENT_FAULTS", PERF_COUNT_SW_ALIGNMENT_FAULTS }, - { "COUNT_SW_EMULATION_FAULTS", PERF_COUNT_SW_EMULATION_FAULTS }, - - { "SAMPLE_IP", PERF_SAMPLE_IP }, - { "SAMPLE_TID", PERF_SAMPLE_TID }, - { "SAMPLE_TIME", PERF_SAMPLE_TIME }, - { "SAMPLE_ADDR", PERF_SAMPLE_ADDR }, - { "SAMPLE_READ", PERF_SAMPLE_READ }, - { "SAMPLE_CALLCHAIN", PERF_SAMPLE_CALLCHAIN }, - { "SAMPLE_ID", PERF_SAMPLE_ID }, - { "SAMPLE_CPU", PERF_SAMPLE_CPU }, - { "SAMPLE_PERIOD", PERF_SAMPLE_PERIOD }, - { "SAMPLE_STREAM_ID", PERF_SAMPLE_STREAM_ID }, - { "SAMPLE_RAW", PERF_SAMPLE_RAW }, - - { "FORMAT_TOTAL_TIME_ENABLED", PERF_FORMAT_TOTAL_TIME_ENABLED }, - { "FORMAT_TOTAL_TIME_RUNNING", PERF_FORMAT_TOTAL_TIME_RUNNING }, - { "FORMAT_ID", PERF_FORMAT_ID }, - { "FORMAT_GROUP", PERF_FORMAT_GROUP }, - - { "RECORD_MMAP", PERF_RECORD_MMAP }, - { "RECORD_LOST", PERF_RECORD_LOST }, - { "RECORD_COMM", PERF_RECORD_COMM }, - { "RECORD_EXIT", PERF_RECORD_EXIT }, - { "RECORD_THROTTLE", PERF_RECORD_THROTTLE }, - { "RECORD_UNTHROTTLE", PERF_RECORD_UNTHROTTLE }, - { "RECORD_FORK", PERF_RECORD_FORK }, - { "RECORD_READ", PERF_RECORD_READ }, - { "RECORD_SAMPLE", PERF_RECORD_SAMPLE }, - { .name = NULL, }, -}; - -static PyMethodDef perf__methods[] = { - { .ml_name = NULL, } -}; - -PyMODINIT_FUNC initperf(void) -{ - PyObject *obj; - int i; - PyObject *dict, *module = Py_InitModule("perf", perf__methods); - - if (module == NULL || - pyrf_event__setup_types() < 0 || - pyrf_evlist__setup_types() < 0 || - pyrf_evsel__setup_types() < 0 || - pyrf_thread_map__setup_types() < 0 || - pyrf_cpu_map__setup_types() < 0) - return; - - Py_INCREF(&pyrf_evlist__type); - PyModule_AddObject(module, "evlist", (PyObject*)&pyrf_evlist__type); - - Py_INCREF(&pyrf_evsel__type); - PyModule_AddObject(module, "evsel", (PyObject*)&pyrf_evsel__type); - - Py_INCREF(&pyrf_thread_map__type); - PyModule_AddObject(module, "thread_map", (PyObject*)&pyrf_thread_map__type); - - Py_INCREF(&pyrf_cpu_map__type); - PyModule_AddObject(module, "cpu_map", (PyObject*)&pyrf_cpu_map__type); - - dict = PyModule_GetDict(module); - if (dict == NULL) - goto error; - - for (i = 0; perf__constants[i].name != NULL; i++) { - obj = PyInt_FromLong(perf__constants[i].value); - if (obj == NULL) - goto error; - PyDict_SetItemString(dict, perf__constants[i].name, obj); - Py_DECREF(obj); - } - -error: - if (PyErr_Occurred()) - PyErr_SetString(PyExc_ImportError, "perf: Init failed!"); -} diff --git a/trunk/tools/perf/util/scripting-engines/trace-event-python.c b/trunk/tools/perf/util/scripting-engines/trace-event-python.c index 2040b8538527..c6d99334bdfa 100644 --- a/trunk/tools/perf/util/scripting-engines/trace-event-python.c +++ b/trunk/tools/perf/util/scripting-engines/trace-event-python.c @@ -248,7 +248,8 @@ static void python_process_event(int cpu, void *data, context = PyCObject_FromVoidPtr(scripting_context, NULL); PyTuple_SetItem(t, n++, PyString_FromString(handler_name)); - PyTuple_SetItem(t, n++, context); + PyTuple_SetItem(t, n++, + PyCObject_FromVoidPtr(scripting_context, NULL)); if (handler) { PyTuple_SetItem(t, n++, PyInt_FromLong(cpu)); diff --git a/trunk/tools/perf/util/session.c b/trunk/tools/perf/util/session.c index a3a871f7bda3..105f00bfd555 100644 --- a/trunk/tools/perf/util/session.c +++ b/trunk/tools/perf/util/session.c @@ -67,7 +67,7 @@ static int perf_session__open(struct perf_session *self, bool force) static void perf_session__id_header_size(struct perf_session *session) { - struct perf_sample *data; + struct sample_data *data; u64 sample_type = session->sample_type; u16 size = 0; @@ -165,7 +165,7 @@ struct perf_session *perf_session__new(const char *filename, int mode, } else if (mode == O_WRONLY) { /* * In O_RDONLY mode this will be performed when reading the - * kernel MMAP event, in perf_event__process_mmap(). + * kernel MMAP event, in event__process_mmap(). */ if (perf_session__create_kernel_maps(self) < 0) goto out_delete; @@ -242,16 +242,17 @@ static bool symbol__match_parent_regex(struct symbol *sym) return 0; } -int perf_session__resolve_callchain(struct perf_session *self, - struct thread *thread, - struct ip_callchain *chain, - struct symbol **parent) +struct map_symbol *perf_session__resolve_callchain(struct perf_session *self, + struct thread *thread, + struct ip_callchain *chain, + struct symbol **parent) { u8 cpumode = PERF_RECORD_MISC_USER; unsigned int i; - int err; + struct map_symbol *syms = calloc(chain->nr, sizeof(*syms)); - callchain_cursor_reset(&self->callchain_cursor); + if (!syms) + return NULL; for (i = 0; i < chain->nr; i++) { u64 ip = chain->ips[i]; @@ -280,33 +281,30 @@ int perf_session__resolve_callchain(struct perf_session *self, *parent = al.sym; if (!symbol_conf.use_callchain) break; + syms[i].map = al.map; + syms[i].sym = al.sym; } - - err = callchain_cursor_append(&self->callchain_cursor, - ip, al.map, al.sym); - if (err) - return err; } - return 0; + return syms; } -static int process_event_synth_stub(union perf_event *event __used, +static int process_event_synth_stub(event_t *event __used, struct perf_session *session __used) { dump_printf(": unhandled!\n"); return 0; } -static int process_event_stub(union perf_event *event __used, - struct perf_sample *sample __used, +static int process_event_stub(event_t *event __used, + struct sample_data *sample __used, struct perf_session *session __used) { dump_printf(": unhandled!\n"); return 0; } -static int process_finished_round_stub(union perf_event *event __used, +static int process_finished_round_stub(event_t *event __used, struct perf_session *session __used, struct perf_event_ops *ops __used) { @@ -314,7 +312,7 @@ static int process_finished_round_stub(union perf_event *event __used, return 0; } -static int process_finished_round(union perf_event *event, +static int process_finished_round(event_t *event, struct perf_session *session, struct perf_event_ops *ops); @@ -331,7 +329,7 @@ static void perf_event_ops__fill_defaults(struct perf_event_ops *handler) if (handler->exit == NULL) handler->exit = process_event_stub; if (handler->lost == NULL) - handler->lost = perf_event__process_lost; + handler->lost = event__process_lost; if (handler->read == NULL) handler->read = process_event_stub; if (handler->throttle == NULL) @@ -365,98 +363,98 @@ void mem_bswap_64(void *src, int byte_size) } } -static void perf_event__all64_swap(union perf_event *event) +static void event__all64_swap(event_t *self) { - struct perf_event_header *hdr = &event->header; - mem_bswap_64(hdr + 1, event->header.size - sizeof(*hdr)); + struct perf_event_header *hdr = &self->header; + mem_bswap_64(hdr + 1, self->header.size - sizeof(*hdr)); } -static void perf_event__comm_swap(union perf_event *event) +static void event__comm_swap(event_t *self) { - event->comm.pid = bswap_32(event->comm.pid); - event->comm.tid = bswap_32(event->comm.tid); + self->comm.pid = bswap_32(self->comm.pid); + self->comm.tid = bswap_32(self->comm.tid); } -static void perf_event__mmap_swap(union perf_event *event) +static void event__mmap_swap(event_t *self) { - event->mmap.pid = bswap_32(event->mmap.pid); - event->mmap.tid = bswap_32(event->mmap.tid); - event->mmap.start = bswap_64(event->mmap.start); - event->mmap.len = bswap_64(event->mmap.len); - event->mmap.pgoff = bswap_64(event->mmap.pgoff); + self->mmap.pid = bswap_32(self->mmap.pid); + self->mmap.tid = bswap_32(self->mmap.tid); + self->mmap.start = bswap_64(self->mmap.start); + self->mmap.len = bswap_64(self->mmap.len); + self->mmap.pgoff = bswap_64(self->mmap.pgoff); } -static void perf_event__task_swap(union perf_event *event) +static void event__task_swap(event_t *self) { - event->fork.pid = bswap_32(event->fork.pid); - event->fork.tid = bswap_32(event->fork.tid); - event->fork.ppid = bswap_32(event->fork.ppid); - event->fork.ptid = bswap_32(event->fork.ptid); - event->fork.time = bswap_64(event->fork.time); + self->fork.pid = bswap_32(self->fork.pid); + self->fork.tid = bswap_32(self->fork.tid); + self->fork.ppid = bswap_32(self->fork.ppid); + self->fork.ptid = bswap_32(self->fork.ptid); + self->fork.time = bswap_64(self->fork.time); } -static void perf_event__read_swap(union perf_event *event) +static void event__read_swap(event_t *self) { - event->read.pid = bswap_32(event->read.pid); - event->read.tid = bswap_32(event->read.tid); - event->read.value = bswap_64(event->read.value); - event->read.time_enabled = bswap_64(event->read.time_enabled); - event->read.time_running = bswap_64(event->read.time_running); - event->read.id = bswap_64(event->read.id); + self->read.pid = bswap_32(self->read.pid); + self->read.tid = bswap_32(self->read.tid); + self->read.value = bswap_64(self->read.value); + self->read.time_enabled = bswap_64(self->read.time_enabled); + self->read.time_running = bswap_64(self->read.time_running); + self->read.id = bswap_64(self->read.id); } -static void perf_event__attr_swap(union perf_event *event) +static void event__attr_swap(event_t *self) { size_t size; - event->attr.attr.type = bswap_32(event->attr.attr.type); - event->attr.attr.size = bswap_32(event->attr.attr.size); - event->attr.attr.config = bswap_64(event->attr.attr.config); - event->attr.attr.sample_period = bswap_64(event->attr.attr.sample_period); - event->attr.attr.sample_type = bswap_64(event->attr.attr.sample_type); - event->attr.attr.read_format = bswap_64(event->attr.attr.read_format); - event->attr.attr.wakeup_events = bswap_32(event->attr.attr.wakeup_events); - event->attr.attr.bp_type = bswap_32(event->attr.attr.bp_type); - event->attr.attr.bp_addr = bswap_64(event->attr.attr.bp_addr); - event->attr.attr.bp_len = bswap_64(event->attr.attr.bp_len); - - size = event->header.size; - size -= (void *)&event->attr.id - (void *)event; - mem_bswap_64(event->attr.id, size); + self->attr.attr.type = bswap_32(self->attr.attr.type); + self->attr.attr.size = bswap_32(self->attr.attr.size); + self->attr.attr.config = bswap_64(self->attr.attr.config); + self->attr.attr.sample_period = bswap_64(self->attr.attr.sample_period); + self->attr.attr.sample_type = bswap_64(self->attr.attr.sample_type); + self->attr.attr.read_format = bswap_64(self->attr.attr.read_format); + self->attr.attr.wakeup_events = bswap_32(self->attr.attr.wakeup_events); + self->attr.attr.bp_type = bswap_32(self->attr.attr.bp_type); + self->attr.attr.bp_addr = bswap_64(self->attr.attr.bp_addr); + self->attr.attr.bp_len = bswap_64(self->attr.attr.bp_len); + + size = self->header.size; + size -= (void *)&self->attr.id - (void *)self; + mem_bswap_64(self->attr.id, size); } -static void perf_event__event_type_swap(union perf_event *event) +static void event__event_type_swap(event_t *self) { - event->event_type.event_type.event_id = - bswap_64(event->event_type.event_type.event_id); + self->event_type.event_type.event_id = + bswap_64(self->event_type.event_type.event_id); } -static void perf_event__tracing_data_swap(union perf_event *event) +static void event__tracing_data_swap(event_t *self) { - event->tracing_data.size = bswap_32(event->tracing_data.size); + self->tracing_data.size = bswap_32(self->tracing_data.size); } -typedef void (*perf_event__swap_op)(union perf_event *event); - -static perf_event__swap_op perf_event__swap_ops[] = { - [PERF_RECORD_MMAP] = perf_event__mmap_swap, - [PERF_RECORD_COMM] = perf_event__comm_swap, - [PERF_RECORD_FORK] = perf_event__task_swap, - [PERF_RECORD_EXIT] = perf_event__task_swap, - [PERF_RECORD_LOST] = perf_event__all64_swap, - [PERF_RECORD_READ] = perf_event__read_swap, - [PERF_RECORD_SAMPLE] = perf_event__all64_swap, - [PERF_RECORD_HEADER_ATTR] = perf_event__attr_swap, - [PERF_RECORD_HEADER_EVENT_TYPE] = perf_event__event_type_swap, - [PERF_RECORD_HEADER_TRACING_DATA] = perf_event__tracing_data_swap, - [PERF_RECORD_HEADER_BUILD_ID] = NULL, - [PERF_RECORD_HEADER_MAX] = NULL, +typedef void (*event__swap_op)(event_t *self); + +static event__swap_op event__swap_ops[] = { + [PERF_RECORD_MMAP] = event__mmap_swap, + [PERF_RECORD_COMM] = event__comm_swap, + [PERF_RECORD_FORK] = event__task_swap, + [PERF_RECORD_EXIT] = event__task_swap, + [PERF_RECORD_LOST] = event__all64_swap, + [PERF_RECORD_READ] = event__read_swap, + [PERF_RECORD_SAMPLE] = event__all64_swap, + [PERF_RECORD_HEADER_ATTR] = event__attr_swap, + [PERF_RECORD_HEADER_EVENT_TYPE] = event__event_type_swap, + [PERF_RECORD_HEADER_TRACING_DATA] = event__tracing_data_swap, + [PERF_RECORD_HEADER_BUILD_ID] = NULL, + [PERF_RECORD_HEADER_MAX] = NULL, }; struct sample_queue { u64 timestamp; u64 file_offset; - union perf_event *event; + event_t *event; struct list_head list; }; @@ -474,8 +472,8 @@ static void perf_session_free_sample_buffers(struct perf_session *session) } static int perf_session_deliver_event(struct perf_session *session, - union perf_event *event, - struct perf_sample *sample, + event_t *event, + struct sample_data *sample, struct perf_event_ops *ops, u64 file_offset); @@ -485,7 +483,7 @@ static void flush_sample_queue(struct perf_session *s, struct ordered_samples *os = &s->ordered_samples; struct list_head *head = &os->samples; struct sample_queue *tmp, *iter; - struct perf_sample sample; + struct sample_data sample; u64 limit = os->next_flush; u64 last_ts = os->last_sample ? os->last_sample->timestamp : 0ULL; @@ -496,7 +494,7 @@ static void flush_sample_queue(struct perf_session *s, if (iter->timestamp > limit) break; - perf_session__parse_sample(s, iter->event, &sample); + event__parse_sample(iter->event, s, &sample); perf_session_deliver_event(s, iter->event, &sample, ops, iter->file_offset); @@ -552,7 +550,7 @@ static void flush_sample_queue(struct perf_session *s, * Flush every events below timestamp 7 * etc... */ -static int process_finished_round(union perf_event *event __used, +static int process_finished_round(event_t *event __used, struct perf_session *session, struct perf_event_ops *ops) { @@ -609,12 +607,12 @@ static void __queue_event(struct sample_queue *new, struct perf_session *s) #define MAX_SAMPLE_BUFFER (64 * 1024 / sizeof(struct sample_queue)) -static int perf_session_queue_event(struct perf_session *s, union perf_event *event, - struct perf_sample *sample, u64 file_offset) +static int perf_session_queue_event(struct perf_session *s, event_t *event, + struct sample_data *data, u64 file_offset) { struct ordered_samples *os = &s->ordered_samples; struct list_head *sc = &os->sample_cache; - u64 timestamp = sample->time; + u64 timestamp = data->time; struct sample_queue *new; if (!timestamp || timestamp == ~0ULL) @@ -650,7 +648,7 @@ static int perf_session_queue_event(struct perf_session *s, union perf_event *ev return 0; } -static void callchain__printf(struct perf_sample *sample) +static void callchain__printf(struct sample_data *sample) { unsigned int i; @@ -662,8 +660,8 @@ static void callchain__printf(struct perf_sample *sample) } static void perf_session__print_tstamp(struct perf_session *session, - union perf_event *event, - struct perf_sample *sample) + event_t *event, + struct sample_data *sample) { if (event->header.type != PERF_RECORD_SAMPLE && !session->sample_id_all) { @@ -678,8 +676,8 @@ static void perf_session__print_tstamp(struct perf_session *session, printf("%" PRIu64 " ", sample->time); } -static void dump_event(struct perf_session *session, union perf_event *event, - u64 file_offset, struct perf_sample *sample) +static void dump_event(struct perf_session *session, event_t *event, + u64 file_offset, struct sample_data *sample) { if (!dump_trace) return; @@ -693,11 +691,11 @@ static void dump_event(struct perf_session *session, union perf_event *event, perf_session__print_tstamp(session, event, sample); printf("%#" PRIx64 " [%#x]: PERF_RECORD_%s", file_offset, - event->header.size, perf_event__name(event->header.type)); + event->header.size, event__get_event_name(event->header.type)); } -static void dump_sample(struct perf_session *session, union perf_event *event, - struct perf_sample *sample) +static void dump_sample(struct perf_session *session, event_t *event, + struct sample_data *sample) { if (!dump_trace) return; @@ -711,8 +709,8 @@ static void dump_sample(struct perf_session *session, union perf_event *event, } static int perf_session_deliver_event(struct perf_session *session, - union perf_event *event, - struct perf_sample *sample, + event_t *event, + struct sample_data *sample, struct perf_event_ops *ops, u64 file_offset) { @@ -745,7 +743,7 @@ static int perf_session_deliver_event(struct perf_session *session, } static int perf_session__preprocess_sample(struct perf_session *session, - union perf_event *event, struct perf_sample *sample) + event_t *event, struct sample_data *sample) { if (event->header.type != PERF_RECORD_SAMPLE || !(session->sample_type & PERF_SAMPLE_CALLCHAIN)) @@ -760,7 +758,7 @@ static int perf_session__preprocess_sample(struct perf_session *session, return 0; } -static int perf_session__process_user_event(struct perf_session *session, union perf_event *event, +static int perf_session__process_user_event(struct perf_session *session, event_t *event, struct perf_event_ops *ops, u64 file_offset) { dump_event(session, event, file_offset, NULL); @@ -785,16 +783,15 @@ static int perf_session__process_user_event(struct perf_session *session, union } static int perf_session__process_event(struct perf_session *session, - union perf_event *event, + event_t *event, struct perf_event_ops *ops, u64 file_offset) { - struct perf_sample sample; + struct sample_data sample; int ret; - if (session->header.needs_swap && - perf_event__swap_ops[event->header.type]) - perf_event__swap_ops[event->header.type](event); + if (session->header.needs_swap && event__swap_ops[event->header.type]) + event__swap_ops[event->header.type](event); if (event->header.type >= PERF_RECORD_HEADER_MAX) return -EINVAL; @@ -807,7 +804,7 @@ static int perf_session__process_event(struct perf_session *session, /* * For all kernel events we get the sample data */ - perf_session__parse_sample(session, event, &sample); + event__parse_sample(event, session, &sample); /* Preprocess sample records - precheck callchains */ if (perf_session__preprocess_sample(session, event, &sample)) @@ -846,7 +843,7 @@ static struct thread *perf_session__register_idle_thread(struct perf_session *se static void perf_session__warn_about_errors(const struct perf_session *session, const struct perf_event_ops *ops) { - if (ops->lost == perf_event__process_lost && + if (ops->lost == event__process_lost && session->hists.stats.total_lost != 0) { ui__warning("Processed %" PRIu64 " events and LOST %" PRIu64 "!\n\nCheck IO/CPU overload!\n\n", @@ -878,7 +875,7 @@ volatile int session_done; static int __perf_session__process_pipe_events(struct perf_session *self, struct perf_event_ops *ops) { - union perf_event event; + event_t event; uint32_t size; int skip = 0; u64 head; @@ -959,7 +956,7 @@ int __perf_session__process_events(struct perf_session *session, struct ui_progress *progress; size_t page_size, mmap_size; char *buf, *mmaps[8]; - union perf_event *event; + event_t *event; uint32_t size; perf_event_ops__fill_defaults(ops); @@ -1004,7 +1001,7 @@ int __perf_session__process_events(struct perf_session *session, file_pos = file_offset + head; more: - event = (union perf_event *)(buf + head); + event = (event_t *)(buf + head); if (session->header.needs_swap) perf_event_header__bswap(&event->header); diff --git a/trunk/tools/perf/util/session.h b/trunk/tools/perf/util/session.h index 977b3a1b14aa..decd83f274fd 100644 --- a/trunk/tools/perf/util/session.h +++ b/trunk/tools/perf/util/session.h @@ -51,17 +51,15 @@ struct perf_session { int cwdlen; char *cwd; struct ordered_samples ordered_samples; - struct callchain_cursor callchain_cursor; - char filename[0]; + char filename[0]; }; struct perf_event_ops; -typedef int (*event_op)(union perf_event *self, struct perf_sample *sample, +typedef int (*event_op)(event_t *self, struct sample_data *sample, struct perf_session *session); -typedef int (*event_synth_op)(union perf_event *self, - struct perf_session *session); -typedef int (*event_op2)(union perf_event *self, struct perf_session *session, +typedef int (*event_synth_op)(event_t *self, struct perf_session *session); +typedef int (*event_op2)(event_t *self, struct perf_session *session, struct perf_event_ops *ops); struct perf_event_ops { @@ -96,10 +94,10 @@ int __perf_session__process_events(struct perf_session *self, int perf_session__process_events(struct perf_session *self, struct perf_event_ops *event_ops); -int perf_session__resolve_callchain(struct perf_session *self, - struct thread *thread, - struct ip_callchain *chain, - struct symbol **parent); +struct map_symbol *perf_session__resolve_callchain(struct perf_session *self, + struct thread *thread, + struct ip_callchain *chain, + struct symbol **parent); bool perf_session__has_traces(struct perf_session *self, const char *msg); @@ -156,13 +154,4 @@ size_t perf_session__fprintf_nr_events(struct perf_session *self, FILE *fp) { return hists__fprintf_nr_events(&self->hists, fp); } - -static inline int perf_session__parse_sample(struct perf_session *session, - const union perf_event *event, - struct perf_sample *sample) -{ - return perf_event__parse_sample(event, session->sample_type, - session->sample_id_all, sample); -} - #endif /* __PERF_SESSION_H */ diff --git a/trunk/tools/perf/util/setup.py b/trunk/tools/perf/util/setup.py deleted file mode 100644 index 1947b0430c94..000000000000 --- a/trunk/tools/perf/util/setup.py +++ /dev/null @@ -1,19 +0,0 @@ -#!/usr/bin/python2 - -from distutils.core import setup, Extension - -perf = Extension('perf', - sources = ['util/python.c', 'util/ctype.c', 'util/evlist.c', - 'util/evsel.c', 'util/cpumap.c', 'util/thread_map.c', - 'util/util.c', 'util/xyarray.c'], - include_dirs = ['util/include'], - extra_compile_args = ['-fno-strict-aliasing', '-Wno-write-strings']) - -setup(name='perf', - version='0.1', - description='Interface with the Linux profiling infrastructure', - author='Arnaldo Carvalho de Melo', - author_email='acme@redhat.com', - license='GPLv2', - url='http://perf.wiki.kernel.org', - ext_modules=[perf]) diff --git a/trunk/tools/perf/util/strfilter.c b/trunk/tools/perf/util/strfilter.c deleted file mode 100644 index 4064b7d708b8..000000000000 --- a/trunk/tools/perf/util/strfilter.c +++ /dev/null @@ -1,200 +0,0 @@ -#include -#include "util.h" -#include "string.h" -#include "strfilter.h" - -/* Operators */ -static const char *OP_and = "&"; /* Logical AND */ -static const char *OP_or = "|"; /* Logical OR */ -static const char *OP_not = "!"; /* Logical NOT */ - -#define is_operator(c) ((c) == '|' || (c) == '&' || (c) == '!') -#define is_separator(c) (is_operator(c) || (c) == '(' || (c) == ')') - -static void strfilter_node__delete(struct strfilter_node *self) -{ - if (self) { - if (self->p && !is_operator(*self->p)) - free((char *)self->p); - strfilter_node__delete(self->l); - strfilter_node__delete(self->r); - free(self); - } -} - -void strfilter__delete(struct strfilter *self) -{ - if (self) { - strfilter_node__delete(self->root); - free(self); - } -} - -static const char *get_token(const char *s, const char **e) -{ - const char *p; - - while (isspace(*s)) /* Skip spaces */ - s++; - - if (*s == '\0') { - p = s; - goto end; - } - - p = s + 1; - if (!is_separator(*s)) { - /* End search */ -retry: - while (*p && !is_separator(*p) && !isspace(*p)) - p++; - /* Escape and special case: '!' is also used in glob pattern */ - if (*(p - 1) == '\\' || (*p == '!' && *(p - 1) == '[')) { - p++; - goto retry; - } - } -end: - *e = p; - return s; -} - -static struct strfilter_node *strfilter_node__alloc(const char *op, - struct strfilter_node *l, - struct strfilter_node *r) -{ - struct strfilter_node *ret = zalloc(sizeof(struct strfilter_node)); - - if (ret) { - ret->p = op; - ret->l = l; - ret->r = r; - } - - return ret; -} - -static struct strfilter_node *strfilter_node__new(const char *s, - const char **ep) -{ - struct strfilter_node root, *cur, *last_op; - const char *e; - - if (!s) - return NULL; - - memset(&root, 0, sizeof(root)); - last_op = cur = &root; - - s = get_token(s, &e); - while (*s != '\0' && *s != ')') { - switch (*s) { - case '&': /* Exchg last OP->r with AND */ - if (!cur->r || !last_op->r) - goto error; - cur = strfilter_node__alloc(OP_and, last_op->r, NULL); - if (!cur) - goto nomem; - last_op->r = cur; - last_op = cur; - break; - case '|': /* Exchg the root with OR */ - if (!cur->r || !root.r) - goto error; - cur = strfilter_node__alloc(OP_or, root.r, NULL); - if (!cur) - goto nomem; - root.r = cur; - last_op = cur; - break; - case '!': /* Add NOT as a leaf node */ - if (cur->r) - goto error; - cur->r = strfilter_node__alloc(OP_not, NULL, NULL); - if (!cur->r) - goto nomem; - cur = cur->r; - break; - case '(': /* Recursively parses inside the parenthesis */ - if (cur->r) - goto error; - cur->r = strfilter_node__new(s + 1, &s); - if (!s) - goto nomem; - if (!cur->r || *s != ')') - goto error; - e = s + 1; - break; - default: - if (cur->r) - goto error; - cur->r = strfilter_node__alloc(NULL, NULL, NULL); - if (!cur->r) - goto nomem; - cur->r->p = strndup(s, e - s); - if (!cur->r->p) - goto nomem; - } - s = get_token(e, &e); - } - if (!cur->r) - goto error; - *ep = s; - return root.r; -nomem: - s = NULL; -error: - *ep = s; - strfilter_node__delete(root.r); - return NULL; -} - -/* - * Parse filter rule and return new strfilter. - * Return NULL if fail, and *ep == NULL if memory allocation failed. - */ -struct strfilter *strfilter__new(const char *rules, const char **err) -{ - struct strfilter *ret = zalloc(sizeof(struct strfilter)); - const char *ep = NULL; - - if (ret) - ret->root = strfilter_node__new(rules, &ep); - - if (!ret || !ret->root || *ep != '\0') { - if (err) - *err = ep; - strfilter__delete(ret); - ret = NULL; - } - - return ret; -} - -static bool strfilter_node__compare(struct strfilter_node *self, - const char *str) -{ - if (!self || !self->p) - return false; - - switch (*self->p) { - case '|': /* OR */ - return strfilter_node__compare(self->l, str) || - strfilter_node__compare(self->r, str); - case '&': /* AND */ - return strfilter_node__compare(self->l, str) && - strfilter_node__compare(self->r, str); - case '!': /* NOT */ - return !strfilter_node__compare(self->r, str); - default: - return strglobmatch(str, self->p); - } -} - -/* Return true if STR matches the filter rules */ -bool strfilter__compare(struct strfilter *self, const char *str) -{ - if (!self) - return false; - return strfilter_node__compare(self->root, str); -} diff --git a/trunk/tools/perf/util/strfilter.h b/trunk/tools/perf/util/strfilter.h deleted file mode 100644 index 00f58a7506de..000000000000 --- a/trunk/tools/perf/util/strfilter.h +++ /dev/null @@ -1,48 +0,0 @@ -#ifndef __PERF_STRFILTER_H -#define __PERF_STRFILTER_H -/* General purpose glob matching filter */ - -#include -#include - -/* A node of string filter */ -struct strfilter_node { - struct strfilter_node *l; /* Tree left branche (for &,|) */ - struct strfilter_node *r; /* Tree right branche (for !,&,|) */ - const char *p; /* Operator or rule */ -}; - -/* String filter */ -struct strfilter { - struct strfilter_node *root; -}; - -/** - * strfilter__new - Create a new string filter - * @rules: Filter rule, which is a combination of glob expressions. - * @err: Pointer which points an error detected on @rules - * - * Parse @rules and return new strfilter. Return NULL if an error detected. - * In that case, *@err will indicate where it is detected, and *@err is NULL - * if a memory allocation is failed. - */ -struct strfilter *strfilter__new(const char *rules, const char **err); - -/** - * strfilter__compare - compare given string and a string filter - * @self: String filter - * @str: target string - * - * Compare @str and @self. Return true if the str match the rule - */ -bool strfilter__compare(struct strfilter *self, const char *str); - -/** - * strfilter__delete - delete a string filter - * @self: String filter to delete - * - * Delete @self. - */ -void strfilter__delete(struct strfilter *self); - -#endif diff --git a/trunk/tools/perf/util/symbol.c b/trunk/tools/perf/util/symbol.c index 3e193f8e3061..7821d0e6866f 100644 --- a/trunk/tools/perf/util/symbol.c +++ b/trunk/tools/perf/util/symbol.c @@ -1525,8 +1525,8 @@ int dso__load(struct dso *self, struct map *map, symbol_filter_t filter) symbol_conf.symfs, self->long_name); break; case DSO__ORIG_GUEST_KMODULE: - if (map->groups && machine) - root_dir = machine->root_dir; + if (map->groups && map->groups->machine) + root_dir = map->groups->machine->root_dir; else root_dir = ""; snprintf(name, size, "%s%s%s", symbol_conf.symfs, diff --git a/trunk/tools/perf/util/thread.c b/trunk/tools/perf/util/thread.c index d5d3b22250f3..00f4eade2e3e 100644 --- a/trunk/tools/perf/util/thread.c +++ b/trunk/tools/perf/util/thread.c @@ -7,6 +7,61 @@ #include "util.h" #include "debug.h" +/* Skip "." and ".." directories */ +static int filter(const struct dirent *dir) +{ + if (dir->d_name[0] == '.') + return 0; + else + return 1; +} + +struct thread_map *thread_map__new_by_pid(pid_t pid) +{ + struct thread_map *threads; + char name[256]; + int items; + struct dirent **namelist = NULL; + int i; + + sprintf(name, "/proc/%d/task", pid); + items = scandir(name, &namelist, filter, NULL); + if (items <= 0) + return NULL; + + threads = malloc(sizeof(*threads) + sizeof(pid_t) * items); + if (threads != NULL) { + for (i = 0; i < items; i++) + threads->map[i] = atoi(namelist[i]->d_name); + threads->nr = items; + } + + for (i=0; imap[0] = tid; + threads->nr = 1; + } + + return threads; +} + +struct thread_map *thread_map__new(pid_t pid, pid_t tid) +{ + if (pid != -1) + return thread_map__new_by_pid(pid); + return thread_map__new_by_tid(tid); +} + static struct thread *thread__new(pid_t pid) { struct thread *self = zalloc(sizeof(*self)); diff --git a/trunk/tools/perf/util/thread.h b/trunk/tools/perf/util/thread.h index e5f2401c1b5e..d7574101054a 100644 --- a/trunk/tools/perf/util/thread.h +++ b/trunk/tools/perf/util/thread.h @@ -18,10 +18,24 @@ struct thread { int comm_len; }; +struct thread_map { + int nr; + int map[]; +}; + struct perf_session; void thread__delete(struct thread *self); +struct thread_map *thread_map__new_by_pid(pid_t pid); +struct thread_map *thread_map__new_by_tid(pid_t tid); +struct thread_map *thread_map__new(pid_t pid, pid_t tid); + +static inline void thread_map__delete(struct thread_map *threads) +{ + free(threads); +} + int thread__set_comm(struct thread *self, const char *comm); int thread__comm_len(struct thread *self); struct thread *perf_session__findnew(struct perf_session *self, pid_t pid); diff --git a/trunk/tools/perf/util/thread_map.c b/trunk/tools/perf/util/thread_map.c deleted file mode 100644 index a5df131b77c3..000000000000 --- a/trunk/tools/perf/util/thread_map.c +++ /dev/null @@ -1,64 +0,0 @@ -#include -#include -#include -#include "thread_map.h" - -/* Skip "." and ".." directories */ -static int filter(const struct dirent *dir) -{ - if (dir->d_name[0] == '.') - return 0; - else - return 1; -} - -struct thread_map *thread_map__new_by_pid(pid_t pid) -{ - struct thread_map *threads; - char name[256]; - int items; - struct dirent **namelist = NULL; - int i; - - sprintf(name, "/proc/%d/task", pid); - items = scandir(name, &namelist, filter, NULL); - if (items <= 0) - return NULL; - - threads = malloc(sizeof(*threads) + sizeof(pid_t) * items); - if (threads != NULL) { - for (i = 0; i < items; i++) - threads->map[i] = atoi(namelist[i]->d_name); - threads->nr = items; - } - - for (i=0; imap[0] = tid; - threads->nr = 1; - } - - return threads; -} - -struct thread_map *thread_map__new(pid_t pid, pid_t tid) -{ - if (pid != -1) - return thread_map__new_by_pid(pid); - return thread_map__new_by_tid(tid); -} - -void thread_map__delete(struct thread_map *threads) -{ - free(threads); -} diff --git a/trunk/tools/perf/util/thread_map.h b/trunk/tools/perf/util/thread_map.h deleted file mode 100644 index 3cb907311409..000000000000 --- a/trunk/tools/perf/util/thread_map.h +++ /dev/null @@ -1,15 +0,0 @@ -#ifndef __PERF_THREAD_MAP_H -#define __PERF_THREAD_MAP_H - -#include - -struct thread_map { - int nr; - int map[]; -}; - -struct thread_map *thread_map__new_by_pid(pid_t pid); -struct thread_map *thread_map__new_by_tid(pid_t tid); -struct thread_map *thread_map__new(pid_t pid, pid_t tid); -void thread_map__delete(struct thread_map *threads); -#endif /* __PERF_THREAD_MAP_H */ diff --git a/trunk/tools/perf/util/top.c b/trunk/tools/perf/util/top.c deleted file mode 100644 index 70a9c13f4ad5..000000000000 --- a/trunk/tools/perf/util/top.c +++ /dev/null @@ -1,218 +0,0 @@ -/* - * Copyright (C) 2011, Red Hat Inc, Arnaldo Carvalho de Melo - * - * Refactored from builtin-top.c, see that files for further copyright notes. - * - * Released under the GPL v2. (and only v2, not any later version) - */ - -#include "cpumap.h" -#include "event.h" -#include "evlist.h" -#include "evsel.h" -#include "parse-events.h" -#include "symbol.h" -#include "top.h" -#include - -/* - * Ordering weight: count-1 * count-2 * ... / count-n - */ -static double sym_weight(const struct sym_entry *sym, struct perf_top *top) -{ - double weight = sym->snap_count; - int counter; - - if (!top->display_weighted) - return weight; - - for (counter = 1; counter < top->evlist->nr_entries - 1; counter++) - weight *= sym->count[counter]; - - weight /= (sym->count[counter] + 1); - - return weight; -} - -static void perf_top__remove_active_sym(struct perf_top *top, struct sym_entry *syme) -{ - pthread_mutex_lock(&top->active_symbols_lock); - list_del_init(&syme->node); - pthread_mutex_unlock(&top->active_symbols_lock); -} - -static void rb_insert_active_sym(struct rb_root *tree, struct sym_entry *se) -{ - struct rb_node **p = &tree->rb_node; - struct rb_node *parent = NULL; - struct sym_entry *iter; - - while (*p != NULL) { - parent = *p; - iter = rb_entry(parent, struct sym_entry, rb_node); - - if (se->weight > iter->weight) - p = &(*p)->rb_left; - else - p = &(*p)->rb_right; - } - - rb_link_node(&se->rb_node, parent, p); - rb_insert_color(&se->rb_node, tree); -} - -size_t perf_top__header_snprintf(struct perf_top *top, char *bf, size_t size) -{ - struct perf_evsel *counter; - float samples_per_sec = top->samples / top->delay_secs; - float ksamples_per_sec = top->kernel_samples / top->delay_secs; - float esamples_percent = (100.0 * top->exact_samples) / top->samples; - size_t ret = 0; - - if (!perf_guest) { - ret = snprintf(bf, size, - " PerfTop:%8.0f irqs/sec kernel:%4.1f%%" - " exact: %4.1f%% [", samples_per_sec, - 100.0 - (100.0 * ((samples_per_sec - ksamples_per_sec) / - samples_per_sec)), - esamples_percent); - } else { - float us_samples_per_sec = top->us_samples / top->delay_secs; - float guest_kernel_samples_per_sec = top->guest_kernel_samples / top->delay_secs; - float guest_us_samples_per_sec = top->guest_us_samples / top->delay_secs; - - ret = snprintf(bf, size, - " PerfTop:%8.0f irqs/sec kernel:%4.1f%% us:%4.1f%%" - " guest kernel:%4.1f%% guest us:%4.1f%%" - " exact: %4.1f%% [", samples_per_sec, - 100.0 - (100.0 * ((samples_per_sec - ksamples_per_sec) / - samples_per_sec)), - 100.0 - (100.0 * ((samples_per_sec - us_samples_per_sec) / - samples_per_sec)), - 100.0 - (100.0 * ((samples_per_sec - - guest_kernel_samples_per_sec) / - samples_per_sec)), - 100.0 - (100.0 * ((samples_per_sec - - guest_us_samples_per_sec) / - samples_per_sec)), - esamples_percent); - } - - if (top->evlist->nr_entries == 1 || !top->display_weighted) { - struct perf_evsel *first; - first = list_entry(top->evlist->entries.next, struct perf_evsel, node); - ret += snprintf(bf + ret, size - ret, "%" PRIu64 "%s ", - (uint64_t)first->attr.sample_period, - top->freq ? "Hz" : ""); - } - - if (!top->display_weighted) { - ret += snprintf(bf + ret, size - ret, "%s", - event_name(top->sym_evsel)); - } else list_for_each_entry(counter, &top->evlist->entries, node) { - ret += snprintf(bf + ret, size - ret, "%s%s", - counter->idx ? "/" : "", event_name(counter)); - } - - ret += snprintf(bf + ret, size - ret, "], "); - - if (top->target_pid != -1) - ret += snprintf(bf + ret, size - ret, " (target_pid: %d", - top->target_pid); - else if (top->target_tid != -1) - ret += snprintf(bf + ret, size - ret, " (target_tid: %d", - top->target_tid); - else - ret += snprintf(bf + ret, size - ret, " (all"); - - if (top->cpu_list) - ret += snprintf(bf + ret, size - ret, ", CPU%s: %s)", - top->evlist->cpus->nr > 1 ? "s" : "", top->cpu_list); - else { - if (top->target_tid != -1) - ret += snprintf(bf + ret, size - ret, ")"); - else - ret += snprintf(bf + ret, size - ret, ", %d CPU%s)", - top->evlist->cpus->nr, - top->evlist->cpus->nr > 1 ? "s" : ""); - } - - return ret; -} - -void perf_top__reset_sample_counters(struct perf_top *top) -{ - top->samples = top->us_samples = top->kernel_samples = - top->exact_samples = top->guest_kernel_samples = - top->guest_us_samples = 0; -} - -float perf_top__decay_samples(struct perf_top *top, struct rb_root *root) -{ - struct sym_entry *syme, *n; - float sum_ksamples = 0.0; - int snap = !top->display_weighted ? top->sym_counter : 0, j; - - /* Sort the active symbols */ - pthread_mutex_lock(&top->active_symbols_lock); - syme = list_entry(top->active_symbols.next, struct sym_entry, node); - pthread_mutex_unlock(&top->active_symbols_lock); - - top->rb_entries = 0; - list_for_each_entry_safe_from(syme, n, &top->active_symbols, node) { - syme->snap_count = syme->count[snap]; - if (syme->snap_count != 0) { - - if ((top->hide_user_symbols && - syme->origin == PERF_RECORD_MISC_USER) || - (top->hide_kernel_symbols && - syme->origin == PERF_RECORD_MISC_KERNEL)) { - perf_top__remove_active_sym(top, syme); - continue; - } - syme->weight = sym_weight(syme, top); - - if ((int)syme->snap_count >= top->count_filter) { - rb_insert_active_sym(root, syme); - ++top->rb_entries; - } - sum_ksamples += syme->snap_count; - - for (j = 0; j < top->evlist->nr_entries; j++) - syme->count[j] = top->zero ? 0 : syme->count[j] * 7 / 8; - } else - perf_top__remove_active_sym(top, syme); - } - - return sum_ksamples; -} - -/* - * Find the longest symbol name that will be displayed - */ -void perf_top__find_widths(struct perf_top *top, struct rb_root *root, - int *dso_width, int *dso_short_width, int *sym_width) -{ - struct rb_node *nd; - int printed = 0; - - *sym_width = *dso_width = *dso_short_width = 0; - - for (nd = rb_first(root); nd; nd = rb_next(nd)) { - struct sym_entry *syme = rb_entry(nd, struct sym_entry, rb_node); - struct symbol *sym = sym_entry__symbol(syme); - - if (++printed > top->print_entries || - (int)syme->snap_count < top->count_filter) - continue; - - if (syme->map->dso->long_name_len > *dso_width) - *dso_width = syme->map->dso->long_name_len; - - if (syme->map->dso->short_name_len > *dso_short_width) - *dso_short_width = syme->map->dso->short_name_len; - - if (sym->namelen > *sym_width) - *sym_width = sym->namelen; - } -} diff --git a/trunk/tools/perf/util/top.h b/trunk/tools/perf/util/top.h deleted file mode 100644 index 4f769f47e19a..000000000000 --- a/trunk/tools/perf/util/top.h +++ /dev/null @@ -1,64 +0,0 @@ -#ifndef __PERF_TOP_H -#define __PERF_TOP_H 1 - -#include "types.h" -#include "../perf.h" -#include -#include -#include -#include - -struct perf_evlist; -struct perf_evsel; - -struct sym_entry { - struct rb_node rb_node; - struct list_head node; - unsigned long snap_count; - double weight; - int skip; - u8 origin; - struct map *map; - unsigned long count[0]; -}; - -static inline struct symbol *sym_entry__symbol(struct sym_entry *self) -{ - return ((void *)self) + symbol_conf.priv_size; -} - -struct perf_top { - struct perf_evlist *evlist; - /* - * Symbols will be added here in perf_event__process_sample and will - * get out after decayed. - */ - struct list_head active_symbols; - pthread_mutex_t active_symbols_lock; - u64 samples; - u64 kernel_samples, us_samples; - u64 exact_samples; - u64 guest_us_samples, guest_kernel_samples; - int print_entries, count_filter, delay_secs; - int display_weighted, freq, rb_entries, sym_counter; - pid_t target_pid, target_tid; - bool hide_kernel_symbols, hide_user_symbols, zero; - const char *cpu_list; - struct perf_evsel *sym_evsel; -}; - -size_t perf_top__header_snprintf(struct perf_top *top, char *bf, size_t size); -void perf_top__reset_sample_counters(struct perf_top *top); -float perf_top__decay_samples(struct perf_top *top, struct rb_root *root); -void perf_top__find_widths(struct perf_top *top, struct rb_root *root, - int *dso_width, int *dso_short_width, int *sym_width); - -#ifdef NO_NEWT_SUPPORT -static inline int perf_top__tui_browser(struct perf_top *top __used) -{ - return 0; -} -#else -int perf_top__tui_browser(struct perf_top *top); -#endif -#endif /* __PERF_TOP_H */ diff --git a/trunk/tools/perf/util/trace-event-parse.c b/trunk/tools/perf/util/trace-event-parse.c index d8e622dd738a..73a02223c629 100644 --- a/trunk/tools/perf/util/trace-event-parse.c +++ b/trunk/tools/perf/util/trace-event-parse.c @@ -153,7 +153,7 @@ void parse_proc_kallsyms(char *file, unsigned int size __unused) char *next = NULL; char *addr_str; char ch; - int ret __used; + int ret; int i; line = strtok_r(file, "\n", &next); diff --git a/trunk/tools/perf/util/ui/browsers/annotate.c b/trunk/tools/perf/util/ui/browsers/annotate.c index 1aa39658539c..82b78f99251b 100644 --- a/trunk/tools/perf/util/ui/browsers/annotate.c +++ b/trunk/tools/perf/util/ui/browsers/annotate.c @@ -1,11 +1,9 @@ #include "../browser.h" #include "../helpline.h" #include "../libslang.h" -#include "../../annotate.h" #include "../../hist.h" #include "../../sort.h" #include "../../symbol.h" -#include "../../annotate.h" static void ui__error_window(const char *fmt, ...) { @@ -60,34 +58,32 @@ static void annotate_browser__write(struct ui_browser *self, void *entry, int ro } static double objdump_line__calc_percent(struct objdump_line *self, - struct symbol *sym, int evidx) + struct list_head *head, + struct symbol *sym) { double percent = 0.0; if (self->offset != -1) { int len = sym->end - sym->start; unsigned int hits = 0; - struct annotation *notes = symbol__annotation(sym); - struct source_line *src_line = notes->src->lines; - struct sym_hist *h = annotation__histogram(notes, evidx); + struct sym_priv *priv = symbol__priv(sym); + struct sym_ext *sym_ext = priv->ext; + struct sym_hist *h = priv->hist; s64 offset = self->offset; - struct objdump_line *next; + struct objdump_line *next = objdump__get_next_ip_line(head, self); + - next = objdump__get_next_ip_line(¬es->src->source, self); while (offset < (s64)len && (next == NULL || offset < next->offset)) { - if (src_line) { - percent += src_line[offset].percent; + if (sym_ext) { + percent += sym_ext[offset].percent; } else - hits += h->addr[offset]; + hits += h->ip[offset]; ++offset; } - /* - * If the percentage wasn't already calculated in - * symbol__get_source_line, do it now: - */ - if (src_line == NULL && h->sum) + + if (sym_ext == NULL && h->sum) percent = 100.0 * hits / h->sum; } @@ -140,10 +136,10 @@ static void annotate_browser__set_top(struct annotate_browser *self, static int annotate_browser__run(struct annotate_browser *self) { struct rb_node *nd; - struct symbol *sym = self->b.priv; + struct hist_entry *he = self->b.priv; int key; - if (ui_browser__show(&self->b, sym->name, + if (ui_browser__show(&self->b, he->ms.sym->name, "<-, -> or ESC: exit, TAB/shift+TAB: cycle thru samples") < 0) return -1; /* @@ -183,47 +179,42 @@ static int annotate_browser__run(struct annotate_browser *self) return key; } -int hist_entry__tui_annotate(struct hist_entry *he, int evidx) -{ - return symbol__tui_annotate(he->ms.sym, he->ms.map, evidx); -} - -int symbol__tui_annotate(struct symbol *sym, struct map *map, int evidx) +int hist_entry__tui_annotate(struct hist_entry *self) { struct objdump_line *pos, *n; struct objdump_line_rb_node *rbpos; - struct annotation *notes = symbol__annotation(sym); + LIST_HEAD(head); struct annotate_browser browser = { .b = { - .entries = ¬es->src->source, + .entries = &head, .refresh = ui_browser__list_head_refresh, .seek = ui_browser__list_head_seek, .write = annotate_browser__write, - .priv = sym, + .priv = self, }, }; int ret; - if (sym == NULL) + if (self->ms.sym == NULL) return -1; - if (map->dso->annotate_warned) + if (self->ms.map->dso->annotate_warned) return -1; - if (symbol__annotate(sym, map, sizeof(*rbpos)) < 0) { + if (hist_entry__annotate(self, &head, sizeof(*rbpos)) < 0) { ui__error_window(ui_helpline__last_msg); return -1; } ui_helpline__push("Press <- or ESC to exit"); - list_for_each_entry(pos, ¬es->src->source, node) { + list_for_each_entry(pos, &head, node) { size_t line_len = strlen(pos->line); if (browser.b.width < line_len) browser.b.width = line_len; rbpos = objdump_line__rb(pos); rbpos->idx = browser.b.nr_entries++; - rbpos->percent = objdump_line__calc_percent(pos, sym, evidx); + rbpos->percent = objdump_line__calc_percent(pos, &head, self->ms.sym); if (rbpos->percent < 0.01) continue; objdump__insert_line(&browser.entries, rbpos); @@ -238,7 +229,7 @@ int symbol__tui_annotate(struct symbol *sym, struct map *map, int evidx) browser.b.width += 18; /* Percentage */ ret = annotate_browser__run(&browser); - list_for_each_entry_safe(pos, n, ¬es->src->source, node) { + list_for_each_entry_safe(pos, n, &head, node) { list_del(&pos->node); objdump_line__free(pos); } diff --git a/trunk/tools/perf/util/ui/browsers/hists.c b/trunk/tools/perf/util/ui/browsers/hists.c index 294b49538522..60c463c16028 100644 --- a/trunk/tools/perf/util/ui/browsers/hists.c +++ b/trunk/tools/perf/util/ui/browsers/hists.c @@ -377,7 +377,7 @@ static int hist_browser__show_callchain_node_rb_tree(struct hist_browser *self, while (node) { struct callchain_node *child = rb_entry(node, struct callchain_node, rb_node); struct rb_node *next = rb_next(node); - u64 cumul = callchain_cumul_hits(child); + u64 cumul = cumul_hits(child); struct callchain_list *chain; char folded_sign = ' '; int first = true; @@ -797,8 +797,7 @@ static int hists__browser_title(struct hists *self, char *bf, size_t size, return printed; } -int hists__browse(struct hists *self, const char *helpline, - const char *ev_name, int evidx) +int hists__browse(struct hists *self, const char *helpline, const char *ev_name) { struct hist_browser *browser = hist_browser__new(self); struct pstack *fstack; @@ -936,7 +935,7 @@ int hists__browse(struct hists *self, const char *helpline, if (he == NULL) continue; - hist_entry__tui_annotate(he, evidx); + hist_entry__tui_annotate(he); } else if (choice == browse_map) map__browse(browser->selection->map); else if (choice == zoom_dso) { @@ -985,7 +984,7 @@ int hists__browse(struct hists *self, const char *helpline, return key; } -int hists__tui_browse_tree(struct rb_root *self, const char *help, int evidx) +int hists__tui_browse_tree(struct rb_root *self, const char *help) { struct rb_node *first = rb_first(self), *nd = first, *next; int key = 0; @@ -994,7 +993,7 @@ int hists__tui_browse_tree(struct rb_root *self, const char *help, int evidx) struct hists *hists = rb_entry(nd, struct hists, rb_node); const char *ev_name = __event_name(hists->type, hists->config); - key = hists__browse(hists, help, ev_name, evidx); + key = hists__browse(hists, help, ev_name); switch (key) { case NEWT_KEY_TAB: next = rb_next(nd); diff --git a/trunk/tools/perf/util/ui/browsers/map.c b/trunk/tools/perf/util/ui/browsers/map.c index 8462bffe20bc..e5158369106e 100644 --- a/trunk/tools/perf/util/ui/browsers/map.c +++ b/trunk/tools/perf/util/ui/browsers/map.c @@ -41,7 +41,7 @@ static int ui_entry__read(const char *title, char *bf, size_t size, int width) out_free_form: newtPopWindow(); newtFormDestroy(form); - return err; + return 0; } struct map_browser { diff --git a/trunk/tools/perf/util/ui/browsers/top.c b/trunk/tools/perf/util/ui/browsers/top.c deleted file mode 100644 index ca6062483a8f..000000000000 --- a/trunk/tools/perf/util/ui/browsers/top.c +++ /dev/null @@ -1,136 +0,0 @@ -/* - * Copyright (C) 2011, Red Hat Inc, Arnaldo Carvalho de Melo - * - * Parts came from builtin-{top,stat,record}.c, see those files for further - * copyright notes. - * - * Released under the GPL v2. (and only v2, not any later version) - */ -#include "../browser.h" -#include "../helpline.h" -#include "../libslang.h" -#include "../../evlist.h" -#include "../../hist.h" -#include "../../sort.h" -#include "../../symbol.h" -#include "../../top.h" - -struct perf_top_browser { - struct ui_browser b; - struct rb_root root; - float sum_ksamples; - int dso_width; - int dso_short_width; - int sym_width; -}; - -static void perf_top_browser__write(struct ui_browser *browser, void *entry, int row) -{ - struct perf_top_browser *top_browser = container_of(browser, struct perf_top_browser, b); - struct sym_entry *syme = rb_entry(entry, struct sym_entry, rb_node); - bool current_entry = ui_browser__is_current_entry(browser, row); - struct symbol *symbol = sym_entry__symbol(syme); - struct perf_top *top = browser->priv; - int width = browser->width; - double pcnt; - - pcnt = 100.0 - (100.0 * ((top_browser->sum_ksamples - syme->snap_count) / - top_browser->sum_ksamples)); - ui_browser__set_percent_color(browser, pcnt, current_entry); - - if (top->evlist->nr_entries == 1 || !top->display_weighted) { - slsmg_printf("%20.2f ", syme->weight); - width -= 24; - } else { - slsmg_printf("%9.1f %10ld ", syme->weight, syme->snap_count); - width -= 23; - } - - slsmg_printf("%4.1f%%", pcnt); - width -= 7; - - if (verbose) { - slsmg_printf(" %016" PRIx64, symbol->start); - width -= 17; - } - - slsmg_printf(" %-*.*s ", top_browser->sym_width, top_browser->sym_width, - symbol->name); - width -= top_browser->sym_width; - slsmg_write_nstring(width >= syme->map->dso->long_name_len ? - syme->map->dso->long_name : - syme->map->dso->short_name, width); -} - -static void perf_top_browser__update_rb_tree(struct perf_top_browser *browser) -{ - struct perf_top *top = browser->b.priv; - - browser->root = RB_ROOT; - browser->b.top = NULL; - browser->sum_ksamples = perf_top__decay_samples(top, &browser->root); - perf_top__find_widths(top, &browser->root, &browser->dso_width, - &browser->dso_short_width, - &browser->sym_width); - if (browser->sym_width + browser->dso_width > browser->b.width - 29) { - browser->dso_width = browser->dso_short_width; - if (browser->sym_width + browser->dso_width > browser->b.width - 29) - browser->sym_width = browser->b.width - browser->dso_width - 29; - } - browser->b.nr_entries = top->rb_entries; -} - -static int perf_top_browser__run(struct perf_top_browser *browser) -{ - int key; - char title[160]; - struct perf_top *top = browser->b.priv; - int delay_msecs = top->delay_secs * 1000; - - perf_top_browser__update_rb_tree(browser); - perf_top__header_snprintf(top, title, sizeof(title)); - perf_top__reset_sample_counters(top); - - if (ui_browser__show(&browser->b, title, "ESC: exit") < 0) - return -1; - - newtFormSetTimer(browser->b.form, delay_msecs); - - while (1) { - key = ui_browser__run(&browser->b); - - switch (key) { - case -1: - /* FIXME we need to check if it was es.reason == NEWT_EXIT_TIMER */ - perf_top_browser__update_rb_tree(browser); - perf_top__header_snprintf(top, title, sizeof(title)); - perf_top__reset_sample_counters(top); - ui_browser__set_color(&browser->b, NEWT_COLORSET_ROOT); - SLsmg_gotorc(0, 0); - slsmg_write_nstring(title, browser->b.width); - break; - case NEWT_KEY_TAB: - default: - goto out; - } - } -out: - ui_browser__hide(&browser->b); - return key; -} - -int perf_top__tui_browser(struct perf_top *top) -{ - struct perf_top_browser browser = { - .b = { - .entries = &browser.root, - .refresh = ui_browser__rb_tree_refresh, - .seek = ui_browser__rb_tree_seek, - .write = perf_top_browser__write, - .priv = top, - }, - }; - - ui_helpline__push("Press <- or ESC to exit"); - return perf_top_browser__run(&browser); -} diff --git a/trunk/tools/perf/util/ui/libslang.h b/trunk/tools/perf/util/ui/libslang.h index 2b63e1c9b181..5623da8e8080 100644 --- a/trunk/tools/perf/util/ui/libslang.h +++ b/trunk/tools/perf/util/ui/libslang.h @@ -13,11 +13,11 @@ #if SLANG_VERSION < 20104 #define slsmg_printf(msg, args...) \ - SLsmg_printf((char *)(msg), ##args) + SLsmg_printf((char *)msg, ##args) #define slsmg_write_nstring(msg, len) \ - SLsmg_write_nstring((char *)(msg), len) + SLsmg_write_nstring((char *)msg, len) #define sltt_set_color(obj, name, fg, bg) \ - SLtt_set_color(obj,(char *)(name), (char *)(fg), (char *)(bg)) + SLtt_set_color(obj,(char *)name, (char *)fg, (char *)bg) #else #define slsmg_printf SLsmg_printf #define slsmg_write_nstring SLsmg_write_nstring diff --git a/trunk/tools/perf/util/ui/setup.c b/trunk/tools/perf/util/ui/setup.c index fbf1a145492f..662085032eb7 100644 --- a/trunk/tools/perf/util/ui/setup.c +++ b/trunk/tools/perf/util/ui/setup.c @@ -14,12 +14,11 @@ static void newt_suspend(void *d __used) newtResume(); } -void setup_browser(bool fallback_to_pager) +void setup_browser(void) { if (!isatty(1) || !use_browser || dump_trace) { use_browser = 0; - if (fallback_to_pager) - setup_pager(); + setup_pager(); return; }