* Re: fb_imageblit()
From: Antonino Daplas @ 2003-01-08 2:41 UTC (permalink / raw)
To: James Simmons; +Cc: Geert Uytterhoeven, Linux Frame Buffer Device Development
In-Reply-To: <Pine.LNX.4.44.0301072215370.17129-100000@phoenix.infradead.org>
On Wed, 2003-01-08 at 06:23, James Simmons wrote:
> > >
> > > If monochrome image data would be packed as well, it could be handled by
> > > setting fb_image.fg_color = 1 and fb_image.bg_color = 0 (or vice versa for
> > > mono10), and fb_set_logo() becomes simpler as well.
> > >
> > > If we retain the unpacked data for images, we need some other flag to
> > > indicate color expansion. Perhaps setting fb_image.depth to 0?
> > >
> > If we change the contents of the logo data, then it makes sense to pack
> > the logo data also. However, if we stick to indices, we might as well
> > retain the "unpacked" 8-bit format. I think setting fb_image.depth to 0
> > to mean color expansion is more appropriate. Drivers that will need
> > trivial changing would be tgafb, i810fb, rivafb, tdfxfb, atyfb, vga16fb
> > and of course cfb_imgblt.c, softcursor.c and fbcon.c.
>
> The requirement I made of imageblit was to always use packed data. What
> the indices approach was to to always use a struct fb_cmap. This way it
> didn't matter if used a pseudocolor mode or a directcolor mode.
I've thought of that also, packing the data according to the pixel depth.
However, this will be very inefficient since image blitting
will go like this:
a. Prepare logo data so each pixel of data is in directcolor format (if
we will use the cmap), so depth corresponds to framebuffer depth, and
data is packed.
b. Pass the structure to cfb_imageblit.
c. In cfb_imageblit, unpack the logo data:
d. Get each color component from the cmap data.
e. Recreate pixel data based on var.[color].offset and
var.[color].length.
f. Write the pixel data in packed form to the framebuffer.
Whereas, with the current approach:
a. Prepare logo data such that each pixel corresponds to one byte.
b. Pass the structure to cfb_imageblit.
c. Read color information from pseudopalette if directcolor/truecolor.
d. Write the pixel data in packed form to the framebuffer.
Aside from the inefficiency of the method (pack, unpack, pack), drawing
the logo will become inconsistent with the behavior of the rest of the
functions, since it's the only one that gets color info differently. If
you look at color_imageblit() and slow_imageblit(), they basically use
the same code logic.
Secondly, indexing the cmap instead of the pseudo_palette means that
cfb_imageblit has to know the native framebuffer format. This was
argued before that the generic drawing functions need not know of the
format, one of the reasons we have info->pseudopalette. Actually, in
order to be really consistent, I would rather have everything refer to
the pseudopalette, regardless of the visual format. This will be better
especially for some of the corner cases, like monochrome cards with
bits_per_pixel = 8.
Thirdly, it's much simpler for drivers to draw the logo. Just get the
corrct pixel data from it's own palette. No need to construct each
pixel from the cmap. That's tedious, slow, and will contribute to code
bloat. Which is easier? Get each byte from the logo data, and use it as an
index to the pseudo_palette, or unpack the data, separate each unit to 4
color components, and construct pixel data from cmap using the 4 extracted
indices?
I agree that it would be faster in some cases to draw a packed logo
data, but if we're going to be inconsistent, let's do it all the way.
Make the logo data match the native framebuffer format. This will be
very efficient, and this is the one that I actually prefer.
Tony
-------------------------------------------------------
This SF.NET email is sponsored by:
SourceForge Enterprise Edition + IBM + LinuxWorld = Something 2 See!
http://www.vasoftware.com
^ permalink raw reply
* Re: Re: [PATCH]: image.depth fix to accomodate monochrome cards
From: Antonino Daplas @ 2003-01-08 2:41 UTC (permalink / raw)
To: Geert Uytterhoeven; +Cc: James Simmons, Linux Fbdev development list
In-Reply-To: <Pine.GSO.4.21.0301072201350.21057-100000@vervain.sonytel.be>
On Wed, 2003-01-08 at 05:06, Geert Uytterhoeven wrote:
> On 8 Jan 2003, Antonino Daplas wrote:
> > 2. diff submitted by Geert: cleaner logo data preparation for
> > monochrome cards and correct initialization of palette_cmap.transp.
>
> I'll have to do some more fixes there, since the monochrome logo is used not
> only on monochrome displays, but on all other displays with bits_per_pixel < 4
> Since the pixel data in fb_image are colormap indices, they have to reflect the
> correct `black' and `white' colors on such displays.
>
> E.g. on amifb (which supports all bits_per_pixel from 1 through 8) the logo
> showed up in black-and-blue with bits_per_pixel == 3, cfr. the first two
> entries of {red,green,blue}8[] in fbcmap.c.
>
Hmm, I see. I think only linux_logo_bw will be the only one affected,
since linux_logo_16 happens to match the console palette and in
linux_logo, we either reset the palette and/or the cmap.
Would expanding each bit to the full bit depth work? Ie for bpp=8 using
monochrome data, white is 0 and black is 0xff.
I think we still have several corner cases, such as TRUECOLOR with bpp
<= 8, I'm not sure if that works.
Anyway, here's an updated patch for linux-2.5.54 + James Simmons' latest
fbdev.diff. Not sure if it works though :-)
Tony
diff -Naur linux-2.5.54/drivers/video/cfbimgblt.c linux/drivers/video/cfbimgblt.c
--- linux-2.5.54/drivers/video/cfbimgblt.c 2003-01-08 01:53:45.000000000 +0000
+++ linux/drivers/video/cfbimgblt.c 2003-01-08 01:51:21.000000000 +0000
@@ -323,7 +323,7 @@
bitstart &= ~(bpl - 1);
dst1 = p->screen_base + bitstart;
- if (image->depth == 1) {
+ if (image->depth == 0) {
if (p->fix.visual == FB_VISUAL_TRUECOLOR ||
p->fix.visual == FB_VISUAL_DIRECTCOLOR) {
fgcolor = ((u32 *)(p->pseudo_palette))[image->fg_color];
diff -Naur linux-2.5.54/drivers/video/console/fbcon.c linux/drivers/video/console/fbcon.c
--- linux-2.5.54/drivers/video/console/fbcon.c 2003-01-08 01:53:45.000000000 +0000
+++ linux/drivers/video/console/fbcon.c 2003-01-07 15:43:52.000000000 +0000
@@ -395,7 +395,7 @@
image.dx = xx * vc->vc_font.width;
image.dy = yy * vc->vc_font.height;
image.height = vc->vc_font.height;
- image.depth = 1;
+ image.depth = 0;
if (!(vc->vc_font.width & 7)) {
unsigned int pitch, cnt, i, j, k;
@@ -1170,7 +1170,7 @@
image.dy = real_y(p, ypos) * vc->vc_font.height;
image.width = vc->vc_font.width;
image.height = vc->vc_font.height;
- image.depth = 1;
+ image.depth = 0;
image.data = p->fontdata + (c & charmask) * vc->vc_font.height * width;
info->fbops->fb_imageblit(info, &image);
diff -Naur linux-2.5.54/drivers/video/fbmem.c linux/drivers/video/fbmem.c
--- linux-2.5.54/drivers/video/fbmem.c 2003-01-08 01:53:45.000000000 +0000
+++ linux/drivers/video/fbmem.c 2003-01-08 01:53:22.000000000 +0000
@@ -386,6 +386,7 @@
palette_cmap.red = palette_red;
palette_cmap.green = palette_green;
palette_cmap.blue = palette_blue;
+ palette_cmap.transp = NULL;
for (i = 0; i < LINUX_LOGO_COLORS; i += n) {
n = LINUX_LOGO_COLORS - i;
@@ -448,26 +449,33 @@
palette[i] = i << redshift | i << greenshift | i << blueshift;
}
-static void __init fb_set_logo(struct fb_info *info, u8 *logo, int needs_logo)
+#if defined (__BIG_ENDIAN)
+#define BIT_SHIFT(x, shift) ((x) >> (shift))
+#else
+#define BIT_SHIFT(x, shift) ((x) << (shift))
+#endif
+
+static void fb_set_logo(struct fb_info *info, u8 *logo, int needs_logo)
{
int i, j;
+ u8 mask = (u8) ~(BIT_SHIFT(0xffff, info->var.bits_per_pixel));
switch (needs_logo) {
case 4:
- for (i = 0; i < (LOGO_W * LOGO_H)/2; i++) {
+ for (i = 0; i < (LOGO_W * LOGO_H)/2; i++) {
logo[i*2] = linux_logo16[i] >> 4;
logo[(i*2)+1] = linux_logo16[i] & 0xf;
}
break;
case 1:
case ~1:
- default:
- for (i = 0; i < (LOGO_W * LOGO_H)/8; i++)
- for (j = 0; j < 8; j++)
- logo[i*8 + j] = (linux_logo_bw[i] & (7 - j)) ?
- ((needs_logo == 1) ? 1 : 0) :
- ((needs_logo == 1) ? 0 : 1);
- break;
+ for (i = 0; i < (LOGO_W * LOGO_H)/8; i++) {
+ u8 d = linux_logo_bw[i];
+ for (j = 0; j < 8; j++, d <<= 1)
+ logo[i*8+j] = (((d ^ needs_logo) >> 7) & 1) ?
+ mask : 0;
+ }
+ break;
}
}
diff -Naur linux-2.5.54/drivers/video/i810/i810_accel.c linux/drivers/video/i810/i810_accel.c
--- linux-2.5.54/drivers/video/i810/i810_accel.c 2003-01-08 01:53:45.000000000 +0000
+++ linux/drivers/video/i810/i810_accel.c 2003-01-07 15:45:47.000000000 +0000
@@ -404,7 +404,7 @@
return;
}
- if (par->depth == 4 || image->depth != 1) {
+ if (par->depth == 4 || image->depth != 0) {
wait_for_engine_idle(par);
cfb_imageblit(p, image);
return;
diff -Naur linux-2.5.54/drivers/video/riva/fbdev.c linux/drivers/video/riva/fbdev.c
--- linux-2.5.54/drivers/video/riva/fbdev.c 2003-01-08 01:53:45.000000000 +0000
+++ linux/drivers/video/riva/fbdev.c 2003-01-07 15:47:28.000000000 +0000
@@ -1323,7 +1323,7 @@
volatile u32 *d;
int i, j, size;
- if (image->depth != 1) {
+ if (image->depth != 0) {
wait_for_idle(par);
cfb_imageblit(info, image);
return;
diff -Naur linux-2.5.54/drivers/video/skeletonfb.c linux/drivers/video/skeletonfb.c
--- linux-2.5.54/drivers/video/skeletonfb.c 2003-01-08 01:53:45.000000000 +0000
+++ linux/drivers/video/skeletonfb.c 2003-01-07 15:59:33.000000000 +0000
@@ -445,9 +445,14 @@
* @fg_color: For mono bitmap images this is color data for
* @bg_color: the foreground and background of the image to
* write directly to the frmaebuffer.
- * @depth: How many bits represent a single pixel for this image.
+ * @depth: This will be zero (0) if color expanding (character drawing).
+ * If nonzero, this represent the pixel depth of the data.
* @data: The actual data used to construct the image on the display.
- * @cmap: The colormap used for color images.
+ * It is a monochrome bitmap if color expanding. For image
+ * drawing, each byte of data represents 1 pixel irrespective
+ * of the framebuffer depth. The byte is either an index to the
+ * pseudo_palette for directcolor and truecolor, or the
+ * actual pixel written to the framebuffer.
*/
}
diff -Naur linux-2.5.54/drivers/video/softcursor.c linux/drivers/video/softcursor.c
--- linux-2.5.54/drivers/video/softcursor.c 2003-01-08 01:53:45.000000000 +0000
+++ linux/drivers/video/softcursor.c 2003-01-07 15:39:15.000000000 +0000
@@ -47,7 +47,7 @@
image.dy = cursor->image.dy;
image.width = cursor->image.width;
image.height = cursor->image.height;
- image.depth = cursor->image.depth;
+ image.depth = 0;
image.data = data;
if (info->fbops->fb_imageblit)
diff -Naur linux-2.5.54/drivers/video/tdfxfb.c linux/drivers/video/tdfxfb.c
--- linux-2.5.54/drivers/video/tdfxfb.c 2003-01-08 01:53:45.000000000 +0000
+++ linux/drivers/video/tdfxfb.c 2003-01-07 15:46:33.000000000 +0000
@@ -939,7 +939,7 @@
u8 *chardata = (u8 *) pixmap->data;
u32 srcfmt;
- if (pixmap->depth == 1) {
+ if (pixmap->depth == 0) {
banshee_make_room(par, 8 + ((size + 3) >> 2));
tdfx_outl(par, COLORFORE, pixmap->fg_color);
tdfx_outl(par, COLORBACK, pixmap->bg_color);
diff -Naur linux-2.5.54/drivers/video/tgafb.c linux/drivers/video/tgafb.c
--- linux-2.5.54/drivers/video/tgafb.c 2003-01-08 01:53:45.000000000 +0000
+++ linux/drivers/video/tgafb.c 2003-01-07 15:44:35.000000000 +0000
@@ -572,7 +572,7 @@
can do better than the generic code. */
/* ??? There is a DMA write mode; I wonder if that could be
made to pull the data from the image buffer... */
- if (image->depth > 1) {
+ if (image->depth > 0) {
cfb_imageblit(info, image);
return;
}
diff -Naur linux-2.5.54/drivers/video/vga16fb.c linux/drivers/video/vga16fb.c
--- linux-2.5.54/drivers/video/vga16fb.c 2003-01-08 01:53:45.000000000 +0000
+++ linux/drivers/video/vga16fb.c 2003-01-07 15:50:49.000000000 +0000
@@ -1301,7 +1301,7 @@
void vga16fb_imageblit(struct fb_info *info, struct fb_image *image)
{
- if (image->depth == 1)
+ if (image->depth == 0)
vga_imageblit_expand(info, image);
else if (image->depth == info->var.bits_per_pixel)
vga_imageblit_color(info, image);
-------------------------------------------------------
This SF.NET email is sponsored by:
SourceForge Enterprise Edition + IBM + LinuxWorld = Something 2 See!
http://www.vasoftware.com
^ permalink raw reply
* [TRIVIAl]RE: Kernel module version support.
From: Wang, Stanley @ 2003-01-08 2:53 UTC (permalink / raw)
To: 'Rusty Russell'
Cc: levon, Zhuang, Louis, 'linux-kernel@vger.kernel.org',
'trivial@rustcorp.com.au'
> Yes, and the module's state (LOADING, UNLOADING or LIVE). There might
> be others, too.
Is thiw what you want ? And when would you like to export the module's state
information?
# This is a BitKeeper generated patch for the following project:
# Project Name: Linux kernel tree
# This patch format is intended for GNU patch command version 2.5 or higher.
# This patch includes the following deltas:
# ChangeSet 1.893 -> 1.894
# kernel/module.c 1.45 -> 1.46
#
# The following is the BitKeeper ChangeSet Log
# --------------------------------------------
# 03/01/08 stanley@manticore.sh.intel.com 1.894
# Print module state
# --------------------------------------------
#
diff -Nru a/kernel/module.c b/kernel/module.c
--- a/kernel/module.c Wed Jan 8 10:33:28 2003
+++ b/kernel/module.c Wed Jan 8 10:33:29 2003
@@ -486,6 +486,14 @@
return ret;
}
+static void print_module_info(struct seq_file *m, struct module *mod)
+{
+ seq_printf(m, " %s", mod->state == MODULE_STATE_LIVE ? "Live":
+ mod->state == MODULE_STATE_COMING ? "Loading":
+ "Unloading");
+ seq_printf(m, " 0x%p", mod->module_core);
+}
+
static void print_unload_info(struct seq_file *m, struct module *mod)
{
struct module_use *use;
@@ -1422,6 +1430,7 @@
seq_printf(m, "%s %lu",
mod->name, mod->init_size + mod->core_size);
print_unload_info(m, mod);
+ print_module_info(m, mod);
seq_printf(m, "\n");
return 0;
}
Regards,
Your Sincerely,
Stanley Wang
SW Engineer, Intel Corporation.
Intel China Software Lab.
Tel: 021-52574545 ext. 1171
iNet: 8-752-1171
Opinions expressed are those of the author and do not represent Intel
Corporation
^ permalink raw reply
* [PATCH] [2.5] IRQ distribution in the 2.5.52 kernel
From: Kamble, Nitin A @ 2003-01-08 2:52 UTC (permalink / raw)
To: linux-kernel, Kamble, Nitin A
Cc: Saxena, Sunil, Mallick, Asit K, Nakajima, Jun
[-- Attachment #1: Type: text/plain, Size: 13752 bytes --]
The patch for the IRQ balancing.
Thanks,
Nitin
diff -Naru 2.5.52/Documentation/kernel-parameters.txt
kirqb/Documentation/kernel-parameters.txt
--- 2.5.52/Documentation/kernel-parameters.txt Tue Dec 17 15:35:57 2002
+++ kirqb/Documentation/kernel-parameters.txt Tue Dec 17 15:37:29 2002
@@ -352,6 +352,8 @@
hugepages= [HW,IA-32] Maximal number of HugeTLB pages
+ noirqbalance [IA-32,SMP,KNL] Disable kernel irq balancing
+
i8042_direct [HW] Non-translated mode
i8042_dumbkbd
i8042_noaux
diff -Naru 2.5.52/arch/i386/kernel/io_apic.c
kirqb/arch/i386/kernel/io_apic.c
--- 2.5.52/arch/i386/kernel/io_apic.c Tue Dec 17 15:35:26 2002
+++ kirqb/arch/i386/kernel/io_apic.c Fri Dec 20 01:23:15 2002
@@ -206,19 +206,37 @@
spin_unlock_irqrestore(&ioapic_lock, flags);
}
-#if CONFIG_SMP
+#if defined(CONFIG_SMP)
+# include <asm/processor.h> /* kernel_thread() */
+# include <linux/kernel_stat.h> /* kstat */
+# include <linux/slab.h> /* kmalloc() */
+# include <linux/timer.h> /* time_after() */
+
+# if CONFIG_BALANCED_IRQ_DEBUG
+# define TDprintk(x...) do { printk("<%ld:%s:%d>: ", jiffies,
__FILE__, __LINE__); printk(x); } while (0)
+# define Dprintk(x...) do { TDprintk(x); } while (0)
+# else
+# define TDprintk(x...)
+# define Dprintk(x...)
+# endif
-typedef struct {
- unsigned int cpu;
- unsigned long timestamp;
-} ____cacheline_aligned irq_balance_t;
-
-static irq_balance_t irq_balance[NR_IRQS] __cacheline_aligned
- = { [ 0 ... NR_IRQS-1 ] = { 0, 0 } };
+# define MIN(a,b) (((a) < (b)) ? (a) : (b))
+# define MAX(a,b) (((a) > (b)) ? (a) : (b))
extern unsigned long irq_affinity [NR_IRQS];
-
-#endif
+unsigned long __cacheline_aligned irq_balance_mask [NR_IRQS];
+static int irqbalance_disabled __initdata = 0;
+static int physical_balance = 0;
+
+struct irq_cpu_info {
+ unsigned long * last_irq;
+ unsigned long * irq_delta;
+ unsigned long irq;
+} irq_cpu_data[NR_CPUS];
+
+#define CPU_IRQ(cpu) (irq_cpu_data[cpu].irq)
+#define LAST_CPU_IRQ(cpu,irq) (irq_cpu_data[cpu].last_irq[irq])
+#define IRQ_DELTA(cpu,irq) (irq_cpu_data[cpu].irq_delta[irq])
#define IDLE_ENOUGH(cpu,now) \
(idle_cpu(cpu) && ((now) -
irq_stat[(cpu)].idle_timestamp > 1))
@@ -226,10 +244,224 @@
#define IRQ_ALLOWED(cpu,allowed_mask) \
((1 << cpu) & (allowed_mask))
-#if CONFIG_SMP
+#define CPU_TO_PACKAGEINDEX(i) \
+ ((physical_balance && i > cpu_sibling_map[i]) ?
cpu_sibling_map[i] : i)
+
+#define MAX_BALANCED_IRQ_INTERVAL (5*HZ)
+#define MIN_BALANCED_IRQ_INTERVAL (HZ/2)
+#define BALANCED_IRQ_MORE_DELTA (HZ/10)
+#define BALANCED_IRQ_LESS_DELTA (HZ)
+
+unsigned long balanced_irq_interval = MAX_BALANCED_IRQ_INTERVAL;
+
+static inline void balance_irq(int cpu, int irq);
+
+static inline void rotate_irqs_among_cpus(unsigned long
useful_load_threshold)
+{
+ int i, j;
+ Dprintk("Rotating IRQs among CPUs.\n");
+ for (i = 0; i < NR_CPUS; i++) {
+ for (j = 0; cpu_online(i) && (j < NR_IRQS); j++) {
+ if (!irq_desc[j].action)
+ continue;
+ /* Is it a significant load ? */
+ if (IRQ_DELTA(CPU_TO_PACKAGEINDEX(i),j) <
useful_load_threshold)
+ continue;
+ balance_irq(i, j);
+ }
+ }
+ balanced_irq_interval = MAX(MIN_BALANCED_IRQ_INTERVAL,
+ balanced_irq_interval - BALANCED_IRQ_LESS_DELTA);
+ return;
+}
+
+static void do_irq_balance(void)
+{
+ int i, j;
+ unsigned long max_cpu_irq = 0, min_cpu_irq = (~0);
+ unsigned long move_this_load = 0;
+ int max_loaded = 0, min_loaded = 0;
+ unsigned long useful_load_threshold = balanced_irq_interval +
10;
+ int selected_irq;
+ int tmp_loaded, first_attempt = 1;
+ unsigned long tmp_cpu_irq;
+ unsigned long imbalance = 0;
+ unsigned long allowed_mask;
+ unsigned long target_cpu_mask;
+
+ for (i = 0; i < NR_CPUS; i++) {
+ int package_index;
+ CPU_IRQ(i) = 0;
+ if (!cpu_online(i))
+ continue;
+ package_index = CPU_TO_PACKAGEINDEX(i);
+ for (j = 0; j < NR_IRQS; j++) {
+ unsigned long value_now, delta;
+ /* Is this an active IRQ? */
+ if (!irq_desc[j].action)
+ continue;
+ if (package_index == i)
+ IRQ_DELTA(package_index,j) = 0;
+ /* Determine the total count per processor per
IRQ */
+ value_now = (unsigned long)
kstat_cpu(i).irqs[j];
+
+ /* Determine the activity per processor per IRQ
*/
+ delta = value_now - LAST_CPU_IRQ(i,j);
+
+ /* Update last_cpu_irq[][] for the next time */
+ LAST_CPU_IRQ(i,j) = value_now;
+
+ /* Ignore IRQs whose rate is less than the clock
*/
+ if (delta < useful_load_threshold)
+ continue;
+ /* update the load for the processor or package
total */
+ IRQ_DELTA(package_index,j) += delta;
+
+ /* Keep track of the higher numbered sibling as
well */
+ if (i != package_index)
+ CPU_IRQ(i) += delta;
+ /*
+ * We have sibling A and sibling B in the
package
+ *
+ * cpu_irq[A] = load for cpu A + load for cpu B
+ * cpu_irq[B] = load for cpu B
+ */
+ CPU_IRQ(package_index) += delta;
+ }
+ }
+ /* Find the least loaded processor package */
+ for (i = 0; i < NR_CPUS; i++) {
+ if (!cpu_online(i))
+ continue;
+ if (physical_balance && i > cpu_sibling_map[i])
+ continue;
+ if (min_cpu_irq > CPU_IRQ(i)) {
+ min_cpu_irq = CPU_IRQ(i);
+ min_loaded = i;
+ }
+ }
+ max_cpu_irq = ULONG_MAX;
+
+tryanothercpu:
+ /* Look for heaviest loaded processor.
+ * We may come back to get the next heaviest loaded processor.
+ * Skip processors with trivial loads.
+ */
+ tmp_cpu_irq = 0;
+ tmp_loaded = -1;
+ for (i = 0; i < NR_CPUS; i++) {
+ if (!cpu_online(i))
+ continue;
+ if (physical_balance && i > cpu_sibling_map[i])
+ continue;
+ if (max_cpu_irq <= CPU_IRQ(i))
+ continue;
+ if (tmp_cpu_irq < CPU_IRQ(i)) {
+ tmp_cpu_irq = CPU_IRQ(i);
+ tmp_loaded = i;
+ }
+ }
+
+ if (tmp_loaded == -1) {
+ /* In the case of small number of heavy interrupt sources,
+ * loading some of the cpus too much. We use Ingo's original
+ * approach to rotate them around.
+ */
+ if (!first_attempt && imbalance >=
useful_load_threshold) {
+ rotate_irqs_among_cpus(useful_load_threshold);
+ return;
+ }
+ goto not_worth_the_effort;
+ }
+
+ first_attempt = 0; /* heaviest search */
+ max_cpu_irq = tmp_cpu_irq; /* load */
+ max_loaded = tmp_loaded; /* processor */
+ imbalance = (max_cpu_irq - min_cpu_irq) / 2;
+
+ Dprintk("max_loaded cpu = %d\n", max_loaded);
+ Dprintk("min_loaded cpu = %d\n", min_loaded);
+ Dprintk("max_cpu_irq load = %ld\n", max_cpu_irq);
+ Dprintk("min_cpu_irq load = %ld\n", min_cpu_irq);
+ Dprintk("load imbalance = %lu\n", imbalance);
+
+ /* if imbalance is less than approx 10% of max load, then
+ * observe diminishing returns action. - quit
+ */
+ if (imbalance < (max_cpu_irq >> 3)) {
+ Dprintk("Imbalance too trivial\n");
+ goto not_worth_the_effort;
+ }
+
+tryanotherirq:
+ /* if we select an IRQ to move that can't go where we want, then
+ * see if there is another one to try.
+ */
+ move_this_load = 0;
+ selected_irq = -1;
+ for (j = 0; j < NR_IRQS; j++) {
+ /* Is this an active IRQ? */
+ if (!irq_desc[j].action)
+ continue;
+ if (imbalance <= IRQ_DELTA(max_loaded,j))
+ continue;
+ /* Try to find the IRQ that is closest to the imbalance
+ * without going over.
+ */
+ if (move_this_load < IRQ_DELTA(max_loaded,j)) {
+ move_this_load = IRQ_DELTA(max_loaded,j);
+ selected_irq = j;
+ }
+ }
+ if (selected_irq == -1) {
+ goto tryanothercpu;
+ }
-#define IRQ_BALANCE_INTERVAL (HZ/50)
+ imbalance = move_this_load;
+ /* For physical_balance case, we accumlated both load
+ * values in the one of the siblings cpu_irq[],
+ * to use the same code for physical and logical processors
+ * as much as possible.
+ *
+ * NOTE: the cpu_irq[] array holds the sum of the load for
+ * sibling A and sibling B in the slot for the lowest numbered
+ * sibling (A), _AND_ the load for sibling B in the slot for
+ * the higher numbered sibling.
+ *
+ * We seek the least loaded sibling by making the comparison
+ * (A+B)/2 vs B
+ */
+ if (physical_balance && (CPU_IRQ(min_loaded) >> 1) >
CPU_IRQ(cpu_sibling_map[min_loaded]))
+ min_loaded = cpu_sibling_map[min_loaded];
+
+ allowed_mask = cpu_online_map & irq_affinity[selected_irq];
+ target_cpu_mask = 1 << min_loaded;
+
+ if (target_cpu_mask & allowed_mask) {
+ irq_desc_t *desc = irq_desc + selected_irq;
+ Dprintk("irq = %d moved to cpu = %d\n", selected_irq,
min_loaded);
+ /* mark for change destination */
+ spin_lock(&desc->lock);
+ irq_balance_mask[selected_irq] = target_cpu_mask;
+ spin_unlock(&desc->lock);
+ /* Since we made a change, come back sooner to
+ * check for more variation.
+ */
+ balanced_irq_interval = MAX(MIN_BALANCED_IRQ_INTERVAL,
+ balanced_irq_interval -
BALANCED_IRQ_LESS_DELTA);
+ return;
+ }
+ goto tryanotherirq;
+
+not_worth_the_effort:
+ /* if we did not find an IRQ to move, then adjust the time
interval upward */
+ balanced_irq_interval = MIN(MAX_BALANCED_IRQ_INTERVAL,
+ balanced_irq_interval + BALANCED_IRQ_MORE_DELTA);
+ Dprintk("IRQ worth rotating not found\n");
+ return;
+}
+
static unsigned long move(int curr_cpu, unsigned long allowed_mask,
unsigned long now, int direction)
{
int search_idle = 1;
@@ -256,34 +488,112 @@
return cpu;
}
-static inline void balance_irq(int irq)
+static inline void balance_irq (int cpu, int irq)
{
- irq_balance_t *entry = irq_balance + irq;
unsigned long now = jiffies;
-
+ unsigned long allowed_mask;
+ unsigned int new_cpu;
+
if (clustered_apic_mode)
return;
- if (unlikely(time_after(now, entry->timestamp +
IRQ_BALANCE_INTERVAL))) {
- unsigned long allowed_mask;
- unsigned int new_cpu;
- int random_number;
-
- rdtscl(random_number);
- random_number &= 1;
-
- allowed_mask = cpu_online_map & irq_affinity[irq];
- entry->timestamp = now;
- new_cpu = move(entry->cpu, allowed_mask, now,
random_number);
- if (entry->cpu != new_cpu) {
- entry->cpu = new_cpu;
- set_ioapic_affinity(irq, 1 << new_cpu);
+ allowed_mask = cpu_online_map & irq_affinity[irq];
+ new_cpu = move(cpu, allowed_mask, now, 1);
+ if (cpu != new_cpu) {
+ irq_desc_t *desc = irq_desc + irq;
+ spin_lock(&desc->lock);
+ irq_balance_mask[irq] = 1 << new_cpu;
+ spin_unlock(&desc->lock);
+ }
+}
+
+int balanced_irq(void *unused)
+{
+ int i;
+ unsigned long prev_balance_time = jiffies;
+ long time_remaining = balanced_irq_interval;
+ daemonize();
+ sigfillset(¤t->blocked);
+ sprintf(current->comm, "balanced_irq");
+
+ /* push everything to CPU 0 to give us a starting point. */
+ for (i = 0 ; i < NR_IRQS ; i++)
+ irq_balance_mask[i] = 1 << 0;
+ for (;;) {
+ set_current_state(TASK_INTERRUPTIBLE);
+ time_remaining = schedule_timeout(time_remaining);
+ if (time_after(jiffies,
prev_balance_time+balanced_irq_interval)) {
+ Dprintk("balanced_irq: calling do_irq_balance()
%lu\n", jiffies);
+ do_irq_balance();
+ prev_balance_time = jiffies;
+ time_remaining = balanced_irq_interval;
}
+ }
+}
+
+static int __init balanced_irq_init(void)
+{
+ int i;
+ struct cpuinfo_x86 *c;
+ c = &boot_cpu_data;
+ if (irqbalance_disabled)
+ return 0;
+ /* Enable physical balance only if more than
+ * one physical processor package is present */
+ if (smp_num_siblings > 1 && cpu_online_map >> 2)
+ physical_balance = 1;
+
+ for (i = 0; i < NR_CPUS; i++) {
+ if (!cpu_online(i))
+ continue;
+ irq_cpu_data[i].irq_delta = kmalloc(sizeof(unsigned
long) * NR_IRQS, GFP_KERNEL);
+ irq_cpu_data[i].last_irq = kmalloc(sizeof(unsigned long)
* NR_IRQS, GFP_KERNEL);
+ if (irq_cpu_data[i].irq_delta == NULL ||
irq_cpu_data[i].last_irq == NULL) {
+ printk(KERN_ERR "balanced_irq_init: out of
memory");
+ goto failed;
+ }
+ memset(irq_cpu_data[i].irq_delta,0,sizeof(unsigned long)
* NR_IRQS);
+ memset(irq_cpu_data[i].last_irq,0,sizeof(unsigned long)
* NR_IRQS);
+ }
+
+ printk(KERN_INFO "Starting balanced_irq\n");
+ if (kernel_thread(balanced_irq, NULL, CLONE_KERNEL) >= 0)
+ return 0;
+ else
+ printk(KERN_ERR "balanced_irq_init: failed to spawn
balanced_irq");
+failed:
+ for (i = 0; i < NR_CPUS; i++) {
+ if (irq_cpu_data[i].irq_delta)
+ kfree(irq_cpu_data[i].irq_delta);
+ if (irq_cpu_data[i].last_irq)
+ kfree(irq_cpu_data[i].last_irq);
}
+ return 0;
}
-#else /* !SMP */
-static inline void balance_irq(int irq) { }
-#endif
+
+static int __init irqbalance_disable(char *str)
+{
+ irqbalance_disabled = 1;
+ return 0;
+}
+
+__setup("noirqbalance", irqbalance_disable);
+
+static void set_ioapic_affinity (unsigned int irq, unsigned long mask);
+
+static inline void move_irq(int irq)
+{
+ /* note - we hold the desc->lock */
+ if (unlikely(irq_balance_mask[irq])) {
+ set_ioapic_affinity(irq, irq_balance_mask[irq]);
+ irq_balance_mask[irq] = 0;
+ }
+}
+
+__initcall(balanced_irq_init);
+
+#endif /* defined(CONFIG_SMP) */
+
/*
* support for broken MP BIOSs, enables hand-redirection of PIRQ0-7 to
@@ -1308,7 +1618,7 @@
*/
static void ack_edge_ioapic_irq(unsigned int irq)
{
- balance_irq(irq);
+ move_irq(irq);
if ((irq_desc[irq].status & (IRQ_PENDING | IRQ_DISABLED))
== (IRQ_PENDING | IRQ_DISABLED))
mask_IO_APIC_irq(irq);
@@ -1348,7 +1658,7 @@
unsigned long v;
int i;
- balance_irq(irq);
+ move_irq(irq);
/*
* It appears there is an erratum which affects at least version 0x11
* of I/O APIC (that's the 82093AA and cores integrated into various
[-- Attachment #2: kirqb_2.5.52.patch --]
[-- Type: application/octet-stream, Size: 13221 bytes --]
diff -Naru 2.5.52/Documentation/kernel-parameters.txt kirqb/Documentation/kernel-parameters.txt
--- 2.5.52/Documentation/kernel-parameters.txt Tue Dec 17 15:35:57 2002
+++ kirqb/Documentation/kernel-parameters.txt Tue Dec 17 15:37:29 2002
@@ -352,6 +352,8 @@
hugepages= [HW,IA-32] Maximal number of HugeTLB pages
+ noirqbalance [IA-32,SMP,KNL] Disable kernel irq balancing
+
i8042_direct [HW] Non-translated mode
i8042_dumbkbd
i8042_noaux
diff -Naru 2.5.52/arch/i386/kernel/io_apic.c kirqb/arch/i386/kernel/io_apic.c
--- 2.5.52/arch/i386/kernel/io_apic.c Tue Dec 17 15:35:26 2002
+++ kirqb/arch/i386/kernel/io_apic.c Fri Dec 20 01:23:15 2002
@@ -206,19 +206,37 @@
spin_unlock_irqrestore(&ioapic_lock, flags);
}
-#if CONFIG_SMP
+#if defined(CONFIG_SMP)
+# include <asm/processor.h> /* kernel_thread() */
+# include <linux/kernel_stat.h> /* kstat */
+# include <linux/slab.h> /* kmalloc() */
+# include <linux/timer.h> /* time_after() */
+
+# if CONFIG_BALANCED_IRQ_DEBUG
+# define TDprintk(x...) do { printk("<%ld:%s:%d>: ", jiffies, __FILE__, __LINE__); printk(x); } while (0)
+# define Dprintk(x...) do { TDprintk(x); } while (0)
+# else
+# define TDprintk(x...)
+# define Dprintk(x...)
+# endif
-typedef struct {
- unsigned int cpu;
- unsigned long timestamp;
-} ____cacheline_aligned irq_balance_t;
-
-static irq_balance_t irq_balance[NR_IRQS] __cacheline_aligned
- = { [ 0 ... NR_IRQS-1 ] = { 0, 0 } };
+# define MIN(a,b) (((a) < (b)) ? (a) : (b))
+# define MAX(a,b) (((a) > (b)) ? (a) : (b))
extern unsigned long irq_affinity [NR_IRQS];
-
-#endif
+unsigned long __cacheline_aligned irq_balance_mask [NR_IRQS];
+static int irqbalance_disabled __initdata = 0;
+static int physical_balance = 0;
+
+struct irq_cpu_info {
+ unsigned long * last_irq;
+ unsigned long * irq_delta;
+ unsigned long irq;
+} irq_cpu_data[NR_CPUS];
+
+#define CPU_IRQ(cpu) (irq_cpu_data[cpu].irq)
+#define LAST_CPU_IRQ(cpu,irq) (irq_cpu_data[cpu].last_irq[irq])
+#define IRQ_DELTA(cpu,irq) (irq_cpu_data[cpu].irq_delta[irq])
#define IDLE_ENOUGH(cpu,now) \
(idle_cpu(cpu) && ((now) - irq_stat[(cpu)].idle_timestamp > 1))
@@ -226,10 +244,224 @@
#define IRQ_ALLOWED(cpu,allowed_mask) \
((1 << cpu) & (allowed_mask))
-#if CONFIG_SMP
+#define CPU_TO_PACKAGEINDEX(i) \
+ ((physical_balance && i > cpu_sibling_map[i]) ? cpu_sibling_map[i] : i)
+
+#define MAX_BALANCED_IRQ_INTERVAL (5*HZ)
+#define MIN_BALANCED_IRQ_INTERVAL (HZ/2)
+#define BALANCED_IRQ_MORE_DELTA (HZ/10)
+#define BALANCED_IRQ_LESS_DELTA (HZ)
+
+unsigned long balanced_irq_interval = MAX_BALANCED_IRQ_INTERVAL;
+
+static inline void balance_irq(int cpu, int irq);
+
+static inline void rotate_irqs_among_cpus(unsigned long useful_load_threshold)
+{
+ int i, j;
+ Dprintk("Rotating IRQs among CPUs.\n");
+ for (i = 0; i < NR_CPUS; i++) {
+ for (j = 0; cpu_online(i) && (j < NR_IRQS); j++) {
+ if (!irq_desc[j].action)
+ continue;
+ /* Is it a significant load ? */
+ if (IRQ_DELTA(CPU_TO_PACKAGEINDEX(i),j) < useful_load_threshold)
+ continue;
+ balance_irq(i, j);
+ }
+ }
+ balanced_irq_interval = MAX(MIN_BALANCED_IRQ_INTERVAL,
+ balanced_irq_interval - BALANCED_IRQ_LESS_DELTA);
+ return;
+}
+
+static void do_irq_balance(void)
+{
+ int i, j;
+ unsigned long max_cpu_irq = 0, min_cpu_irq = (~0);
+ unsigned long move_this_load = 0;
+ int max_loaded = 0, min_loaded = 0;
+ unsigned long useful_load_threshold = balanced_irq_interval + 10;
+ int selected_irq;
+ int tmp_loaded, first_attempt = 1;
+ unsigned long tmp_cpu_irq;
+ unsigned long imbalance = 0;
+ unsigned long allowed_mask;
+ unsigned long target_cpu_mask;
+
+ for (i = 0; i < NR_CPUS; i++) {
+ int package_index;
+ CPU_IRQ(i) = 0;
+ if (!cpu_online(i))
+ continue;
+ package_index = CPU_TO_PACKAGEINDEX(i);
+ for (j = 0; j < NR_IRQS; j++) {
+ unsigned long value_now, delta;
+ /* Is this an active IRQ? */
+ if (!irq_desc[j].action)
+ continue;
+ if (package_index == i)
+ IRQ_DELTA(package_index,j) = 0;
+ /* Determine the total count per processor per IRQ */
+ value_now = (unsigned long) kstat_cpu(i).irqs[j];
+
+ /* Determine the activity per processor per IRQ */
+ delta = value_now - LAST_CPU_IRQ(i,j);
+
+ /* Update last_cpu_irq[][] for the next time */
+ LAST_CPU_IRQ(i,j) = value_now;
+
+ /* Ignore IRQs whose rate is less than the clock */
+ if (delta < useful_load_threshold)
+ continue;
+ /* update the load for the processor or package total */
+ IRQ_DELTA(package_index,j) += delta;
+
+ /* Keep track of the higher numbered sibling as well */
+ if (i != package_index)
+ CPU_IRQ(i) += delta;
+ /*
+ * We have sibling A and sibling B in the package
+ *
+ * cpu_irq[A] = load for cpu A + load for cpu B
+ * cpu_irq[B] = load for cpu B
+ */
+ CPU_IRQ(package_index) += delta;
+ }
+ }
+ /* Find the least loaded processor package */
+ for (i = 0; i < NR_CPUS; i++) {
+ if (!cpu_online(i))
+ continue;
+ if (physical_balance && i > cpu_sibling_map[i])
+ continue;
+ if (min_cpu_irq > CPU_IRQ(i)) {
+ min_cpu_irq = CPU_IRQ(i);
+ min_loaded = i;
+ }
+ }
+ max_cpu_irq = ULONG_MAX;
+
+tryanothercpu:
+ /* Look for heaviest loaded processor.
+ * We may come back to get the next heaviest loaded processor.
+ * Skip processors with trivial loads.
+ */
+ tmp_cpu_irq = 0;
+ tmp_loaded = -1;
+ for (i = 0; i < NR_CPUS; i++) {
+ if (!cpu_online(i))
+ continue;
+ if (physical_balance && i > cpu_sibling_map[i])
+ continue;
+ if (max_cpu_irq <= CPU_IRQ(i))
+ continue;
+ if (tmp_cpu_irq < CPU_IRQ(i)) {
+ tmp_cpu_irq = CPU_IRQ(i);
+ tmp_loaded = i;
+ }
+ }
+
+ if (tmp_loaded == -1) {
+ /* In the case of small number of heavy interrupt sources,
+ * loading some of the cpus too much. We use Ingo's original
+ * approach to rotate them around.
+ */
+ if (!first_attempt && imbalance >= useful_load_threshold) {
+ rotate_irqs_among_cpus(useful_load_threshold);
+ return;
+ }
+ goto not_worth_the_effort;
+ }
+
+ first_attempt = 0; /* heaviest search */
+ max_cpu_irq = tmp_cpu_irq; /* load */
+ max_loaded = tmp_loaded; /* processor */
+ imbalance = (max_cpu_irq - min_cpu_irq) / 2;
+
+ Dprintk("max_loaded cpu = %d\n", max_loaded);
+ Dprintk("min_loaded cpu = %d\n", min_loaded);
+ Dprintk("max_cpu_irq load = %ld\n", max_cpu_irq);
+ Dprintk("min_cpu_irq load = %ld\n", min_cpu_irq);
+ Dprintk("load imbalance = %lu\n", imbalance);
+
+ /* if imbalance is less than approx 10% of max load, then
+ * observe diminishing returns action. - quit
+ */
+ if (imbalance < (max_cpu_irq >> 3)) {
+ Dprintk("Imbalance too trivial\n");
+ goto not_worth_the_effort;
+ }
+
+tryanotherirq:
+ /* if we select an IRQ to move that can't go where we want, then
+ * see if there is another one to try.
+ */
+ move_this_load = 0;
+ selected_irq = -1;
+ for (j = 0; j < NR_IRQS; j++) {
+ /* Is this an active IRQ? */
+ if (!irq_desc[j].action)
+ continue;
+ if (imbalance <= IRQ_DELTA(max_loaded,j))
+ continue;
+ /* Try to find the IRQ that is closest to the imbalance
+ * without going over.
+ */
+ if (move_this_load < IRQ_DELTA(max_loaded,j)) {
+ move_this_load = IRQ_DELTA(max_loaded,j);
+ selected_irq = j;
+ }
+ }
+ if (selected_irq == -1) {
+ goto tryanothercpu;
+ }
-#define IRQ_BALANCE_INTERVAL (HZ/50)
+ imbalance = move_this_load;
+ /* For physical_balance case, we accumlated both load
+ * values in the one of the siblings cpu_irq[],
+ * to use the same code for physical and logical processors
+ * as much as possible.
+ *
+ * NOTE: the cpu_irq[] array holds the sum of the load for
+ * sibling A and sibling B in the slot for the lowest numbered
+ * sibling (A), _AND_ the load for sibling B in the slot for
+ * the higher numbered sibling.
+ *
+ * We seek the least loaded sibling by making the comparison
+ * (A+B)/2 vs B
+ */
+ if (physical_balance && (CPU_IRQ(min_loaded) >> 1) > CPU_IRQ(cpu_sibling_map[min_loaded]))
+ min_loaded = cpu_sibling_map[min_loaded];
+
+ allowed_mask = cpu_online_map & irq_affinity[selected_irq];
+ target_cpu_mask = 1 << min_loaded;
+
+ if (target_cpu_mask & allowed_mask) {
+ irq_desc_t *desc = irq_desc + selected_irq;
+ Dprintk("irq = %d moved to cpu = %d\n", selected_irq, min_loaded);
+ /* mark for change destination */
+ spin_lock(&desc->lock);
+ irq_balance_mask[selected_irq] = target_cpu_mask;
+ spin_unlock(&desc->lock);
+ /* Since we made a change, come back sooner to
+ * check for more variation.
+ */
+ balanced_irq_interval = MAX(MIN_BALANCED_IRQ_INTERVAL,
+ balanced_irq_interval - BALANCED_IRQ_LESS_DELTA);
+ return;
+ }
+ goto tryanotherirq;
+
+not_worth_the_effort:
+ /* if we did not find an IRQ to move, then adjust the time interval upward */
+ balanced_irq_interval = MIN(MAX_BALANCED_IRQ_INTERVAL,
+ balanced_irq_interval + BALANCED_IRQ_MORE_DELTA);
+ Dprintk("IRQ worth rotating not found\n");
+ return;
+}
+
static unsigned long move(int curr_cpu, unsigned long allowed_mask, unsigned long now, int direction)
{
int search_idle = 1;
@@ -256,34 +488,112 @@
return cpu;
}
-static inline void balance_irq(int irq)
+static inline void balance_irq (int cpu, int irq)
{
- irq_balance_t *entry = irq_balance + irq;
unsigned long now = jiffies;
-
+ unsigned long allowed_mask;
+ unsigned int new_cpu;
+
if (clustered_apic_mode)
return;
- if (unlikely(time_after(now, entry->timestamp + IRQ_BALANCE_INTERVAL))) {
- unsigned long allowed_mask;
- unsigned int new_cpu;
- int random_number;
-
- rdtscl(random_number);
- random_number &= 1;
-
- allowed_mask = cpu_online_map & irq_affinity[irq];
- entry->timestamp = now;
- new_cpu = move(entry->cpu, allowed_mask, now, random_number);
- if (entry->cpu != new_cpu) {
- entry->cpu = new_cpu;
- set_ioapic_affinity(irq, 1 << new_cpu);
+ allowed_mask = cpu_online_map & irq_affinity[irq];
+ new_cpu = move(cpu, allowed_mask, now, 1);
+ if (cpu != new_cpu) {
+ irq_desc_t *desc = irq_desc + irq;
+ spin_lock(&desc->lock);
+ irq_balance_mask[irq] = 1 << new_cpu;
+ spin_unlock(&desc->lock);
+ }
+}
+
+int balanced_irq(void *unused)
+{
+ int i;
+ unsigned long prev_balance_time = jiffies;
+ long time_remaining = balanced_irq_interval;
+ daemonize();
+ sigfillset(¤t->blocked);
+ sprintf(current->comm, "balanced_irq");
+
+ /* push everything to CPU 0 to give us a starting point. */
+ for (i = 0 ; i < NR_IRQS ; i++)
+ irq_balance_mask[i] = 1 << 0;
+ for (;;) {
+ set_current_state(TASK_INTERRUPTIBLE);
+ time_remaining = schedule_timeout(time_remaining);
+ if (time_after(jiffies, prev_balance_time+balanced_irq_interval)) {
+ Dprintk("balanced_irq: calling do_irq_balance() %lu\n", jiffies);
+ do_irq_balance();
+ prev_balance_time = jiffies;
+ time_remaining = balanced_irq_interval;
}
+ }
+}
+
+static int __init balanced_irq_init(void)
+{
+ int i;
+ struct cpuinfo_x86 *c;
+ c = &boot_cpu_data;
+ if (irqbalance_disabled)
+ return 0;
+ /* Enable physical balance only if more than
+ * one physical processor package is present */
+ if (smp_num_siblings > 1 && cpu_online_map >> 2)
+ physical_balance = 1;
+
+ for (i = 0; i < NR_CPUS; i++) {
+ if (!cpu_online(i))
+ continue;
+ irq_cpu_data[i].irq_delta = kmalloc(sizeof(unsigned long) * NR_IRQS, GFP_KERNEL);
+ irq_cpu_data[i].last_irq = kmalloc(sizeof(unsigned long) * NR_IRQS, GFP_KERNEL);
+ if (irq_cpu_data[i].irq_delta == NULL || irq_cpu_data[i].last_irq == NULL) {
+ printk(KERN_ERR "balanced_irq_init: out of memory");
+ goto failed;
+ }
+ memset(irq_cpu_data[i].irq_delta,0,sizeof(unsigned long) * NR_IRQS);
+ memset(irq_cpu_data[i].last_irq,0,sizeof(unsigned long) * NR_IRQS);
+ }
+
+ printk(KERN_INFO "Starting balanced_irq\n");
+ if (kernel_thread(balanced_irq, NULL, CLONE_KERNEL) >= 0)
+ return 0;
+ else
+ printk(KERN_ERR "balanced_irq_init: failed to spawn balanced_irq");
+failed:
+ for (i = 0; i < NR_CPUS; i++) {
+ if (irq_cpu_data[i].irq_delta)
+ kfree(irq_cpu_data[i].irq_delta);
+ if (irq_cpu_data[i].last_irq)
+ kfree(irq_cpu_data[i].last_irq);
}
+ return 0;
}
-#else /* !SMP */
-static inline void balance_irq(int irq) { }
-#endif
+
+static int __init irqbalance_disable(char *str)
+{
+ irqbalance_disabled = 1;
+ return 0;
+}
+
+__setup("noirqbalance", irqbalance_disable);
+
+static void set_ioapic_affinity (unsigned int irq, unsigned long mask);
+
+static inline void move_irq(int irq)
+{
+ /* note - we hold the desc->lock */
+ if (unlikely(irq_balance_mask[irq])) {
+ set_ioapic_affinity(irq, irq_balance_mask[irq]);
+ irq_balance_mask[irq] = 0;
+ }
+}
+
+__initcall(balanced_irq_init);
+
+#endif /* defined(CONFIG_SMP) */
+
/*
* support for broken MP BIOSs, enables hand-redirection of PIRQ0-7 to
@@ -1308,7 +1618,7 @@
*/
static void ack_edge_ioapic_irq(unsigned int irq)
{
- balance_irq(irq);
+ move_irq(irq);
if ((irq_desc[irq].status & (IRQ_PENDING | IRQ_DISABLED))
== (IRQ_PENDING | IRQ_DISABLED))
mask_IO_APIC_irq(irq);
@@ -1348,7 +1658,7 @@
unsigned long v;
int i;
- balance_irq(irq);
+ move_irq(irq);
/*
* It appears there is an erratum which affects at least version 0x11
* of I/O APIC (that's the 82093AA and cores integrated into various
^ permalink raw reply
* [PATCH] linux-2.5.54_delay-cleanup_A0
From: john stultz @ 2003-01-08 2:46 UTC (permalink / raw)
To: Linus Torvalds; +Cc: lkml
Linus, all,
I've been busy with other things, so I've just been sitting on this for
a while. Anyway, I figured it was about time to resend.
This patch tries to cleanup the delay code by moving the timer-specific
implementations into the timer_ops struct. Thus, rather then doing:
if(x86_delay_tsc)
__rdtsc_delay(loops);
else if(x86_delay_cyclone)
__cyclone_delay(loops);
else if(whatever....
we just simply do:
if(timer)
timer->delay(loops);
Making it much easier to accommodate alternate time sources.
Please apply.
thanks
-john
diff -Nru a/arch/i386/kernel/timers/timer_cyclone.c b/arch/i386/kernel/timers/timer_cyclone.c
--- a/arch/i386/kernel/timers/timer_cyclone.c Tue Jan 7 17:11:03 2003
+++ b/arch/i386/kernel/timers/timer_cyclone.c Tue Jan 7 17:11:03 2003
@@ -150,7 +150,6 @@
}
-#if 0 /* XXX future work */
static void delay_cyclone(unsigned long loops)
{
unsigned long bclock, now;
@@ -162,12 +161,12 @@
now = cyclone_timer[0];
} while ((now-bclock) < loops);
}
-#endif
/************************************************************/
/* cyclone timer_opts struct */
struct timer_opts timer_cyclone = {
.init = init_cyclone,
.mark_offset = mark_offset_cyclone,
- .get_offset = get_offset_cyclone
+ .get_offset = get_offset_cyclone,
+ .delay = delay_cyclone,
};
diff -Nru a/arch/i386/kernel/timers/timer_pit.c b/arch/i386/kernel/timers/timer_pit.c
--- a/arch/i386/kernel/timers/timer_pit.c Tue Jan 7 17:11:03 2003
+++ b/arch/i386/kernel/timers/timer_pit.c Tue Jan 7 17:11:03 2003
@@ -27,6 +27,19 @@
/* nothing needed */
}
+static void delay_pit(unsigned long loops)
+{
+ int d0;
+ __asm__ __volatile__(
+ "\tjmp 1f\n"
+ ".align 16\n"
+ "1:\tjmp 2f\n"
+ ".align 16\n"
+ "2:\tdecl %0\n\tjns 2b"
+ :"=&a" (d0)
+ :"0" (loops));
+}
+
/* This function must be called with interrupts disabled
* It was inspired by Steve McCanne's microtime-i386 for BSD. -- jrs
@@ -129,4 +142,5 @@
.init = init_pit,
.mark_offset = mark_offset_pit,
.get_offset = get_offset_pit,
+ .delay = delay_pit,
};
diff -Nru a/arch/i386/kernel/timers/timer_tsc.c b/arch/i386/kernel/timers/timer_tsc.c
--- a/arch/i386/kernel/timers/timer_tsc.c Tue Jan 7 17:11:03 2003
+++ b/arch/i386/kernel/timers/timer_tsc.c Tue Jan 7 17:11:03 2003
@@ -16,7 +16,6 @@
int tsc_disable __initdata = 0;
-extern int x86_udelay_tsc;
extern spinlock_t i8253_lock;
static int use_tsc;
@@ -107,6 +106,17 @@
delay_at_last_interrupt = (count + LATCH/2) / LATCH;
}
+static void delay_tsc(unsigned long loops)
+{
+ unsigned long bclock, now;
+
+ rdtscl(bclock);
+ do
+ {
+ rep_nop();
+ rdtscl(now);
+ } while ((now-bclock) < loops);
+}
/* ------ Calibrate the TSC -------
* Return 2^32 * (1 / (TSC clocks per usec)) for do_fast_gettimeoffset().
@@ -272,8 +282,6 @@
* We could be more selective here I suspect
* and just enable this for the next intel chips ?
*/
- x86_udelay_tsc = 1;
-
/* report CPU clock rate in Hz.
* The formula is (10^6 * 2^32) / (2^32 * 1 / (clocks/us)) =
* clock/second. Our precision is about 100 ppm.
@@ -310,4 +318,5 @@
.init = init_tsc,
.mark_offset = mark_offset_tsc,
.get_offset = get_offset_tsc,
+ .delay = delay_tsc,
};
diff -Nru a/arch/i386/lib/delay.c b/arch/i386/lib/delay.c
--- a/arch/i386/lib/delay.c Tue Jan 7 17:11:03 2003
+++ b/arch/i386/lib/delay.c Tue Jan 7 17:11:03 2003
@@ -15,35 +15,18 @@
#include <linux/delay.h>
#include <asm/processor.h>
#include <asm/delay.h>
+#include <asm/timer.h>
#ifdef CONFIG_SMP
#include <asm/smp.h>
#endif
-int x86_udelay_tsc = 0; /* Delay via TSC */
+extern struct timer_opts* timer;
-
/*
- * Do a udelay using the TSC for any CPU that happens
- * to have one that we trust.
+ * Backup non-TSC based delay loop.
+ * Used until a timer is chosen.
*/
-
-static void __rdtsc_delay(unsigned long loops)
-{
- unsigned long bclock, now;
-
- rdtscl(bclock);
- do
- {
- rep_nop();
- rdtscl(now);
- } while ((now-bclock) < loops);
-}
-
-/*
- * Non TSC based delay loop for 386, 486, MediaGX
- */
-
static void __loop_delay(unsigned long loops)
{
int d0;
@@ -59,8 +42,8 @@
void __delay(unsigned long loops)
{
- if (x86_udelay_tsc)
- __rdtsc_delay(loops);
+ if(timer)
+ timer->delay(loops);
else
__loop_delay(loops);
}
diff -Nru a/include/asm-i386/timer.h b/include/asm-i386/timer.h
--- a/include/asm-i386/timer.h Tue Jan 7 17:11:03 2003
+++ b/include/asm-i386/timer.h Tue Jan 7 17:11:03 2003
@@ -14,6 +14,7 @@
int (*init)(void);
void (*mark_offset)(void);
unsigned long (*get_offset)(void);
+ void (*delay)(unsigned long);
};
#define TICK_SIZE (tick_nsec / 1000)
^ permalink raw reply
* [2.5] IRQ distribution in the 2.5.52 kernel
From: Kamble, Nitin A @ 2003-01-08 2:50 UTC (permalink / raw)
To: linux-kernel, Kamble, Nitin A
Cc: Saxena, Sunil, Mallick, Asit K, Nakajima, Jun
Hello All,
We were looking at the performance impact of the IRQ routing from
the 2.5.52 Linux kernel. This email includes some of our findings
about the way the interrupts are getting moved in the 2.5.52 kernel.
Also there is discussion and a patch for a new implementation. Let
me know what you think at nitin.a.kamble@intel.com
Current implementation:
======================
We have found that the existing implementation works well on IA32
SMP systems with light load of interrupts. Also we noticed that it
is not working that well under heavy interrupt load conditions on
these SMP systems. The observations are:
* Interrupt load of each IRQ is getting balanced on CPUs independent
of load of other IRQs. Also the current implementation moves the
IRQs randomly. This works well when the interrupt load is light. But
we start seeing imbalance of interrupt load with existence of
multiple heavy interrupt sources. Frequently multiple heavily loaded
IRQs gets moved to a single CPU while other CPUs stay very lightly
loaded. To achieve a good interrupts load balance, it is important to
consider the load of all the interrupts together.
This further can be explained with an example of 4 CPUs and 4
heavy interrupt sources. With the existing random movement approach,
the chance of each of these heavy interrupt sources moving to separate
CPUs is: (4/4)*(3/4)*(2/4)*(1/4) = 3/16. It means 13/16 = 81.25% of
the time the situation is, some CPUs are very lightly loaded and some
are loaded with multiple heavy interrupts. This causes the interrupt
load imbalance and results in less performance. In a case of 2 CPUs
and 2 heavily loaded interrupt sources, this imbalance happens
1/2 = 50% of the times. This issue becomes more and more severe with
increasing number of heavy interrupt sources.
* Another interesting observation is: We cannot see the imbalance
of the interrupt load from /proc/interrupts. (/proc/interrupts shows
the cumulative load of interrupts on all CPUs.) If the interrupt load
is imbalanced and this imbalance is getting rotated among CPUs
continuously, then /proc/interrupts will still show that the interrupt
load is going to processors very evenly. Currently at the frequency
(HZ/50) at which IRQs are moved across CPUs, it is not possible to
see any interrupt load imbalance happening.
* We have also found that, in certain cases the static IRQ binding
performs better than the existing kernel distribution of interrupt
load. The reason is, in a well-balanced interrupt load situations,
these interrupts are unnecessarily getting frequently moved across
CPUs. This adds an extra overhead; also it takes off the CPU cache
warmth benefits.
This came out from the performance measurements done on a 4-way HT
(8 logical processors) Pentium 4 Xeon system running 8 copies of
netperf. The 4 NICs in the system taking different IRQs generated
sizable interrupt load with the help of connected clients.
Here the netperf transactions/sec throughput numbers observed are:
IRQs nicely manually bound to CPUs: 56.20K
The current kernel implementation of IRQ movement: 50.05K
-----------------------
The static binding of IRQs has performed 12.28% better than the
current IRQ movement implemented in the kernel.
* The current implementation does not distinguish siblings from the
HT (Hyper-Threading(tm)) enabled CPUs. It will be beneficial to
balance the interrupt load with respect to processor packages first,
and then among logical CPUs inside processor packages.
For example if we have 2 heavy interrupt sources and 2 processor
packages (4 logical CPUs); Assigning both the heavy interrupt sources
in different processor packages is better, it will use different
execution resources from the different processor packages.
New revised implementation:
==========================
We also have been working on a new implementation. The following
points are in main focus.
* At any moment heavily loaded IRQs are distributed to different
CPUs to achieve as much balance as possible.
* Lightly loaded interrupt sources are ignored from the load
balancing, as they do not cause considerable imbalance.
* When the heavy interrupt sources are balanced, they are not moved
around. This also helps in keeping the CPU caches warm.
* It has been made HT aware. While distributing the load, the load
on a processor package to which the logical CPUs belong to is also
considered.
* In the situations of few (lesser than num_cpus) heavy interrupt
sources, it is not possible to balance them evenly. In such case
the existing code has been reused to move the interrupts. The
randomness from the original code has been removed.
* The time interval for redistribution has been made flexible. It
varies as the system interrupt load changes.
* A new kernel_thread is introduced to do the load balancing
calculations for all the interrupt sources. It keeps the balanace_maps
ready for interrupt handlers, keeping the overhead in the interrupt
handling to minimum.
* It allows the disabling of the IRQ distribution from the boot loader
command line, if anybody wants to do it for any reason.
* The algorithm also takes into account the static binding of
interrupts to CPUs that user imposes from the
/proc/irq/{n}/smp_affinity interface.
Throughput numbers with the netperf setup for the new implementation:
Current kernel IRQ balance implementation: 50.02K transactions/sec
The new IRQ balance implementation: 56.01K transactions/sec
---------------------
The performance improvement on P4 Xeon of 11.9% is observed.
The new IRQ balance implementation also shows little performance
improvement on P6 (Pentium II, III) systems.
On a P6 system the netperf throughput numbers are:
Current kernel IRQ balance implementation: 36.96K transactions/sec
The new IRQ balance implementation: 37.65K transactions/sec
---------------------
Here the performance improvement on P6 system of about 2% is observed.
Thanks & Regards,
Nitin
^ permalink raw reply
* Re: aic7xxx broken in 2.5.53/54 ?
From: Tomas Szepe @ 2003-01-08 2:41 UTC (permalink / raw)
To: Justin T. Gibbs; +Cc: dipankar, linux-scsi, linux-kernel
In-Reply-To: <274040000.1041869813@aslan.scsiguy.com>
> [gibbs@scsiguy.com]
>
> These reads are actually more expensive than just using PIO. Neither of
> these older drivers included a test to try and catch fishy behavior.
Justin, are you quite sure that these tests actually work?
I too have just run into
aic7xxx: PCI Device 0:16:0 failed memory mapped test. Using PIO.
aic7xxx: PCI Device 0:17:0 failed memory mapped test. Using PIO.
with aic79xx-linux-2.4-20021230 (6.2.25) in Linux 2.4.21-pre3.
What makes me scratch my head in particular is:
o The chipset is i440BX aka the Compatibility King.
o I've never had *any* problems with 6.2.8.
Full ahc boot-up messages follow:
PCI: Found IRQ 11 for device 00:10.0
aic7xxx: PCI Device 0:16:0 failed memory mapped test. Using PIO.
PCI: Found IRQ 10 for device 00:11.0
aic7xxx: PCI Device 0:17:0 failed memory mapped test. Using PIO.
scsi0 : Adaptec AIC7XXX EISA/VLB/PCI SCSI HBA DRIVER, Rev 6.2.25
<Adaptec 2940 Ultra SCSI adapter>
aic7880: Ultra Single Channel A, SCSI Id=7, 16/253 SCBs
scsi1 : Adaptec AIC7XXX EISA/VLB/PCI SCSI HBA DRIVER, Rev 6.2.25
<Adaptec 2940 Ultra SCSI adapter>
aic7880: Ultra Single Channel A, SCSI Id=7, 16/253 SCBs
(scsi1:A:4): 20.000MB/s transfers (20.000MHz, offset 15)
(scsi0:A:3): 20.000MB/s transfers (20.000MHz, offset 15)
Vendor: SEAGATE Model: ST39173N Rev: 6244
Type: Direct-Access ANSI SCSI revision: 02
scsi0:A:3:0: Tagged Queuing enabled. Depth 253
Vendor: SEAGATE Model: ST39173N Rev: 6244
Type: Direct-Access ANSI SCSI revision: 02
scsi1:A:4:0: Tagged Queuing enabled. Depth 253
Attached scsi disk sda at scsi0, channel 0, id 3, lun 0
Attached scsi disk sdb at scsi1, channel 0, id 4, lun 0
...
--
Tomas Szepe <szepe@pinerecords.com>
^ permalink raw reply
* Re: long stalls
From: Brian Tinsley @ 2003-01-08 2:48 UTC (permalink / raw)
To: Brian Gerst; +Cc: linux-kernel
In-Reply-To: <3E1B907F.60008@didntduck.org>
Thanks for the reply!
I thought highmem I/O was addressed in 2.4.20? Am I off-base here?
I actually just built a 2.4.20 kernel with highmem debugging turned on.
We'll see if anything pops up.
Brian Gerst wrote:
> Brian Tinsley wrote:
>
>> We have been having terrible problems with long stalls, meaning from a
>> couple of minutes to an hour, happening when filesystem I/O load gets
>> high. The system time as reported by vmstat or sar will increase up to
>> 99% and as it spreads to each procesor, the system becomes completely
>> unresponsive (except that it responds to pings just fine -
>> interesting!). When the system finally returns to the world of the
>> living, the only evidence that something bad has happened is the runtime
>> for kswapd is abnormally high. I have seen this happen with the stock
>> 2.4.17, 2.4.19, and 2.4.20 kernels on SMP PIII and PIV machines (either
>> 4GB or 8GB RAM, all SCSI disks, dual GigE NICs). I've searched the lkml
>> archives and google and have found several similar postings, but there
>> is never an explanation or resolution. Any help would be *very* much
>> appreciated! If any info from the system in question is desired, I will
>> be glad to provide it.
>>
>>
>>
> With 4GB of memory you are likely boucing I/O requests to low memory.
> This has been fixed in 2.5. I do not know if a backport exists for 2.4.
>
> --
> Brian Gerst
--
-[========================]-
-[ Brian Tinsley ]-
-[ Chief Systems Engineer ]-
-[ Emageon ]-
-[========================]-
^ permalink raw reply
* Re: long stalls
From: Brian Gerst @ 2003-01-08 2:44 UTC (permalink / raw)
To: Brian Tinsley; +Cc: linux-kernel
In-Reply-To: <3E1B73F3.2070604@emageon.com>
Brian Tinsley wrote:
> We have been having terrible problems with long stalls, meaning from a
> couple of minutes to an hour, happening when filesystem I/O load gets
> high. The system time as reported by vmstat or sar will increase up to
> 99% and as it spreads to each procesor, the system becomes completely
> unresponsive (except that it responds to pings just fine -
> interesting!). When the system finally returns to the world of the
> living, the only evidence that something bad has happened is the runtime
> for kswapd is abnormally high. I have seen this happen with the stock
> 2.4.17, 2.4.19, and 2.4.20 kernels on SMP PIII and PIV machines (either
> 4GB or 8GB RAM, all SCSI disks, dual GigE NICs). I've searched the lkml
> archives and google and have found several similar postings, but there
> is never an explanation or resolution. Any help would be *very* much
> appreciated! If any info from the system in question is desired, I will
> be glad to provide it.
>
>
>
With 4GB of memory you are likely boucing I/O requests to low memory.
This has been fixed in 2.5. I do not know if a backport exists for 2.4.
--
Brian Gerst
^ permalink raw reply
* Re: [PATCH] Set TIF_IRET in more places
From: Linus Torvalds @ 2003-01-08 2:33 UTC (permalink / raw)
To: Richard Henderson; +Cc: Zack Weinberg, Jamie Lokier, linux-kernel
In-Reply-To: <20030107172128.A9592@twiddle.net>
On Tue, 7 Jan 2003, Richard Henderson wrote:
> > We're open to better ideas ...
>
> Something like having dwarf2 unwind information for the
> vsyscall page on the page as well?
What would the unwind info look like? The current BK kernel will put the
signal return into the vsyscall page, so gdb could pick up the info from
there. But I have no idea what the unwind info looks like, or how to tell
gdb about it.
Linus
^ permalink raw reply
* Re: Question for Marcelo
From: Samuel Flory @ 2003-01-08 2:34 UTC (permalink / raw)
To: Walt H; +Cc: linux-kernel
In-Reply-To: <3E1AFA70.4070200@mindspring.com>
Walt H wrote:
> Hi Marcelo,
>
> I was just wondering if support for the Adaptec 79xx had been added to
> 2.4.21-pre? I have a server with the dual channel 7902 support on
> board, that so far appears to be working OK. It's using 2.4.20 with
> the driver patched in from Adaptec's site. I found an earlier mail
> from you stating that it would be added during the 2.4.20-pre cycle.
> Are there problems with the driver I should be aware of? Thanks,
>
> -Walt
>
> PS. Please CC me in any replies, as I'm not subscribed to the list.
> Thanks.
I believe that he would prefer that it get tested in the ac tree 1st.
Alan seemed receptive to including it, but he's not doing much with the
2.4 ac kernel any more.
http://marc.theaimsgroup.com/?l=linux-kernel&m=104106449418263&w=2
PS- All you really need to do to update the driver is delete
drivers/scsi/aic7xxx, and replace it with the newer driver from Gibbs
site. Recompile and you are done.
http://people.freebsd.org/~gibbs/linux/SRC/
aic79xx-linux-2.4-20021230-tar.gz
--
There is no such thing as obsolete hardware.
Merely hardware that other people don't want.
(The Second Rule of Hardware Acquisition)
Sam Flory <sflory@rackable.com>
^ permalink raw reply
* Re: Nvidia and its choice to read the GPL "differently"
From: Miles Bader @ 2003-01-08 2:29 UTC (permalink / raw)
To: dpaun; +Cc: rms, lm, acahalan, linux-kernel
In-Reply-To: <200301071118.41059.dpaun@rogers.com>
"Dimitrie O. Paun" <dpaun@rogers.com> writes:
> I know you have a very strong sentimental attachment to GNU,
> and that's more than understandable. But in the great scheme of things,
> it's a minor issue. As much as you like them to, people don't attach
> semantics to names. Period. They just want a catchy label, and that's all.
I think you're quite wrong -- names are very important, much more so
than it may seem at first.
If someone's mom (having heard the gossip) asks their computer-literate
child, `What is this XXX thing, anyway?', the answer is likely to be
very different when XXX is "GNU" as opposed to when XXX is "Linux".
The reason is that GNU _starts_ with freedom as an idea, and builds
software on top of that; it's very hard to explain GNU without explaining
freedom too. Most people that associate themself with the `Linux'
movement, OTOH, seem to start with `look at all the cool stuff it does;'
the freedom part, even for those that care about it, seems to remain on
the periphery (I hope I don't piss anyone off with this characterization,
this is just what I've observed!).
Which approach is the right one obviously depends on your priorities, but
it's pretty clear to me that these respective groups of people _do_
associate themselves with the names. I think that's one reason Richard's
attempts to get people to use GNU/linux have met with such strong
resistance (yeah, I know it's not the _only_ reason).
Perhaps, if everyone starting using `GNU/linux,' it would actually
_dilute_ the meaning of GNU, since many people that had no idea about what
GNU means would suddenly start using it just because someone told them the
name had changed from Linux. None-the-less, I think it would have some
of the opposite effect too, making people that previously never thought
about it wonder `what's this GNU?'
On a slight tangent: I bought an electronic english/japanese dictionary
about 8 years ago, and it happened to have a definition of GNU in it,
complete with a short (and I think accurate) description of free software!
Recently I bought a new dictionary; it doesn't define GNU, but it does
contain a definition of `Linux' -- and the summary is `a competitor to
windows'! It then goes into further detail saying it's `freeware'
(free-beer free), and worked on cooperatively by its users, but no
mention of `freedom' as such; it's clear the dicionary makers were just a
bit confused, but I wonder if they'd have gotten it right if the name
contained `GNU', with its strong associations with freedom...
-Miles
--
The secret to creativity is knowing how to hide your sources.
--Albert Einstein
^ permalink raw reply
* [PATCH 2.4] DHCP-client-related options in Configure.help
From: Neale Banks @ 2003-01-08 2:23 UTC (permalink / raw)
To: linux-kernel, Marcelo Tosatti
In-Reply-To: <Pine.LNX.4.05.10301081312150.2087-100000@marina.lowendale.com.au>
Appended patch against 2.4.21-pre2 updates
Documentation/Configure.help re options which are required to support
DHCP client.
Thanks,
Neale.
--- linux-2.4.21-pre2/Documentation/Configure.help Wed Jan 8 12:02:26 2003
+++ linux-2.4.21-pre2-ntb/Documentation/Configure.help Wed Jan 8 12:08:33 2003
@@ -2446,7 +2446,9 @@
information.
You need to say Y here if you want to use PPP packet filtering
- (see the CONFIG_PPP_FILTER option below).
+ (see the CONFIG_PPP_FILTER option below) or if the host may be using
+ DHCP to configure its own address (the DHCP client requires this and
+ 'Packet socket').
If unsure, say N.
@@ -6382,6 +6384,9 @@
directly with network devices without an intermediate network
protocol implemented in the kernel, e.g. tcpdump. If you want them
to work, choose Y.
+
+ Note that DHCP client requires this and 'Socket filtering', so if
+ you want DHCP client to work, choose Y.
This driver is also available as a module called af_packet.o ( =
code which can be inserted in and removed from the running kernel
^ permalink raw reply
* [PATCH 2.2] DHCP-client-related options in Configure.help
From: Neale Banks @ 2003-01-08 2:20 UTC (permalink / raw)
To: linux-kernel, Alan Cox
In-Reply-To: <Pine.LNX.4.05.10301081312150.2087-100000@marina.lowendale.com.au>
Appended patch against 2.2.24-rc1 updates Documentation/Configure.help
re options which are required to support DHCP client.
Thanks,
Neale.
--- linux-2.2.24-rc1/Documentation/Configure.help Sat Nov 30 05:05:55 2002
+++ linux-2.2.24-rc1-ntb0/Documentation/Configure.help Sat Dec 21 19:02:23 2002
@@ -1364,7 +1364,9 @@
certain types of data to get through the socket. Linux Socket
Filtering works on all socket types except TCP for now. See the text
file linux/Documentation/networking/filter.txt for more information.
- If unsure, say N.
+ If unsure, say N unless the host may be using DHCP to configure its
+ own address (the DHCP client requires this and 'Packet socket') - in
+ that case say Y.
Network firewalls
CONFIG_FIREWALL
@@ -4152,6 +4154,7 @@
module, say M here and read Documentation/modules.txt. You will
need to add 'alias net-pf-17 af_packet' to your /etc/conf.modules
file for the module version to function automatically. If unsure, say Y.
+ Note that DHCP client requires this and 'Socket filtering'.
Kernel/User network link driver
CONFIG_NETLINK
^ permalink raw reply
* DHCP-client-related options in Configure.help
From: Neale Banks @ 2003-01-08 2:14 UTC (permalink / raw)
To: linux-kernel
Separate patches to follow explicitly note that each of the two options
'Socket filtering' and 'Packet socket' are required for DHCP client.
Yep, I found out the hard way - build a kernel without these two and
DHCP client doesn't work at all. Given the prevalance of DHCP, IMHO
it isn't reasonable to remain silent about DHCP's dependence on these
two options and counsel "if unsure, say N" (albeit in only one of the
above cases).
Patches for 2.2 and 2.4 will follow separately. I'll also check 2.5.
Neale.
^ permalink raw reply
* Re: long stalls
From: Brian Tinsley @ 2003-01-08 2:16 UTC (permalink / raw)
To: Russell Leighton; +Cc: linux-kernel
In-Reply-To: <3E1B8439.8040209@elegant-software.com>
Out of curiosity, which RH kernel are you using? I moved on to 2.4.19
and 2.4.20 primarily because the RH 2.4.18 series of kernels apparently
has a scheduler bug (at least one) that causes the heartbeat software
from Linux-HA to loose heartbeat signals and failover. Not a good
scenario when you are trying to provide HA systems to hospitals!
Russell Leighton wrote:
>
> I can't help, but I can echo a "me too".
>
> We only see it when I have 2 file I/O intensive processes...they both
> will just stop for some few seconds, system seems idle...then
> they just start again. RH7.3 SMP, Dual PIII, 4GB RAM, 3com RAID
> Controller .
>
> Brian Tinsley wrote:
>
>> We have been having terrible problems with long stalls, meaning from
>> a couple of minutes to an hour, happening when filesystem I/O load
>> gets high. The system time as reported by vmstat or sar will increase
>> up to 99% and as it spreads to each procesor, the system becomes
>> completely unresponsive (except that it responds to pings just fine -
>> interesting!). When the system finally returns to the world of the
>> living, the only evidence that something bad has happened is the
>> runtime for kswapd is abnormally high. I have seen this happen with
>> the stock 2.4.17, 2.4.19, and 2.4.20 kernels on SMP PIII and PIV
>> machines (either 4GB or 8GB RAM, all SCSI disks, dual GigE NICs).
>> I've searched the lkml archives and google and have found several
>> similar postings, but there is never an explanation or resolution.
>> Any help would be *very* much appreciated! If any info from the
>> system in question is desired, I will be glad to provide it.
>>
>>
>>
>
--
-[========================]-
-[ Brian Tinsley ]-
-[ Chief Systems Engineer ]-
-[ Emageon ]-
-[========================]-
^ permalink raw reply
* Re: Playing Surround Sound with Alsa Drivers
From: Miguel Pastor @ 2003-01-08 2:07 UTC (permalink / raw)
To: Takashi Iwai; +Cc: Benny Sjostrand, Alsa Dev Mail List
In-Reply-To: <s5hvg119t82.wl@alsa2.suse.de>
Yes I was able to play surround sound for first time. Very exciting.
Thank you for the good work pushing the penguin army to a more enjoyable
experience with Linux.
Sincerely,
Miguel
On Tue, 2003-01-07 at 01:58, Takashi Iwai wrote:
At Thu, 02 Jan 2003 10:40:56 +0100,
Benny Sjostrand wrote:
>
> >
> >
> >Actually the drive that I use to send sound to the rears speakers is
> >"h:0,1" not "h:1,0". That's because the rear speakers controller is just
> >a subdevice of my first and only sound card. That works with no problems
> >sending sound only to the rear speakers but not to the four speakers.
> >I'm looking for a way to create surround sound using the four speakers.
> >There must be a way. Help please!
> >
> >
> >
> Oops! sorry for my misstake, I mean hw:0,0 -> front speakers and
> hw:0,1-> rear speakers (assuming that you got only one soundcard
> installed). In such way it's possible to control each speaker
> independently, programs like xine can take advantage of this.
>
> Then, whatever you want to do is just a software issue. It's not
> possible to send the same output to front and rear just via a simple
> "aplay ...", maybe it's possible to do magic via the .asoundrc stuff
> crearting a virtual device, but I dont know how to do that.
the latest alsa-lib cvs tree already includes the definition for
cs46xx. you'll be able to play a 4-channel wav file like
% aplay -Dsurround40 4channels.wav
Takashi
-------------------------------------------------------
This SF.NET email is sponsored by:
SourceForge Enterprise Edition + IBM + LinuxWorld = Something 2 See!
http://www.vasoftware.com
^ permalink raw reply
* Re: 2.5.54: ide-scsi still buggy?
From: Zwane Mwaikambo @ 2003-01-08 2:17 UTC (permalink / raw)
To: Lukas Hejtmanek; +Cc: linux-kernel
In-Reply-To: <20030108014005.GC725@mail.muni.cz>
On Wed, 8 Jan 2003, Lukas Hejtmanek wrote:
> Hello,
>
> ide-scsi emulation does not work for drive /dev/hdg, why?
>
> kernel boot parameters:
> kernel /boot/vmlinuz-2.5.54bk3 ro root=/dev/hda1 ide=reverse vga=4 hdg=ide-scsi
>
> It freezes kernel (sysrq do nothing) after lines:
> scsi0 : SCSI host adapter emulation for IDE ATAPI devices
> Vendor: TEAC Model: CD-W512EB Rev: 2
> Type: CD-ROM ANSI SCSI revision: 02
> scsi scan: host 0 channel 0 id 0 lun 0 identifier too long, length 60, max 50. Device might be improperly identified.
>
> while attaching it to /dev/hde works ok. Why?
This has been observed to cause an oops on some boxes and nothing on mine,
try this patch from Andries
diff -u --recursive --new-file -X /linux/dontdiff a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c
--- a/drivers/scsi/scsi_scan.c Wed Jan 1 23:54:23 2003
+++ b/drivers/scsi/scsi_scan.c Sun Jan 5 14:22:21 2003
@@ -544,32 +544,6 @@
}
/**
- * scsi_check_id_size - check if size fits in the driverfs name
- * @sdev: Scsi_Device to use for error message
- * @size: the length of the id we want to store
- *
- * Description:
- * Use a function for this since the same code is used in various
- * places, and we only create one string and call to printk.
- *
- * Return:
- * 0 - fits
- * 1 - size too large
- **/
-static int scsi_check_id_size(Scsi_Device *sdev, int size)
-{
- if (size > DEVICE_NAME_SIZE) {
- printk(KERN_WARNING "scsi scan: host %d channel %d id %d lun %d"
- " identifier too long, length %d, max %d. Device might"
- " be improperly identified.\n", sdev->host->host_no,
- sdev->channel, sdev->id, sdev->lun, size,
- DEVICE_NAME_SIZE);
- return 1;
- } else
- return 0;
-}
-
-/**
* scsi_get_evpd_page - get a list of supported vpd pages
* @sdev: Scsi_Device to send an INQUIRY VPD
* @sreq: Scsi_Request associated with @sdev
@@ -715,17 +689,16 @@
* scsi_check_fill_deviceid - check the id and if OK fill it
* @sdev: device to use for error messages
* @id_page: id descriptor for INQUIRY VPD DEVICE ID, page 0x83
- * @name: store the id in name
+ * @name: store the id in name (of size DEVICE_NAME_SIZE > 26)
* @id_search: store if the id_page matches these values
*
* Description:
* Check if @id_page matches the @id_search, if so store an id (uid)
- * into name.
+ * into name, that is all zero on entrance.
*
* Return:
* 0: Success
* 1: No match
- * 2: Failure due to size constraints
**/
static int scsi_check_fill_deviceid(Scsi_Device *sdev, char *id_page,
char *name, const struct scsi_id_search_values *id_search)
@@ -755,70 +728,41 @@
if ((id_page[0] & 0x0f) != id_search->code_set)
return 1;
- name[0] = hex_str[id_search->id_type];
+ /*
+ * All OK - store ID
+ */
+ name[0] = hex_str[id_search->id_type];
+
+ /*
+ * Prepend the vendor and model before the id, since the id
+ * might not be unique across all vendors and models.
+ * The same code is used below, with a different size.
+ */
+ if (id_search->id_type == SCSI_ID_VENDOR_SPECIFIC) {
+ strncat(name, sdev->vendor, 8);
+ strncat(name, sdev->model, 16);
+ }
+
+ i = 4;
+ j = strlen(name);
if ((id_page[0] & 0x0f) == SCSI_ID_ASCII) {
/*
* ASCII descriptor.
*/
- if (id_search->id_type == SCSI_ID_VENDOR_SPECIFIC) {
- /*
- * Prepend the vendor and model before the id,
- * since the id might not be unique across all
- * vendors and models. The same code is used
- * below, with a differnt size.
- *
- * Need 1 byte for the idtype, 1 for trailing
- * '\0', 8 for vendor, 16 for model total 26, plus
- * the name descriptor length.
- */
- if (scsi_check_id_size(sdev, 26 + id_page[3]))
- return 2;
- else {
- strncat(name, sdev->vendor, 8);
- strncat(name, sdev->model, 16);
- }
- } else if (scsi_check_id_size (sdev, (2 + id_page[3])))
- /*
- * Need 1 byte for the idtype, 1 byte for
- * the trailing '\0', plus the descriptor length.
- */
- return 2;
- memcpy(&name[strlen(name)], &id_page[4], id_page[3]);
- return 0;
- } else if ((id_page[0] & 0x0f) == SCSI_ID_BINARY) {
- if (id_search->id_type == SCSI_ID_VENDOR_SPECIFIC) {
- /*
- * Prepend the vendor and model before the id.
- */
- if (scsi_check_id_size(sdev, 26 + (id_page[3] * 2)))
- return 2;
- else {
- strncat(name, sdev->vendor, 8);
- strncat(name, sdev->model, 16);
- }
- } else if (scsi_check_id_size(sdev, 2 + (id_page[3] * 2)))
- /*
- * Need 1 byte for the idtype, 1 for trailing
- * '\0', 8 for vendor, 16 for model total 26, plus
- * the name descriptor length.
- */
- return 2;
+ while (i < 4 + id_page[3] && j < DEVICE_NAME_SIZE-1)
+ name[j++] = id_page[i++];
+ } else {
/*
* Binary descriptor, convert to ASCII, using two bytes of
- * ASCII for each byte in the id_page. Store starting at
- * the end of name.
+ * ASCII for each byte in the id_page.
*/
- for(i = 4, j = strlen(name); i < 4 + id_page[3]; i++) {
+ while (i < 4 + id_page[3] && j < DEVICE_NAME_SIZE-2) {
name[j++] = hex_str[(id_page[i] & 0xf0) >> 4];
name[j++] = hex_str[id_page[i] & 0x0f];
+ i++;
}
- return 0;
}
- /*
- * Code set must have already matched.
- */
- printk(KERN_ERR "scsi scan: scsi_check_fill_deviceid unexpected state.\n");
- return 1;
+ return 0;
}
/**
@@ -834,7 +778,7 @@
* 0: Failure
* 1: Success
**/
-int scsi_get_deviceid(Scsi_Device *sdev, Scsi_Request *sreq)
+static int scsi_get_deviceid(Scsi_Device *sdev, Scsi_Request *sreq)
{
unsigned char *id_page;
unsigned char scsi_cmd[MAX_COMMAND_SIZE];
@@ -879,14 +823,14 @@
}
/*
- * Search for a match in the proiritized id_search_list.
+ * Search for a match in the prioritized id_search_list.
*/
for (id_idx = 0; id_idx < ARRAY_SIZE(id_search_list); id_idx++) {
/*
* Examine each descriptor returned. There is normally only
* one or a small number of descriptors.
*/
- for(scnt = 4; scnt <= id_page[3] + 3;
+ for (scnt = 4; scnt <= id_page[3] + 3;
scnt += id_page[scnt + 3] + 4) {
if ((scsi_check_fill_deviceid(sdev, &id_page[scnt],
sdev->sdev_driverfs_dev.name,
@@ -941,12 +885,11 @@
{
unsigned char *serialnumber_page;
unsigned char scsi_cmd[MAX_COMMAND_SIZE];
- int max_lgth = 255;
+ const int max_lgth = 255;
+ int len;
- retry:
serialnumber_page = kmalloc(max_lgth, GFP_ATOMIC |
- (sdev->host->unchecked_isa_dma) ?
- GFP_DMA : 0);
+ (sdev->host->unchecked_isa_dma) ? GFP_DMA : 0);
if (!serialnumber_page) {
printk(KERN_WARNING "scsi scan: Allocation failure identifying"
" host %d channel %d id %d lun %d, device might be"
@@ -969,26 +912,19 @@
if (sreq->sr_result)
goto leave;
- /*
- * check to see if response was truncated
- */
- if (serialnumber_page[3] > max_lgth) {
- max_lgth = serialnumber_page[3] + 4;
- kfree(serialnumber_page);
- goto retry;
- }
/*
- * Need 1 byte for SCSI_UID_SER_NUM, 1 for trailing '\0', 8 for
- * vendor, 16 for model = 26, plus serial number size.
+ * a check to see if response was truncated is superfluous,
+ * since serialnumber_page[3] cannot be larger than 255
*/
- if (scsi_check_id_size (sdev, (26 + serialnumber_page[3])))
- goto leave;
+
sdev->sdev_driverfs_dev.name[0] = SCSI_UID_SER_NUM;
strncat(sdev->sdev_driverfs_dev.name, sdev->vendor, 8);
strncat(sdev->sdev_driverfs_dev.name, sdev->model, 16);
- strncat(sdev->sdev_driverfs_dev.name, &serialnumber_page[4],
- serialnumber_page[3]);
+ len = serialnumber_page[3];
+ if (len > DEVICE_NAME_SIZE-26)
+ len = DEVICE_NAME_SIZE-26;
+ strncat(sdev->sdev_driverfs_dev.name, &serialnumber_page[4], len);
kfree(serialnumber_page);
return 1;
leave:
@@ -1002,23 +938,19 @@
* @sdev: get a default name for this device
*
* Description:
- * Set the name of @sdev to the concatenation of the vendor, model,
- * and revision found in @sdev.
+ * Set the name of @sdev (of size DEVICE_NAME_SIZE > 29) to the
+ * concatenation of the vendor, model, and revision found in @sdev.
*
* Return:
* 1: Success
**/
int scsi_get_default_name(Scsi_Device *sdev)
{
- if (scsi_check_id_size(sdev, 29))
- return 0;
- else {
- sdev->sdev_driverfs_dev.name[0] = SCSI_UID_UNKNOWN;
- strncpy(&sdev->sdev_driverfs_dev.name[1], sdev->vendor, 8);
- strncat(sdev->sdev_driverfs_dev.name, sdev->model, 16);
- strncat(sdev->sdev_driverfs_dev.name, sdev->rev, 4);
- return 1;
- }
+ sdev->sdev_driverfs_dev.name[0] = SCSI_UID_UNKNOWN;
+ strncpy(&sdev->sdev_driverfs_dev.name[1], sdev->vendor, 8);
+ strncat(sdev->sdev_driverfs_dev.name, sdev->model, 16);
+ strncat(sdev->sdev_driverfs_dev.name, sdev->rev, 4);
+ return 1;
}
/**
--
function.linuxpower.ca
^ permalink raw reply
* Getting interface IP addresses with proc filesystem
From: Burton Samograd @ 2003-01-08 2:06 UTC (permalink / raw)
To: linux-kernel
[-- Attachment #1: Type: text/plain, Size: 934 bytes --]
Hi all,
I'm curious how one goes about getting the current IP addresses held by a
machine. I saw some rather convoluted code in qmail that shows how to do it but
it seems like a rather difficult (and future bug ridden if the interface
changes) piece of code and was thinking that a /proc/net interface would be the
easiest solution, at least on the end user side.
My thinking goes along the lines of adding a file in /proc/net called interfaces
(or something more appropriate) which gives the following type of listing:
eth0 12.35.23.58
eth0:0 192.168.0.1
lo 127.0.0.1
ppp0 45.3.3.89
etc
for each of the registered interfaces on the machine. Nice, simple and
shouldn't be too hard to implement, correct? Is this type of information
already present through some other mechanism that I haven't found yet?
Thanks in advance.
--
burton samograd
kruhft@kruhft.dyndns.org
http://kruhftwerk.dyndns.org
[-- Attachment #2: Type: application/pgp-signature, Size: 189 bytes --]
^ permalink raw reply
* Re: 3CR990 question (Nearly unrelated to iSCSI)
From: Jeff Garzik @ 2003-01-08 2:00 UTC (permalink / raw)
To: nick; +Cc: linux-kernel
In-Reply-To: <Pine.LNX.4.21.0301071956200.8546-100000@ns.snowman.net>
On Tue, Jan 07, 2003 at 07:56:37PM -0500, nick@snowman.net wrote:
> On Wed, 8 Jan 2003, Andrew McGregor wrote:
> > > AH permits multiple digests, they also happen to correspond to the
> > > hardware accelerated ones on things like the 3c990...
> Speaking of which, did this driver which was mentioned ever occur?
Two did, actually :)
I hope we will see it appear in a kernel RSN
^ permalink raw reply
* Re: [2.5.54-dj1-bk] Some interesting experiences...
From: dhinds @ 2003-01-08 1:58 UTC (permalink / raw)
To: Joshua Kwan; +Cc: linux-kernel
In-Reply-To: <20030107172147.3c53efa8.joshk@ludicrus.ath.cx>
On Tue, Jan 07, 2003 at 05:21:46PM -0800, Joshua Kwan wrote:
> 2. [linux-2.5] pcmcia-cs 3.2.3 will no longer build: here is the build
> log, pertinent details only.
>
> cc -MD -O3 -Wall -Wstrict-prototypes -pipe -Wa,--no-warn
> -I../include/static -I/usr/src/linux-2.5/include -I../include
> -I../modules -c cardmgr.c
> In file included from cardmgr.c:200:
> /usr/src/linux-2.5/include/scsi/scsi.h:185: parse error before "u8"
This should be fixed in the current beta for 3.2.4 available from
http://pcmcia-cs.sourceforge.net/ftp/NEW.
-- Dave
^ permalink raw reply
* Re: [PATCH] PCI hotplug changes for 2.5.54
From: Greg KH @ 2003-01-08 1:58 UTC (permalink / raw)
To: linux-kernel, pcihpd-discuss
In-Reply-To: <20030108015714.GC30924@kroah.com>
ChangeSet 1.896, 2003/01/07 16:41:22-08:00, greg@kroah.com
PCI hotplug: clean up the try_module_get() logic a bit.
diff -Nru a/drivers/hotplug/pci_hotplug_core.c b/drivers/hotplug/pci_hotplug_core.c
--- a/drivers/hotplug/pci_hotplug_core.c Tue Jan 7 16:44:10 2003
+++ b/drivers/hotplug/pci_hotplug_core.c Tue Jan 7 16:44:10 2003
@@ -561,7 +561,7 @@
up(&parent->d_inode->i_sem);
}
-/* yuck, WFT is this? */
+/* Weee, fun with macros... */
#define GET_STATUS(name,type) \
static int get_##name (struct hotplug_slot *slot, type *value) \
{ \
@@ -661,29 +661,26 @@
power = (u8)(lpower & 0xff);
dbg ("power = %d\n", power);
+ if (!try_module_get(slot->ops->owner)) {
+ retval = -ENODEV;
+ goto exit;
+ }
switch (power) {
case 0:
- if (!slot->ops->disable_slot)
- break;
- if (try_module_get(slot->ops->owner)) {
+ if (slot->ops->disable_slot)
retval = slot->ops->disable_slot(slot);
- module_put(slot->ops->owner);
- }
break;
case 1:
- if (!slot->ops->enable_slot)
- break;
- if (try_module_get(slot->ops->owner)) {
+ if (slot->ops->enable_slot)
retval = slot->ops->enable_slot(slot);
- module_put(slot->ops->owner);
- }
break;
default:
err ("Illegal value specified for power\n");
retval = -EINVAL;
}
+ module_put(slot->ops->owner);
exit:
kfree (buff);
@@ -770,12 +767,13 @@
attention = (u8)(lattention & 0xff);
dbg (" - attention = %d\n", attention);
- if (slot->ops->set_attention_status) {
- if (try_module_get(slot->ops->owner)) {
- retval = slot->ops->set_attention_status(slot, attention);
- module_put(slot->ops->owner);
- }
+ if (!try_module_get(slot->ops->owner)) {
+ retval = -ENODEV;
+ goto exit;
}
+ if (slot->ops->set_attention_status)
+ retval = slot->ops->set_attention_status(slot, attention);
+ module_put(slot->ops->owner);
exit:
kfree (buff);
@@ -1007,12 +1005,13 @@
test = (u32)(ltest & 0xffffffff);
dbg ("test = %d\n", test);
- if (slot->ops->hardware_test) {
- if (try_module_get(slot->ops->owner)) {
- retval = slot->ops->hardware_test(slot, test);
- module_put(slot->ops->owner);
- }
+ if (!try_module_get(slot->ops->owner)) {
+ retval = -ENODEV;
+ goto exit;
}
+ if (slot->ops->hardware_test)
+ retval = slot->ops->hardware_test(slot, test);
+ module_put(slot->ops->owner);
exit:
kfree (buff);
^ permalink raw reply
* Re: long stalls
From: Russell Leighton @ 2003-01-08 1:51 UTC (permalink / raw)
To: Brian Tinsley; +Cc: linux-kernel
In-Reply-To: <3E1B73F3.2070604@emageon.com>
I can't help, but I can echo a "me too".
We only see it when I have 2 file I/O intensive processes...they both
will just stop for some few seconds, system seems idle...then
they just start again. RH7.3 SMP, Dual PIII, 4GB RAM, 3com RAID Controller .
Brian Tinsley wrote:
> We have been having terrible problems with long stalls, meaning from a
> couple of minutes to an hour, happening when filesystem I/O load gets
> high. The system time as reported by vmstat or sar will increase up to
> 99% and as it spreads to each procesor, the system becomes completely
> unresponsive (except that it responds to pings just fine -
> interesting!). When the system finally returns to the world of the
> living, the only evidence that something bad has happened is the
> runtime for kswapd is abnormally high. I have seen this happen with
> the stock 2.4.17, 2.4.19, and 2.4.20 kernels on SMP PIII and PIV
> machines (either 4GB or 8GB RAM, all SCSI disks, dual GigE NICs). I've
> searched the lkml archives and google and have found several similar
> postings, but there is never an explanation or resolution. Any help
> would be *very* much appreciated! If any info from the system in
> question is desired, I will be glad to provide it.
>
>
>
^ permalink raw reply
* Re: [PATCH] PCI hotplug changes for 2.5.54
From: Greg KH @ 2003-01-08 1:57 UTC (permalink / raw)
To: linux-kernel, pcihpd-discuss
In-Reply-To: <20030108015551.GB30924@kroah.com>
ChangeSet 1.895, 2003/01/07 16:29:23-08:00, greg@kroah.com
PCI: properly unregister a PCI device if it is removed.
This is only used by pci hotplug and cardbus systems.
diff -Nru a/drivers/pci/hotplug.c b/drivers/pci/hotplug.c
--- a/drivers/pci/hotplug.c Tue Jan 7 16:44:43 2003
+++ b/drivers/pci/hotplug.c Tue Jan 7 16:44:43 2003
@@ -105,7 +105,7 @@
void
pci_remove_device(struct pci_dev *dev)
{
- put_device(&dev->dev);
+ device_unregister(&dev->dev);
list_del(&dev->bus_list);
list_del(&dev->global_list);
pci_free_resources(dev);
^ permalink raw reply
* [PATCH] PCI hotplug changes for 2.5.54
From: Greg KH @ 2003-01-08 1:55 UTC (permalink / raw)
To: linux-kernel, pcihpd-discuss
In-Reply-To: <20030108015500.GA30924@kroah.com>
ChangeSet 1.894, 2003/01/07 16:24:14-08:00, greg@kroah.com
IBM PCI Hotplug: fix compile time error due to find_bus() function name.
diff -Nru a/drivers/hotplug/ibmphp_core.c b/drivers/hotplug/ibmphp_core.c
--- a/drivers/hotplug/ibmphp_core.c Tue Jan 7 16:45:11 2003
+++ b/drivers/hotplug/ibmphp_core.c Tue Jan 7 16:45:11 2003
@@ -769,11 +769,11 @@
* Parameters: bus number
* Returns : pci_bus * or NULL if not found
*/
-static struct pci_bus *find_bus (u8 busno)
+static struct pci_bus *ibmphp_find_bus (u8 busno)
{
const struct list_head *tmp;
struct pci_bus *bus;
- debug ("inside find_bus, busno = %x \n", busno);
+ debug ("inside %s, busno = %x \n", __FUNCTION__, busno);
list_for_each (tmp, &pci_root_buses) {
bus = (struct pci_bus *) pci_bus_b (tmp);
@@ -1002,7 +1002,7 @@
struct pci_dev *dev;
u16 l;
- if (find_bus (busno) || !(ibmphp_find_same_bus_num (busno)))
+ if (ibmphp_find_bus (busno) || !(ibmphp_find_same_bus_num (busno)))
return 1;
bus = kmalloc (sizeof (*bus), GFP_KERNEL);
@@ -1056,7 +1056,7 @@
func->dev = pci_find_slot (func->busno, (func->device << 3) | (func->function & 0x7));
if (func->dev == NULL) {
- dev0.bus = find_bus (func->busno);
+ dev0.bus = ibmphp_find_bus (func->busno);
dev0.devfn = ((func->device << 3) + (func->function & 0x7));
dev0.sysdata = dev0.bus->sysdata;
@@ -1636,7 +1636,7 @@
return -ENOMEM;
}
- bus = find_bus (0);
+ bus = ibmphp_find_bus (0);
if (!bus) {
err ("Can't find the root pci bus, can not continue\n");
return -ENODEV;
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.